【テクニカル・上級編】【CI/CD連携】DevToolsでキャプチャしたLighthouseレポートを自動化する方法 – デバッグ・コード品質・テストツール生産性向上バイブル

「ブラウザのDevToolsを開いて、Lighthouseタブをポチポチとクリックしている。そんな光景をもし私のチームで見かけたら、即座にその作業を止めさせるだろう」

諸君、私はこれまで数多の巨大な分散システムと、秒間数万リクエストを捌くフロントエンド基盤のアーキテクチャを設計してきた。その経験から断言できるのは、「手動の計測は、計測ではない。ただの気休めだ」ということだ。

パフォーマンス計測を決定論的(Deterministic)なものとし、開発サイクルの不可逆なガードレールとして機能させるためには、Lighthouseをブラウザから引き剥がし、CI/CDパイプラインの深淵へと組み込まなければならない。

今回は、単なるCLIの叩き方ではなく、Headless Chromeの制御、Dockerコンテナ内でのリソース競合回避、そしてLighthouse CI(LHCI)を用いた「持続可能なパフォーマンス監視基盤」の構築について、その真髄を解説する。

—

1. Lighthouse CI (LHCI) のアーキテクチャ:なぜこれが必要なのか

Lighthouseの内部では、Chrome Remote Debugging Protocol (CDP) を介してブラウザを制御し、ページのロード、トレースの取得、そして監査(Audits)が実行される。

手動計測の最大の問題は、実行環境の「ノイズ」だ。開発者のマシンスペック、バックグラウンドで動くSlackやZoom、ネットワークの揺らぎ。これらが混入したレポートに価値はない。

LHCIをCIに組み込む真の目的は以下の3点にある:
1. 環境の正規化: 同一スペックのコンテナ環境で、ネットワークとCPUのスロットリングを厳密に適用する。
2. パフォーマンス・バジェットの強制: LCP(Largest Contentful Paint)が2.5秒を超えたらビルドを落とす、という「規律」を自動化する。
3. 時系列データの蓄積: 単発のスコアではなく、コミットごとの推移を可視化する。

—

2. 極限まで研ぎ澄まされた `.lighthouserc.js` の設計

JSONではなく、JavaScriptで設定を書く。これがプロの選択だ。環境変数に応じて動的に計測対象URLを切り替える柔軟性が必要だからだ。

// .lighthouserc.js – プロフェッショナル向けの高度な設定
module.exports = {
ci: {
collect: {
// 開発サーバの起動コマンド。静的サイトなら ‘npm run serve’ 等
startServerCommand: ‘npm run start’,
// 計測対象のURL。複数指定可能。
url: [‘http://localhost:3000/’],
// 統計的有意性を確保するため、最低3回は回すのが定石だ
numberOfRuns: 3,
settings: {
// Chromeの起動引数。コンテナ環境ではこれらが生命線となる
chromeFlags: [
‘–headless’,
‘–no-sandbox’,
‘–disable-dev-shm-usage’, // /dev/shmのメモリ不足によるクラッシュを回避
‘–disable-gpu’,
],
// モバイル環境をシミュレート。デスクトップなら ‘desktop’
emulatedFormFactor: ‘mobile’,
// ネットワークとCPUのスロットリング設定(重要:実世界のユーザーを想定せよ)
throttlingMethod: ‘simulate’,
throttling: {
rttMs: 40,
throughputKbps: 10240,
cpuSlowdownMultiplier: 4,
},
},
},
assert: {
// パフォーマンスの閾値を設定。ここで「妥協」は許されない
assertions: {
‘categories:performance’: [‘error’, { minScore: 0.9 }],
‘largest-contentful-paint’: [‘error’, { maxNumericValue: 2500 }],
‘total-blocking-time’: [‘error’, { maxNumericValue: 300 }],
// 外部の巨大なJSライブラリ混入を検知する
‘resource-summary:script:size’: [‘warn’, { maxNumericValue: 500000 }],
},
},
upload: {
// 計測結果の保存先。一時的な確認なら ‘temporary-public-storage’ で良いが、
// 組織で運用するなら独自の LHCI Server を立てるべきだ
target: ‘temporary-public-storage’,
},
},
};

—

3. Docker環境における「ゾンビプロセス」と「共有メモリ」の制約

CI環境(GitHub Actions, GitLab CI, Jenkins等)でLighthouseを動かす際、多くのエンジニアが「Chromeが突然死する」という壁にぶち当たる。

原因は2つ。共有メモリ(/dev/shm)の不足と、依存ライブラリの欠如だ。
Dockerコンテナ内でChromeを動かすための、究極のDockerfileの断片を提示しよう。

軽量なNodeイメージをベースにする
FROM node:18-slim

Chromeの実行に必要な最小限のライブラリ群をインストール
これを怠ると、CDPとの通信が確立できずにLighthouseは沈黙する
RUN apt-get update && apt-get install -y \
wget \
gnupg \
ca-certificates \
procps \
libnss3 \
libatk-bridge2.0-0 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
libgbm1 \
libasound2 \
libpangocairo-1.0-0 \
libxshmfence1 \
–no-install-recommends \
&& rm -rf /var/lib/apt/lists/

Lighthouse CI CLI をグローバルにインストール
RUN npm install -g @lhci/cli@0.12.x

実行ユーザーを非rootに変更(セキュリティの鉄則)
USER node
WORKDIR /app

実行時は必ず –no-sandbox を付与することを忘れるな
ENTRYPOINT [“lhci”, “autorun”]

—

4. GitHub Actionsへの高度な統合:自動コードレビュー

ただスコアを測るだけでは不十分だ。PR(プルリクエスト)に対して、パフォーマンス劣化が起きた際に「自動でコメントを叩き込む」仕組みを構築する。

name: Performance CI

on: [pull_request]

jobs:
lighthouse-check:
runs-on: ubuntu-latest
steps:

  • uses: actions/checkout@v3
  • name: Setup Node.js

uses: actions/setup-node@v3
with:
node-version: 18

  • name: Install Dependencies

run: npm ci

  • name: Run Lighthouse CI

run: |
# LHCI_GITHUB_APP_TOKEN を設定することで、PRのステータスチェックと連動させる
npm install -g @lhci/cli@0.12.x
lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}

ここで重要なのは、`LHCI_GITHUB_APP_TOKEN` だ。これを利用することで、GitHubのコミットステータスに「Lighthouseの合格・不合格」が直接表示されるようになる。レビュー担当者は、スコアを確認することなく、赤い×印がついているPRを却下すれば良い。

—

5. エキスパートが教える「計測のブレ」を抑えるハック

CI上での計測結果が安定しない(Flaky)という相談をよく受ける。その場合、以下の3つの「秘術」を試してほしい。

1. CPU Throttlingの固定化:
CI環境(仮想マシン)はホストの負荷によって性能が変動する。`throttlingMethod: ‘devtools’` を使用し、ネットワークエミュレーションをより厳密に行う。
2. Median Runの採用:
`numberOfRuns: 5` とし、その中央値(Median)を最終結果として採用するようにLHCI Server側で設定する。外れ値を排除するのは統計学の基本だ。
3. 待機処理のカスタマイズ:
SPA(Single Page Application)の場合、データのフェッチが完了する前に計測が終わってしまうことがある。`lighthouserc.js` 内で `pauseAfterLoadMs` を設定するか、特定のDOMが出現するまで待機するカスタムスクリプトを `gatherer` として注入せよ。

—

結言:パフォーマンスは「文化」である

LighthouseをCI/CDに組み込むことは、単なるツールの導入ではない。それは、「パフォーマンス劣化をバグと定義する」というチームの宣言である。

自動化されたレポートは、エンジニアの主観を排除し、数値という残酷な事実を突きつける。しかし、その事実こそが、ユーザーに最高の体験を届けるための唯一の道標となるのだ。

君のパイプラインに、今すぐこの「守護神」を組み込みたまえ。話はそれからだ。

タイトルとURLをコピーしました