Next.jsでPSI 100点を叩き出したパフォーマンス改善全記録|Core Web Vitals最適化の極意

Next.jsサイトのPSIスコアを62点から100点(GTM込みで98点)まで改善するには、Google Fontsの廃止、画像の徹底圧縮、レガシーブラウザの切り捨てが不可欠でした。
- 「Next.jsで作ったのに、なぜかLCPが改善しない」
- 「PageSpeed Insightsのスコアが60点台で停滞している」
- 「100点を目指したいが、具体的なコードレベルの対策がわからない」
このような悩みを持つ開発者は多いはずです。
本記事では、conets公式サイトで実際に実施した「泥臭いチューニング」の全工程を公開します。
教科書的な一般論ではなく、実際にスコアを叩き出した技術と意思決定のプロセスを、誰でも再現可能なレベルで解説します。

なぜ今、パフォーマンス改善が重要なのか?

Webサイトのパフォーマンス改善は、もはや「エンジニアの自己満足」ではありません。
それはビジネスの成否を分ける重要な経営課題です。
Next.jsの普及と高速化の難しさ
Next.jsは、Reactベースのフレームワークとしてデファクトスタンダードの地位を確立しました。
サーバーサイドレンダリング(SSR)や静的サイト生成(SSG)を標準でサポートし、SEOに強いサイトを構築できる点が魅力です。
しかし、高機能であるがゆえに、開発者が意識せずに実装を進めると、JavaScriptのバンドルサイズが肥大化しやすく、結果として「重いサイト」が出来上がってしまうというパラドックスを抱えています。
特にApp Routerの登場以降、サーバーコンポーネントとクライアントコンポーネントの境界線が複雑になり、パフォーマンスチューニングの難易度は上がっています。
「デザイン vs 速度」のジレンマ
Web制作の現場では、常に「デザイン」と「速度」のトレードオフが発生します。
デザイナーは美しいフォント(Webフォント)や高解像度の画像、リッチなアニメーションを使いたがります。一方で、エンジニアはそれらがパフォーマンスを低下させる要因であることを知っています。
「おしゃれだけど遅いサイト」と「シンプルだけど爆速なサイト」。どちらが正解かはビジネスの目的によりますが、Core Web Vitalsがランキング要因となった現在、速度を犠牲にすることはSEO上のリスクを伴います。
スコアが悪いと何が起きるか(SEO・CVR・ブランディング)
PageSpeed Insights(PSI)のスコアが低い状態を放置すると、以下のような悪影響が生じます。
- SEO順位の下落: GoogleはCore Web Vitalsをランキングシグナルとして採用しています。特にLCP(読み込み速度)が遅いサイトは、検索順位で不利になります。
- CVR(コンバージョン率)の低下: Amazonの調査では、ページの読み込みが0.1秒遅れるごとに売上が1%低下すると報告されています。ユーザーは待ってくれません。
- ブランド毀損: 表示が遅いサイトは「技術力がない」「ユーザーのことを考えていない」というネガティブな印象を与え、企業の信頼性を損ないます。
conetsでは、これらのリスクを回避し、最高のユーザー体験を提供するために、PSIスコア100点を目指すプロジェクトを立ち上げました。
パフォーマンス改善の全体像とボトルネック分析

初期のPageSpeed Insightsスコアは62点で、主な原因はLCP(43.1秒超過)でした。
分析の結果、日本語Webフォントの読み込み連鎖、2MBを超える巨大画像、レガシーブラウザ向けの不要なポリフィルがボトルネックであることが判明しました。
これらを一つずつ潰すことで、スコアは劇的に改善しました。
指標ごとの課題と対策一覧表
指標 | 問題項目 | ボトルネックの詳細 | 実施した対策 |
LCP | フォント読み込み連鎖 | 日本語フォント(Noto Sans JP)が40ファイル以上に分割され、リクエストの「ウォーターフォール」が発生。テキスト描画が1.5秒遅延。 | next/font/googleを廃止し、システムフォント(OS標準)へ切り替え。読み込み時間を0秒に短縮。 |
LCP | 画像サイズ超過 | 無料相談のご予約の背景画像が 2MB(巨大WebP)、プロフィール画像がPC用サイズ(3840px)のまま配信されていた。 | 背景画像を122KBに圧縮。プロフィール画像に適切なsizes属性を付与し、スマホで小サイズを読み込むよう修正。 |
FCP | 巨大なSVGロゴ | ヘッダーのロゴ(SVG)にビットマップ画像が埋め込まれており、65KBと肥大化。FCP(最初の描画)を直撃。 | ロゴをシンプルにして2KBまで圧縮。 |
TBT | レガシーJSの実行 | Array.prototype.at などのポリフィルが含まれ、バンドルサイズが肥大化。古いブラウザ向けの変換が残っていた。 | package.json の browserslist をモダンブラウザ向けに更新し、IEや古いiOSをサポート対象外へ。 |
LCP | アニメーション遅延 | Heroセクションのテキストにフェードインアニメーションがあり、描画完了(LCP確定)まで1.2秒のアイドルタイムが発生。 | ファーストビューのアニメーションを削除し、初期状態から opacity: 100 で即時表示するよう強制。 |
Speed Index | レンダリングブロック | CSSの読み込みと解析が完了するまで、画面の描画が1秒近くブロックされていた。 | 不要なCSS記述の削減と、上記フォント・画像の軽量化による通信帯域の確保。 |
FCP/LCP/TBT/CLS の相関関係と技術的背景
Core Web Vitalsの各指標は独立しているわけではなく、密接に関連しています。
- FCP(First Contentful Paint): 最初のコンテンツが表示されるまでの時間。これが遅いと、ユーザーは「画面が真っ白」な状態を長く見ることになります。主な原因はサーバー応答時間(TTFB)や、レンダリングをブロックするCSS/JSです。
- LCP(Largest Contentful Paint): メインコンテンツが表示されるまでの時間。FCPが遅ければLCPも遅れますが、FCPが速くても巨大な画像やWebフォントがあればLCPは遅延します。
- TBT(Total Blocking Time): FCPからTTI(操作可能になるまで)の間に、メインスレッドがブロックされた時間の合計。重いJavaScriptの実行が主な原因です。TBTが悪化すると、ユーザーがボタンを押しても反応しない(INP悪化)状態になります。
- CLS(Cumulative Layout Shift): 視覚的な安定性。画像や広告が遅れて読み込まれ、レイアウトがガクッとズレる現象です。
ネットワークウォーターフォールとは何か
ブラウザの開発者ツール(Networkタブ)を見ると、リソースがどのような順序で読み込まれているかがわかります。これを「ウォーターフォール」と呼びます。
理想的なウォーターフォールは、重要なリソース(HTML, CSS, LCP画像)が同時に並行して読み込まれる状態です。しかし、改善前のconetsサイトでは、以下のような「悪夢の連鎖」が起きていました。
- HTMLのダウンロード完了
- CSSのダウンロード開始
- CSSの解析中にWebフォントのリクエストが発生
- Webフォント(40ファイル)のダウンロード待ち
- フォントダウンロード完了後にようやくテキスト描画(LCP発生)
このように、前の処理が終わらないと次が進まない状態(直列処理)が、LCPを大幅に遅らせていたのです。
日本語フォントが爆重な理由(低レベル構造)
欧文フォント(英語)は文字数が少ないため、ファイルサイズは数十KB程度です。しかし、日本語フォント(漢字含む)は数千〜数万文字を含むため、ファイルサイズが数MBにもなります。
Google Fontsはこれを「サブセット化(よく使う文字ごとに分割)」して配信しますが、それでも日本語サイトでは数十個のフォントファイルをダウンロードする必要があり、これが通信のボトルネックとなります。
Next.jsのビルド構造とTBTの関係
Next.jsは、ページごとに必要なJavaScriptを分割(Code Splitting)して配信します。しかし、node_modules に含まれるライブラリや、古いブラウザ向けのポリフィル(互換コード)は、すべてのページで読み込まれる「共通バンドル(chunks/main.jsなど)」に含まれることが多いです。
この共通バンドルが肥大化すると、ブラウザはJSの解析と実行に時間を取られ、メインスレッドがブロックされます。これがTBT悪化の正体です。
【LCP改善】Google Fontsを捨て、システムフォントへ回帰

LCP改善の最大の決定打は、next/font/google の廃止とシステムフォントへの切り替えでした。
日本語フォントはファイルサイズが大きく、サブセット化によるリクエスト増大がLCPを1.5秒遅延させていました。
OS標準フォント(ヒラギノ、メイリオ等)を採用することで、読み込み時間を実質0秒に短縮しました。
next/font の内部挙動(CSS injection, preload の仕様)
Next.jsの next/font は非常に優秀な機能です。ビルド時にフォントファイルをダウンロードし、セルフホスティング(自社サーバーからの配信)に切り替えてくれます。また、CSSの中にフォントデータをインラインで埋め込むことで、レイアウトシフト(CLS)を防ぐ仕組みも持っています。
しかし、日本語フォント(Noto Sans JPなど)の場合、その仕組みが仇となります。Google Fontsから取得した大量のサブセットフォント(woff2ファイル)を、ブラウザは並列でダウンロードしようとします。
HTTP/2通信とはいえ、数十個のリクエストが一斉に発生すると、帯域が圧迫され、肝心のLCP画像やメインJSの読み込みが後回しにされてしまうのです。
サブセット化の限界(Noto Sans JPの爆重量)
「必要な文字だけダウンロードすれば速いのでは?」と思うかもしれません。
確かにサブセット化は有効ですが、日本語のWebサイトでは、ひらがな、カタカナ、常用漢字だけでも相当な文字数になります。
実際に計測したところ、トップページを表示するだけで40個以上のフォントファイルへのリクエストが発生していました。
これらが全て完了するまでテキストが表示されない(または代替フォントから切り替わる瞬間にチラつく)現象は、UXを大きく損なっていました。
システムフォントスタックの歴史と回帰
そこで我々は、「Webフォントを使わない」という決断をしました。
システムフォントとは、ユーザーのデバイス(Windows, Mac, iPhone, Android)にあらかじめインストールされているフォントのことです。
- Mac/iOS: ヒラギノ角ゴシック
- Windows: メイリオ / Yu Gothic
- Android: Noto Sans CJK
これらは既に端末内にあるため、ダウンロード時間は「ゼロ」です。
かつてWebデザインの世界では、OSごとにフォントが違うことを嫌い、Webフォントで統一することが良しとされてきました。
しかし、Core Web Vitals時代においては、「0秒で表示される」という価値が再評価されています。GitHubなどの大手テック系サイトも、システムフォントを採用しています。
実際にフォントを切り替えた前後のウォーターフォール比較
【改善前:Google Fonts使用時】
- HTML取得
- CSS取得
- フォントリクエスト発生(40個以上)
- フォントダウンロード待ち(約1.5秒)
- テキスト描画(LCP)
【改善後:システムフォント使用時】
- HTML取得
- CSS取得
- テキスト描画(LCP) ※フォントダウンロードなし
この差は歴然でした。ウォーターフォールから「フォントの壁」が消え去り、LCPスコアが一気に1.5秒短縮されました。
「デザインを捨てる」意思決定の葛藤
正直に言えば、この決断は簡単ではありませんでした。「Noto Sans JPの美しさが失われる」「ブランドイメージが変わる」という懸念が生まれました。
しかし、我々は「ユーザーにとっての価値」を問い直しました。ユーザーは「美しいフォントで描かれた、表示されるまで3秒かかる文章」と、「普通のフォントだけど、一瞬で表示される文章」、どちらを求めているでしょうか?
conetsは中小企業診断士として、世の中の中小企業に様々な技術を教える側面が強いため、「情報の速さ」を最優先するという経営判断を下しました。
実装内容:layout.tsx でのGoogle Fonts読み込みを削除し、tailwind.config.ts を以下のように変更しました。
// tailwind.config.ts
theme: {
extend: {
fontFamily: {
sans: [
"system-ui",
"-apple-system",
"BlinkMacSystemFont",
"Hiragino Kaku Gothic ProN", // ヒラギノ角ゴ
"Hiragino Sans",
"Meiryo", // メイリオ
"sans-serif",
],
},
},
},【LCP改善】画像の徹底的なダイエットと最適化

フォントの次に着手したのが、画像の最適化です。
無料相談のご予約の背景画像が2MBもあり、これがLCPを悪化させていました。
Squoosh等のツールで122KBまで圧縮し、next/image の sizes 属性を適切に設定することで、スマホでは小さな画像が読み込まれるように修正しました。
ブラウザの画像選択アルゴリズムとsizes属性
next/image を使う際、多くの開発者が sizes 属性を適当に設定(または未設定)しています。しかし、これは致命的です。
ブラウザは、srcset(Next.jsが自動生成する複数の画像候補)と sizes(表示される予定のサイズ)を見て、どの画像をダウンロードするかを決定します。
もし sizes が未設定だと、ブラウザは「画面幅いっぱいに表示されるかもしれない」と判断し、スマホであってもPC用の巨大な画像(3840pxなど)をダウンロードしてしまうことがあります。
<Image
src="/profile.png"
alt="プロフィール"
priority={true}
sizes="(max-width: 768px) 100vw, 50vw" // スマホは全幅、PCは半幅
// ...
/>このように「スマホなら100vw、PCなら50vw」と明示することで、ブラウザは適切なサイズの画像を選択できるようになります。
next/image v13/v14 の仕様差と進化
Next.js 13以降、next/image は大幅に進化しました。
以前の layout="fill" などの複雑なプロパティが整理され、標準の img タグに近い感覚で使えるようになりました。
また、デフォルトでWebP形式への変換が行われますが、next.config.js でAVIF形式を有効にすることで、さらに圧縮率を高めることが可能です。
// next.config.mjs
const nextConfig = {
images: {
formats: ['image/avif', 'image/webp'],
},
};WebPとAVIFの効能と限界
- WebP: JPEG/PNGに比べて約30%軽量。ほぼ全てのモダンブラウザで対応。
- AVIF: WebPよりもさらに圧縮率が高いが、エンコード(変換)に時間がかかる。
conetsでは、サーバー負荷と対応ブラウザのバランスを考慮し、基本はWebPを採用しつつ、将来的なAVIF移行も視野に入れています。
圧縮ツール比較(Squoosh, tinypng, imagemin)
画像をアップロードする前の「元画像」自体の圧縮も重要です。Next.jsが変換してくれるとはいえ、元が2MBあれば変換後もそれなりのサイズになります。
- Squoosh: ブラウザ上で動作し、視覚的に画質を確認しながら圧縮できる。1枚ずつの調整に最適。今回はこれを採用。
- TinyPNG: 手軽だが、圧縮率の微調整ができない。
- imagemin: ビルドプロセスに組み込んで自動化できるが、設定が複雑。
今回は無料相談のご予約の背景画像という「一点物」の最適化だったため、Squooshを使って人間の目でギリギリの画質を見極め、2MB → 122KBへの圧縮に成功しました。
【TBT改善】レガシーブラウザの切り捨てとJS軽量化

TBT(Total Blocking Time)の悪化原因は、メインスレッドをブロックする重いJavaScript処理でした。
特に、古いブラウザ(IEや旧iOS)向けのポリフィル(互換性維持のためのコード)が無駄に含まれていたことが判明しました。
JSが重くなるメカニズム(parse, compile, execute)
JavaScriptは、単にダウンロードするだけでなく、ブラウザがそれを「解析(Parse)」「コンパイル(Compile)」「実行(Execute)」する必要があります。
ファイルサイズが大きいと、ダウンロードに時間がかかるだけでなく、この解析・実行プロセスでCPUを占有し、メインスレッドをブロックしてしまいます。これがTBT悪化の正体です。
ポリフィルがボトルネックを生む理由
ポリフィルとは、古いブラウザでも新しい機能(例:Array.prototype.at や Promise)を使えるようにするための「継ぎ接ぎコード」です。
モダンブラウザ(Chrome, Edge, 最新Safari)には不要なコードですが、設定次第では全てのユーザーに配信されてしまいます。これが「無駄な荷物」となり、TBTを悪化させます。
browserslistの更新とモダンブラウザへの特化
package.json の browserslist を更新し、モダンブラウザのみをサポート対象としました。
"browserslist": [
"last 2 versions",
"not dead",
"not ios < 15.4",
"not chrome < 100",
"not safari < 15.4",
"not firefox < 100",
"not edge < 100",
"not opera < 100",
"not android < 100",
"not ios < 15.4",
"not chrome < 100",
"not safari < 15.4"
]これにより、ビルドツール(SWC/Webpack)は「古いブラウザへの変換は不要」と判断し、より短く効率的なコードを出力するようになります。
legacyBrowsers の内部動作とバンドル差分
さらに、Next.jsの設定ファイルでレガシーブラウザ向けのビルド生成を停止しました。
// next.config.mjs
const nextConfig = {
experimental: {
legacyBrowsers: false, // レガシーブラウザ向け生成を停止
},
// ...
};
export default nextConfig;この設定を入れる前後でビルド結果(.next/static/chunks)を比較したところ、共通バンドルのサイズが約15%削減されていました。たった数行の設定変更ですが、効果は絶大です。
アニメーションによるLCP遅延の排除
Heroセクションのテキストに「ふわっと表示される(フェードイン)」アニメーションを入れていましたが、これがLCPを遅らせていました。
アニメーションが完了して初めて「描画完了」とみなされるため、1.2秒のアニメーションがあれば、LCPも1.2秒遅れます。ファーストビューのアニメーションを削除し、初期状態から opacity: 1 で即時表示するように変更しました。
// src/components/pages/home/HeroSection.tsx
// ▼ JS読み込みやCSS競合を無視して、最速で文字を表示させるスタイル
const forceVisibleStyle = {
opacity: 1,
visibility: "visible" as const,
transform: "none",
animation: "none",
transition: "none",
};
const HeroSection = () => (
<section className="relative overflow-hidden bg-gray-50">
<Image
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
alt="conetsのヒーローバナー背景"
width={1200}
height={1}
priority
className="absolute opacity-0 pointer-events-none"
/>
<div className="absolute inset-0 z-0 opacity-60 pointer-events-none">
<GearsBackgroundWrapper className="text-gray-300/50" />
</div>
<div
className={`relative z-10 mx-auto max-w-6xl ${PADDING_HORIZONTAL.SM} py-24 sm:py-32`}
>
<h1
className={`${COMPONENT_MARGIN_TOP.SM} text-2xl font-extrabold leading-snug text-sub sm:text-3xl lg:text-4xl`}
style={forceVisibleStyle}
>
社長の仕事は「決める」だけ
<br />
売上の上がる仕組みづくりは、
<br className="block sm:hidden" />
すべてconetsにお任せください
</h1>
<p
className={`${COMPONENT_MARGIN_TOP.SM} text-lg leading-relaxed text-gray-700 sm:text-xl opacity-100 translate-y-0 visible`}
style={forceVisibleStyle}
>
長い会議より、小さなテストを。
<br className="block sm:hidden" />
完璧な計画より、まず一歩を。
<br />
マーケティング、業務改善、データ活用まで、一気通貫で成果をつくります。
</p>【最終調整】GTM(Google Tag Manager)との戦いと98点の現実

すべての最適化を行い100点を達成しましたが、マーケティング施策のためにGTMを導入した瞬間、スコアが低下しました。
サードパーティスクリプトの影響は避けられませんが、ビジネスゴール(計測・分析)のために「98点で妥協する」という現実的な判断を下しました。
なぜGTMは重いのか(技術的理由)
GTM自体は単なる「タグのコンテナ(入れ物)」ですが、その中にはGA4、広告コンバージョンタグ、ヒートマップツールなど、多数のサードパーティスクリプトが含まれます。
これらは外部サーバーからダウンロードされ、ページの内容を読み取ったり、ユーザーの操作を監視したりするためにメインスレッドを使用します。
特にページ読み込み直後にこれらが一斉に動き出すと、TBTが跳ね上がります。
GA4, Tag, Trigger の負荷解説
GTMの中で設定されている「トリガー」も負荷の原因です。
「全ページのクリックを計測する」「スクロール率を計測する」といったトリガーは、ブラウザ上で常にイベントリスナーを稼働させる必要があり、CPUリソースを消費します。
不要なタグやトリガーを整理(断捨離)することも、立派なパフォーマンス改善です。
Partytownの具体的な導入が難しい理由
「Partytown」というライブラリを使えば、これらのサードパーティスクリプトをWeb Worker(別スレッド)で動かし、メインスレッドの負荷を下げることができます。
しかし、Partytownは設定が複雑で、一部のタグ(特にDOM操作を伴うもの)が正しく動作しないリスクがあります。
また、プロキシサーバーの設定が必要になる場合もあり、導入ハードルは高いです。今回はメンテナンスコストを考慮し、導入を見送りました。
以下の記事を読んでPartytownの導入をやめました。興味のある方はこちらもどうぞ。
GTMを入れたらサイトスピードがめちゃくちゃ落ちた(改善策あり)
「98点で良い理由」のビジネス視点の解説
「100点」はあくまで指標であり、目的ではありません。
ビジネスの目的は「サイトを通じて成果を上げること」であり、そのためには計測データが不可欠です。
98点あればUXとしては十分合格点であり、体感速度は100点と変わりません。
残りの2点を追うために計測データを捨てるのは、本末転倒です。技術とビジネスのバランスを取った結果の「98点」なのです。
よくある質問(FAQ)
Next.jsのパフォーマンス改善に関するよくある質問として、next/image の使い分け、フォントの最適化、GTMの影響などが挙げられます。
特に画像最適化は効果が高く、まずはここから着手すべきです。
また、スコア改善はSEOだけでなく、ユーザー体験(CVR)向上にも直結します。
QPSI 100点は本当に必要ですか?
必須ではありません。
GoogleのCore Web Vitalsの合格ライン(LCP 2.5秒以内など)をクリアしていれば、SEO上のペナルティはありません。ただし、100点を目指す過程でサイトの無駄が削ぎ落とされ、結果としてCVR向上などの副次効果が得られることは間違いありません。
QGTMを入れた状態で最もスコアを下げない設定は何ですか?
next/script コンポーネントを使い、読み込み戦略を strategy="afterInteractive"(ページがインタラクティブになった後)や strategy="lazyOnload"(アイドル時)に設定することです。
ただし、lazyOnload にすると計測開始が遅れるため、PV計測の精度とのトレードオフになります。
Qnext/font/local は使っても速度は落ちますか?
next/font/google よりはマシですが、やはりフォントファイルのダウンロードが発生するため、システムフォントよりは遅くなります。(我々も実装しましたが、62点が72点になるくらいで100点を目指すことは厳しいと判断しました)
どうしても特定のフォントを使いたい場合は、サブセット化(必要な文字だけを含める)を行い、ファイルサイズを極限まで小さくする工夫が必要です。
Q画像形式はWebPとAVIFどちらが良いですか?
基本はWebPで十分です。AVIFは圧縮率は高いですが、エンコードに時間がかかり、古いブラウザ(Edgeの旧版など)で非対応の場合があります。Next.jsの設定で両方有効にしておけば、ブラウザに応じて最適な形式が配信されます。
QTBTを改善するにはJSを削るしかないですか?
基本的にはそうです。不要なライブラリを削除する、巨大なライブラリ(Moment.jsなど)を軽量なもの(Day.jsなど)に置き換える、Code Splittingを適切に行うなどが有効です。また、React.lazy や dynamic import を使って、ファーストビューに不要なコンポーネントを遅延読み込みさせるのも効果的です。
QCLS(レイアウトシフト)を防ぐコツは?
画像には必ず width と height を指定すること(next/image なら自動)、広告枠などの動的コンテンツにはあらかじめ min-height で領域を確保しておくことが重要です。フォントの読み込み遅延によるチラつき(FOUT/FOIT)もCLSの原因になるため、システムフォントへの切り替えはここでも有効です。
Qモバイルでのスコアが低いのはなぜですか?
PSIのモバイルスコアは、低スペックな端末と低速回線(4G)をシミュレートして計測されるため、PCよりも厳しく判定されます。PCで100点でもモバイルで60点ということはよくあります。モバイルスコアを上げるには、CPU負荷(JS実行時間)を減らすことが最も重要です。
Q改善効果はいつ頃SEO順位に反映されますか?
Core Web Vitalsのデータ(Chrome UX Report)は28日間の集計値に基づいているため、改善を行ってからGoogleの評価に反映されるまでには約1ヶ月かかります。Search Consoleの「ウェブに関する主な指標」レポートで推移を確認しましょう。
Q開発環境(localhost)のスコアは信用できますか?
いいえ、信用できません。開発環境では最適化が無効になっていたり、デバッグ用のコードが含まれていたりするため、本番環境(Vercelなど)にデプロイした状態で計測する必要があります。
QVercel AnalyticsとGTMはどちらが良いですか?
パフォーマンスの観点では、Vercel Analyticsの方が圧倒的に軽量で優秀です。サーバーサイドで計測されるため、クライアントの負荷がほぼありません。ただし、マーケティング分析の機能(広告連携など)はGTM/GA4の方が豊富です。用途に応じて使い分けるか、併用を検討してください。
QCDN(Content Delivery Network)は必要ですか?
Vercelなどのホスティングサービスを使っていれば、自動的にCDN経由で配信されるため、別途設定する必要はありません。自前サーバーで運用している場合は、CloudflareなどのCDN導入が必須です。
Q100点を取ったら終わりですか?
いいえ、終わりではありません。サイトを更新して画像を追加したり、新しい機能を入れたりすれば、スコアはまた下がります。定期的に計測を行い、パフォーマンスを維持し続ける「守りの運用」が必要です。
まとめ:パフォーマンス改善は「引き算」の美学
本記事では、Next.jsサイトのPSIスコアを62点から100点(98点)まで改善した全記録を公開しました。
- LCP改善: Google Fontsを捨て、画像を圧縮し、sizes属性を最適化する。
- TBT改善: レガシーブラウザを切り捨て、不要なJSポリフィルを排除する。
- 意思決定: アニメーションやGTMなど、速度とトレードオフになる要素を冷静に判断する。
改善前の私たちは、「Next.jsを使っているから速いはずだ」という慢心がありました。
しかし現実は、重いフォントと画像で塗り固められた、鈍重なサイトでした。
そこから「デザインを捨てる」「レガシーを切り捨てる」という痛みを伴う決断(引き算)を繰り返すことで、ようやく100点という頂に到達しました。
この過程で得られたのは、単なるスコアだけではありません。「ユーザーにとって本当に大切なものは何か」を問い続ける姿勢です。
今後もconetsでは、CLSのさらなる改善や、新技術(React Server Componentsの最適化など)への追従を続け、最高のパフォーマンスを追求し続けていきます。


