Lighthouseのバッチ実行と結果レポートをいい感じでやるためのパッケージを作りました
nightharborというパッケージを作りました。対象ページのリストを読み込み、ひたすらlighthouseを実行して、それらの結果をレポーティングためのものです。名前はlighthouse(灯台)が稼働してそうなとこ、という安直な感じでつけました。
lighthouseって???
本題の前に、lighthouseについて軽くお話しします。ご存知の方も多いかとおもいますが、Googleが提供しているサイトパフォーマンス計測ツールです。サイトパフォーマンスをスコア化して表示してくれるだけでなく、読み込むまでにどれくらい時間がかかったのか、ページ速度を遅くしている要因が何なのか、どうすれば改善できるのか、などいろいろ丁寧に教えてくれるステキツールです。Chromeの開発者ツールにある Audits
から使うことができます。ブラウザからの使い方は こちらなどをご覧いただければと思います。
本題
このlighthouseというツールですが、node.js上でも動きます。 今回作ったパッケージは、node.js上でlighthouseをバッチ実行するためのものです。
それなりの規模のWebサイトになってくると、パフォーマンスを調べたいページについて、手動でぽちぽちlighthouseを実行するのは結構な手間です。 加えて、「定期的にモニタリングしたい」とか「競合の計測もしたい」なんて要望もでてきたりしたら大変です。手動実行なんてしたくないですし、結果のファイルをどこかに手動アップロードしまくるなんてのも絶対にやりたくありません。
なので、やりたいこととしては、ざっくり以下のような感じです。
- 好きな場所から対象ページリストを読み込む
- 順番にlighthouseを実行する
- 好きな場所に好きな形式で出力する
1, 3を自由にカスタマイズできて、2は設定(lighthouse, puppeteer)が渡せるように作りました。図にするとこんな感じです。
基本的な使い方
基本的な使い方については、サンプルプロジェクトをcloneして実行していただくのが一番手っ取り早いかと思います。
$ git clone https://github.com/YoshiyukiKato/nightharbor-example.git $ cd nightharbor-example $ npm install $ npm start
https://google.com first-contentful-paint: 0.98 first-meaningful-paint: 0.98 speed-index: 0.99 screenshot-thumbnails: null final-screenshot: null estimated-input-latency: 0.82 time-to-first-byte: 1 first-cpu-idle: 0.87 interactive: 0.88 user-timings: null critical-request-chains: null redirects: 1 mainthread-work-breakdown: 0.75 bootup-time: 0.97 uses-rel-preload: 1 uses-rel-preconnect: 0.74 font-display: 1 network-requests: null metrics: null uses-long-cache-ttl: 1 total-byte-weight: 1 offscreen-images: 1 render-blocking-resources: 1 unminified-css: 1 unminified-javascript: 1 unused-css-rules: 1 uses-webp-images: 1 uses-optimized-images: 1 uses-text-compression: 1 uses-responsive-images: 1 efficient-animated-content: 1 dom-size: 1
こんな感じの実行結果がコンソールに出力されたでしょうか。
nhb.config.js
には、このプロジェクトの全ての設定が書いてあります。
const {SimpleLoader} = require("nightharbor/loader"); const {SimpleReporter} = require("nightharbor/reporter"); module.exports = { loaders: [ new SimpleLoader([ { url: "https://google.com" } ]) ], reporters: [ new SimpleReporter() ], //following params are optional //default params are shown as comment /* chromeNum: 1, puppeteerConfig: { headless: true }, lighthouseConfig: { extends: 'lighthouse:default', settings: { onlyCategories: ['performance'], } } */ }
nightharborでは、CLIからの実行とプログラム上での実行の二つを用意していますが、どちらもこのconfigを渡すだけでOKです。 CLIの場合はconfigファイルへのpathを
$ npm i -g nightharbor $ nhb --config ./path/to/config.js
プログラムからの場合は直接configオブジェクトをexec
メソッドに渡します。
import nhb from "nightharbor"; import config from "./path/to/config"; nhb.exec(config) .then(() => console.log("done")); .catch(console.error);
ここからは、nhb.config.js
の内容について説明をしていきます。
loaders
loaders
は、lighthouse実行対象リストを読み込むLoader
の配列です。SimpleLoader
は、組み込みのもっとも簡単なLoader
で、生の配列でlighthouseの実行対象を指定するためのものです。Loader
が扱う実行対象の情報には、url
というパラメータが含まれている必要があります。
{ "url": "https://google.com" }
いまのところ、組み込みのSimpleLoader
に加えて、僕自身が使うために作ったLoader
は以下の2つです。
loaders
には、Loader
のインタフェースを実装したクラスのインスタンスであれば、含めることができます。以下のような感じで独自のLoader
を作ることもできます。
class CustomLoader { /** * @return {Promise<{ url: string, [key: string]: any }[]>} */ load(){ //some asynchronous fetch tasks such as read file and api request. return Promise.resolve([ { url: "https://google.com" } ]); } }
load
メソッドがあればいいのでサクッと作れます。
なお、ここで読み込む対象ページの情報は、最終的にlighthouseの実行結果と結合されReporter
に渡されます。なので、url
以外にもレポートに含めたい情報を含めておくと便利かもしれません。
reporters
reporters
は、lighthouseの実行結果(audits)を任意の形で出力するReporter
の配列です。SimpleReporter
は、組み込みのもっとも簡単なReporter
で、コンソールにlighthouseの結果を出力します。
いまのところ、組み込みのSimpleReporter
に加えて、僕自身が使うために作ったReporter
は以下の三つです。
- nightharbor-file-reporter
- nightharbor-s3-reporter
- nightharbor-bigquery-reporter
- GCP BigQueryに結果をアップロードする
reporters
には、Reporter
のインタフェースを実装したクラスのインスタンスであれば、含めることができます。独自のReporter
を作ることもできます。
class CustomReporter{ /** * will be called when a lighthouse execution completed * @param {any} result * @return {void} */ write(result){ //do something } /** * will be called after all executions * @return {Promise} */ close(){ //do something } }
Reporter
には、一回のlighthouse実行後に結果が渡されるwrite
メソッドと、全ての対象ページへのlighthouse実行が終了した後に呼ばれるclose
メソッドを実装します。なお、現状write
メソッドに渡ってくる結果情報は、データサイズを抑えるため、各audit(例えば、speed-index
など)ごとscore
のみにしています(auditのインタフェースはこちらを見てください)。details
など他の情報も取りたいという要望ありましたらIssueください
chromeNum
puppeteerで起動するchromeの数です。対象ページが多い場合、一つのchromeで処理するのでは流石に時間がかかるので、何個も立ち上げて同時に処理を走らせることができます。ただし、数字を大きく設定する場合、マシンスペックを十分に確保した上で行う必要があります。
puppeteerConfig
puppeteerの設定です。詳しくはこちらをご覧ください。
lighthouseConfig
lighthouseの設定です。詳しくはこちらをご覧ください。
実際の使い方の例
僕自身は、S3から対象リストのCSVファイルを読み込ませるようにして、CloudWatch + AWS Batchで定期実行し、結果をS3とBigQueryに出力しています。 nightharborのアプリケーションはdocker imageにして、AWS ECRに上げています。
アプリケーションのimageはビルド後のサイズが気になるのでnodeのalpineベースで作ったのですが、lighthouseの公式docに従って進めても動かないという罠があって結構大変でした。AWS上での設定や実際に定期計測してみた話はまた別途記事にまとめようかと思いますが、とりあえずalpineベースのサンプルプロジェクトを作ったので、よかったらご活用ください。
まとめ
lighthouseをバッチ実行していい感じでレポーティングするためのパッケージ、nightharborをご紹介しました。 何かのお役に立てば幸いです。IssueもPRもお待ちしております(日本語でも英語でも大丈夫です)。