📝 はじめに
私は日本語が得意ではないため、AI のサポートを受けてこの記事を作成しています。ご了承いただければ幸いです。
I'm not fluent in Japanese, so I used AI assistance to write this article. Thank you for your understanding.
目次
- Lighthouse とは?
- 6つの Web Vitals を理解する
- ☐ フォントの最適化
- ☐ スクリプトの制御
- ☐ スタイルの最適化
- ☐ バンドルの最適化
- ☐ CLS の防止
- ☐ 画像の最適化
- ☐ JavaScript の最適化
- ☐ パフォーマンスを維持する仕組み作り
- まとめ
1. Lighthouse とは?
Lighthouse は Google が提供するオープンソースの Web 品質チェックツールです。パフォーマンス、アクセシビリティ、SEO、PWA など複数の観点からページを評価し、スコアを算出します。
Next.js で開発する際、この Lighthouse スコアを高く保つことは、ユーザー体験の向上だけでなく、SEO ランキングやコンバージョン率にも直結します。本記事では、実務で積み重ねた経験をもとに、具体的なチェックリストとしてまとめました。
2. 6つの Web Vitals を理解する
Lighthouse のパフォーマンススコアは、以下の 6 つの指標(Web Vitals)に基づいて計算されます。それぞれの意味を把握しておくことが、最適化の第一歩です。
| 指標 | 説明 |
|---|---|
| FCP (First Contentful Paint) | 最初の要素が画面に描画されるまでの時間 |
| SI (Speed Index) | コンテンツが視覚的に表示される速さ |
| LCP (Largest Contentful Paint) | 最も大きな要素が描画されるまでの時間 |
| TTI (Time To Interactive) | ページが操作可能になるまでの時間 |
| TBT (Total Blocking Time) | FCP から TTI までの間にメインスレッドがブロックされていた合計時間 |
| CLS (Cumulative Layout Shift) | 予期しないレイアウトのずれの発生量 |
3. ☐ フォントの最適化
フォントは意外とパフォーマンスに影響します。以下のポイントをチェックしましょう。
-
セルフホストする
外部サービスから読み込むのではなく、自前でホストすることでリクエスト数を削減できます。 -
WOFF2 形式を使用する
現時点で最も圧縮率が高いフォント形式です。 -
フォントサブセットを利用する
必要な文字種のみを含んだ軽量版を選びましょう(例:ラテン文字のみ)。 -
Variable Fonts を検討する
複数のスタイルを 1 ファイルにまとめられる可変フォントは、全体の容量を削減できます。 -
font-display: swapを設定する
フォント読み込み中のテキスト非表示(FOIT)を防ぎます。
4. ☐ スクリプトの制御
サードパーティスクリプトはパフォーマンスの大きな要因です。
-
asyncまたはdeferを使用する
メインスレッドをブロックしないように読み込みます。 -
next/scriptを活用する
Next.js 組み込みの Script コンポーネントで、読み込み戦略を細かく制御できます。 -
タグマネージャーに集約する
複数のスクリプトは Google Tag Manager などで一元管理すると制御しやすくなります。 -
リソースヒントを設定する
preconnectやdns-prefetchで事前接続を行い、読み込みを高速化します。
5. ☐ スタイルの最適化
Next.js のような SSR アプリケーションでは、CSS-in-JS はメインスレッドに負荷をかけがちです。
-
CSS Modules または CSS を優先する
CSS-in-JS よりも軽量で、サーバーサイドでの負荷が少なくなります。 -
Next.js の組み込み最適化を活用する
クラス名の minify、Sass サポート、PostCSS などがデフォルトで利用可能です。 -
font-displayを確認する
@font-face で適切に設定されているか再確認しましょう。
6. ☐ バンドルの最適化
バンドルサイズが小さいほど、ページは速くなります。
-
バンドル分析ツールを定期的に実行する
bundle-wizardや@next/bundle-analyzerで現状を可視化しましょう。
bundle-wizardはデプロイ済みアプリケーションでも分析できる点が便利です。 -
Chunk splitting を設定する
next.config.jsで重いパッケージを独立したチャンクに分割します。
// next.config.js の例
module.exports = {
webpack(config) {
config.optimization.splitChunks.cacheGroups.sentry = {
test: /[\\/]node_modules[\\/]@sentry[\\/]/,
name: 'sentry',
chunks: 'all',
};
return config;
},
};
-
重複モジュールをマージする
モノレポ環境などで発生する重複を Webpack の設定で解消します。 -
Webpack performance hints を有効にする
チャンクが一定サイズを超えた場合に警告を出し、早期発見に役立てます。
7. ☐ CLS の防止
CLS(Cumulative Layout Shift)は、ページ読み込み中の予期しないレイアウト移動を数値化したものです。
-
未読み込みコンテンツの領域を確保する
スケルトンローダーやプレースホルダーでスペースを事前に確保します。 -
画像や動画のサイズを明示する
widthとheight属性を必ず指定しましょう。 -
動的コンテンツを既存コンテンツの上に挿入しない
バナーや広告などは、レイアウトが確定した後に読み込むようにします。
8. ☐ 画像の最適化
画像は依然としてパフォーマンス低下の最大要因のひとつです。
-
次世代フォーマットを使用する
WebP や AVIF を採用し、古いブラウザにはフォールバックを用意します。 -
レスポンシブ画像を実装する
ブレイクポイントごとに異なるサイズを用意し、srcSetや<picture>で切り替えます。 -
遅延読み込み(Lazy Loading)を有効にする
<img loading="lazy">でビューポート外の画像は後から読み込みます。 -
重要な画像は preload する
LCP 要素となる画像は事前に読み込み指定を行います。 -
next/imageを活用する
Next.js の Image コンポーネントは、上記の最適化を自動で行ってくれます。
9. ☐ JavaScript の最適化
JavaScript の扱い方次第で、パフォーマンスは大きく変わります。
-
コード分割を実施する
next/dynamicでコンポーネントを動的インポートし、必要なタイミングでのみ読み込みます。
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('@/components/HeavyComponent'), {
loading: () => <p>読み込み中...</p>,
});
-
バレルファイルを避ける
複数のエクスポートをまとめたindex.jsは、ツリーシェイキングが意図通りに動作しない場合があります。個別にインポートしましょう。
// ❌ バレルファイル経由
import { Button, Input } from '@/components';
// ✅ 直接インポート
import Button from '@/components/Button';
import Input from '@/components/Input';
-
ツリーシェイキングを確認する
ライブラリが未使用コードを適切に除去できているか確認します。
10. ☐ パフォーマンスを維持する仕組み作り
一度スコアを上げても、放置すれば再び低下します。以下の仕組みで継続的に維持しましょう。
| 施策 | 内容 |
|---|---|
| [ ] Lighthouse CI | CI 上で Lighthouse を自動実行し、PR がスコアを下げていないかチェックします |
| [ ] Real User Monitoring (RUM) | Sentry などのツールで実際のユーザー環境でのパフォーマンスを計測します |
| [ ] 定期的なバンドル分析 | 新たな依存関係を追加するたびにバンドルサイズを確認します |
| [ ] WebPageTest の活用 | ウォーターフォールチャートやフィルムストリップなど、より詳細な分析が可能です |
| [ ] Webpack performance hints | ビルド時にチャンクサイズの閾値を超えたら警告を出す設定を行います |
まとめ
Next.js で Lighthouse スコアを高く保つためには、以下のサイクルが重要です。
- 計測 – 現状を正しく把握する
- 最適化 – 上記チェックリストを順に実施する
- 自動化 – CI や監視ツールで継続的にチェックする
パフォーマンスは「一度やったら終わり」ではありません。日々の開発フローにこれらのチェックを組み込み、ユーザーにとって快適なアプリケーションを維持していきましょう。
本記事は実務経験と、Marcin Kurka 氏の記事などを参考に作成しました。
📌 参考リンク
