独立サイトのCSS/JS最適化:結合、圧縮、遅延読み込み、クリティカルCSSのインライン化

CSS/JS最適化の目的は「ファイル数を減らすこと」ではなく、初回描画に必要なバイトだけを読み込ませることです。核心となる4つのルールは、クリティカルCSSをheadにインライン化(約15KB以内)、非クリティカルCSSはmedi...

CSS/JS加载策略:阻塞资源与非阻塞资源的分流表CSS/JS loading: split blocking vs non-blocking resources 把所有JS都defer不是免费午餐 —— 交互脚本defer过头INP会涨Deferring every script is not free — over-defer hurts INP 资源类型Resource 加载策略Strategy 收益与风险Payoff & risk 关键CSSCritical CSS 内联到head · 其余异步inline in head · rest async FCP提前0.5至1秒FCP -0.5 to 1s 非关键CSSNon-critical CSS media=print+onload切换media=print swap trick 首屏交互JSAbove-fold JS defer · 不要asyncdefer, not async 不阻塞解析,保序执行non-blocking, ordered 后台/分析JSAnalytics JS requestIdleCallback延迟requestIdleCallback delay 核心指标:FCP≤1.8秒 · TTI≤3.8秒 · 主主线工作≤200msCore: FCP ≤1.8s · TTI ≤3.8s · main-thread ≤200ms 合并≠越快越好:拆成长期缓存的分块比单一大文件更省Merge≠faster: cacheable chunks beat one mega-file 红线:把所有JS加async —— 执行顺序乱,jQuery插件批量报错Red line: async on every script — order breaks, plugins crash 合并CSS前先查未用CSS,否则50KB的死代码一起内联进headPurge unused CSS before inlining critical CSS
CSS/JSの読み込みを振り分け:クリティカルCSSはインライン、非クリティカルは非同期、操作系JSはdefer、解析JSは遅延

独立サイトのCSS/JS最適化:結合、圧縮、遅延読み込み、クリティカルCSSのインライン化

結論から言うと:CSS/JS最適化の目的は「ファイル数を減らすこと」ではなく、初回描画に必要なバイトだけを読み込ませることです。核心となる4つのルールは、クリティカルCSSをheadにインライン化(約15KB以内)、非クリティカルCSSはmedia=print onloadのテクニックで非同期読み込み、初回表示で使う操作系JSはasyncではなくdefer、解析や広告系のJSはrequestIdleCallbackで初回表示の後まで遅らせる、というものです。直感に反する判断が1つあります。すべてのJSにasyncを付けてもタダにはならず、実行順が乱れるとjQueryとそれに依存するプラグインが一斉にエラーを出します。もう1つ直感に反するのは、CSSを1ファイルに結合しても必ず速くなるとは限らない点です。長期キャッシュによる分割の再利用を失うからです。

1. CSS/JSが初回描画をブロックする理由

ブラウザがHTMLを描画するには厳格なルールがあります。CSSは描画をブロックし、JSは解析をブロックします。headにダウンロード未完了のCSSが1つでもあると、ブラウザは1ピクセルも描画しません。bodyにasync/deferの付いていないscriptが1つでもあると、そこまで解析した時点で止まり、JSのダウンロードと実行を待ちます。この2つのブロックが重なることが、FCP(First Contentful Paint)が遅くなる根本原因です。

WordPressの独立サイトでよくある問題は、テーマが5つのCSSを読み込み、プラグインがさらに8つのJSを読み込む構成です。どれも圧縮も結合もされていないソースファイルで、headにlinkとscriptタグがずらりと並び、ダウンロードの順番待ちだけで3〜5秒かかります。最適化の方向は「すべてのファイルを1つに結合する」ことではなく、振り分けです。すぐ読み込む必要があるものと、初回描画が終わってから読み込めばよいものを分けます。Core Web Vitalsの合格ラインはCore Web Vitalsの最適化、WP技術スタックの構成はWordPress技術スタック。

ブロックの種類 ブラウザの動作 影響する指標 対応方法
head内の外部CSS ダウンロード完了まで描画をブロック FCP、LCP クリティカルCSSはインライン、残りは非同期
body内でdeferのないscript HTMLの解析をブロック FCP、TTI 一律にdeferを付けるか、の前に移動
同期XHRリクエスト メインスレッドをブロック INP、TTI 非同期fetchに変更
フォントの読み込み テキストが表示されないことがある LCP font-display:swap+preload
サードパーティスクリプト 解析またはメインスレッドをブロック INP、TBT 遅延させるかGTMで管理

2. クリティカルCSSのインライン化:初回表示に必要なスタイルをheadに書く

クリティカルCSS(Critical CSS)とは、初回表示の内容を描画するために必要な最小限のスタイル集のことです。通常はheader、heroエリア、初回表示で見える本文の一節、ボタンのスタイルで、およそ10〜20KBです。これをHTMLのstyleタグにインライン化すれば、ブラウザはCSSを追加でリクエストする必要がなくなり、FCPを0.5〜1秒早められます。

直感に反する点:インライン化とはCSS全体を詰め込むことではありません。多くの人が自動ツールで「CSSを全部インライン化」し、HTMLが50KBから300KBに膨らんだのにファーストビューはほとんど速くならず、キャッシュも無効になった。正しい方法はファーストビュー(above-the-fold)の部分だけをインライン化し、残りのCSSは外部リンクのまま非同期で読み込むこと。WordPressならCriticalCSSプラグインやPurgeCSSで自動抽出できる。手動で判断する場合、ファーストビューのスタイルは通常CSS全体の15〜25%程度だ。WPのキャッシュ戦略はこちらサイトのキャッシュ戦略。

やり方 headのサイズ FCPの改善 リスク
クリティカルCSSなし インライン0KB ベースライン CSSがレンダリングをブロック
CSS全体をインライン化 100至300KB 非推奨 HTMLが肥大化しキャッシュも無効
ファーストビューのCSSだけインライン化 10至20KB 0.5〜1秒 ファーストビュー用スタイルシートの保守が必要
インライン化+残りを非同期読み込み 10至20KB 0.8〜1.5秒 FOUC対策のちらつき防止が必要

三、非クリティカルCSSの非同期読み込み:media=print onloadのテクニック

クリティカルCSSをインライン化したら、残りのサイト全体のCSSはレンダリングをブロックする必要はない。最もよく使われるテクニックは、linkタグをmedia=”print” onload=”this.media=’all'”と書く方法だ。ブラウザは最初は印刷用スタイルとして読み込み(レンダリングをブロックしない)、読み込み完了後に画面用スタイルに切り替える。広く検証されたハックで、すべてのモダンブラウザが対応している。

noscriptでのフォールバックを入れておけば、JSを無効にした古いブラウザでもスタイルが表示される。具体的なテンプレートは、<link rel=”stylesheet” href=”main.css” media=”print” onload=”this.media=’all'”>に<noscript><link rel=”stylesheet” href=”main.css”></noscript>を加える。このテクニックは短時間のFOUC(スタイル未適用のちらつき)を引き起こすが、クリティカルCSSのインライン化と併用すればファーストビューのスタイルはすでに適用済みで、ちらつきはファーストビューより下のコンテンツでのみ発生するため、ほとんど気づかれない。CDNキャッシュの設定方法はこちらCDNグローバル高速化。

読み込み方法 レンダリングをブロックするか ブラウザ対応 適用シーン
通常の外部CSS ブロックする すべて クリティカルCSS(ただしインライン化すべき)
media=print onloadで切り替え ブロックしない すべてのモダンブラウザ 非クリティカルのサイト全体CSS
rel=preload+onload ブロックしない Chrome/FF/Safari14+ 読み込みタイミングの正確な制御が必要
JSで動的に注入 ブロックしない すべて サードパーティ製コンポーネントのオンデマンド読み込み
styleタグにインライン化 即時反映 すべて クリティカルCSSのみに使用

四、JSのdeferとasync:速ければいいわけではない

scriptタグの読み込みモードは3つある。修飾なし(解析をブロック)、defer(ダウンロードはブロックせず、HTML解析完了後に順番どおり実行)、async(ダウンロードはブロックせず、ダウンロード完了後すぐに実行、順序は保証されない)。多くの人がチュートリアルを見て「すべてのJSにasyncを付けろ」と言うが、これは間違いだ。asyncは実行順序を保証しないため、jQueryがプラグインより先に実行されるとエラーになる。

正しい振り分け:ファーストビューの操作に関わるスクリプト(ナビメニュー、カルーセル、フォーム検証)はdeferを使い、DOMContentLoadedの前に順番どおり実行させる。分析、チャット、ピクセル系のスクリプトはasyncかrequestIdleCallbackで遅延実行する。具体例を挙げると、Google AnalyticsとHotjarの2つにasyncを付けるかsetTimeoutで2秒遅らせても機能には一切影響せず、TBT(総ブロック時間)を200〜400ミリ秒削減できる。GTMでの管理方法はこちらGTM管理。

スクリプトの種類 推奨属性 実行タイミング 注意点
jQuery+依存プラグイン defer DOM解析後に順番どおり実行 必ずdefer、asyncは不可
ファーストビューの操作(メニュー/カルーセル) defer DOMContentLoaded前 ユーザーがクリックする前にイベントを紐付けておく
Google Analytics asyncまたは遅延 アイドル時に実行 遅延してもデータ収集に影響なし
Hotjar/Clarity 2秒遅延またはidle ファーストビュー後 INPへの影響を避ける
サードパーティのチャット/ポップアップ ユーザー操作後に読み込む 30%スクロール後 遅延読み込みはコンバージョンに影響なし
インラインの小スクリプト 属性なし 即時実行 1KB以内に抑える

5. 結合と圧縮:単発のサイズより長期キャッシュが重要

圧縮(minify)は文句なしの効果がある。コメントと空白を削ればCSS/JSのサイズは30〜40%減る。しかし結合(concatenate)には直感に反する面がある。すべてのCSSを1ファイルにまとめると初回訪問は速くなるが、ユーザーが1行コードを変えるたびにファイル全体を再ダウンロードすることになり、長期キャッシュが効かなくなる。正しいやり方は、長期的に安定した複数のブロックに分けることだ。フレームワークCSS、テーマCSS、ページCSSを分け、共通部分は長期キャッシュし、ページ部分は必要に応じて読み込む。

WordPress環境ではAutoptimizeかW3 Total Cacheで結合と圧縮を行う。設定時は「CSSを結合」「JSを結合」「minify」の3項目をオンにするが、「すべてのJSをheadに結合」といった危険なオプションはオフにする。具体的な確認ポイントは、トップページのDevToolsのNetworkでCSSリクエスト数が10個から2〜3個に、JSリクエスト数が8個から3〜4個に減り、かつFOUCもコンソールエラーも出ないことだ。サイトのセキュリティと監視はこちらサイトセキュリティ強化とサイト監視アラート。

最適化の施策 サイズ削減効果 リスク 推奨設定
CSS minify -30%至40% ほぼなし オン
JS minify -30%至40% Source mapが失われる オン
CSS結合 リクエスト数を削減 キャッシュが頻繁に無効化 限定的に結合し、全部はまとめない
JSをheadに結合 リクエスト数を削減 レンダリングをブロック 禁止
JS結合+defer リクエストを減らしつつブロックしない 依存順序 慎重にオンにし、コンソールで確認
未使用CSSの削除 -40%至60% 動的スタイルを誤って削除 PurgeCSSで段階的に適用

FAQ よくある質問

すべてのJSにasyncを付けるのが最速ですか?
いいえ。asyncはダウンロード中HTMLをブロックしませんが、ダウンロードが終わるとすぐ実行され、順序は保証されません。jQueryとそれに依存するプラグインにasyncを付けると実行順が乱れ、$ is not definedが大量に出ます。正しいやり方は、ファーストビューの操作スクリプトにはdefer(順番どおり実行)を、分析や広告のスクリプトにはasyncか遅延読み込みを使うことです。deferとasyncは排他的ではありませんが、スクリプトの役割ごとに使い分ける必要があります。
クリティカルCSSは何KBまでインライン化するのが適切ですか?
10〜20KBが最適です。インラインが少なすぎると初回表示でFOUCのちらつきが残り、30KBを超えるとHTML自体が大きくなりキャッシュが効かなくなります。クリティカルCSSはheader、hero、ファーストビューの本文、ボタンのスタイルだけに絞り、全体のCSSの15〜25%に収めます。CriticalCSSツールで自動抽出したあと手作業で見直し、ファーストビューで使わないクラスを削除しましょう。
CSSを1つの大きなファイルにまとめると読み込みは速くなりますか?
初回訪問ではリクエスト数が減りますが、長期的なキャッシュ効率はむしろ悪化します。まとめると1行の変更でファイル全体のハッシュが変わり、全ユーザーが再ダウンロードすることになります。正しい方法は、フレームワークCSS(長期間変わらない)、テーマCSS(四半期ごとに更新)、ページCSS(必要なときだけ読み込む)の3つに分割し、共通部分は長期キャッシュ、ページ部分はオンデマンドで読み込むことです。統合は同じ種類のものだけにとどめ、すべてをまとめないでください。
media=print onloadのテクニックにはどんな落とし穴がありますか?
落とし穴は2つあります。1つ目は一時的なFOUC(スタイル未適用のちらつき)が起きることです。クリティカルCSSをインライン化していればファーストビューにはすでにスタイルが当たっているため、ちらつきは下方のコンテンツでほとんど見えません。2つ目はnoscriptのフォールバックが必須なことです。JSが無効な古いブラウザでもスタイルを表示させる必要があります。テンプレートはlinkタグにmedia=print onload=this.media=’all’を書き、さらにnoscriptタグで囲んで通常のmedia=allを書きます。
AutoptimizeとWP Rocketはどちらを選ぶべきですか?
Autoptimizeは無料で軽量、CSSとJSの結合と圧縮だけを行うので、すでにページキャッシュがあるサイトに向いています。WP Rocketは約59ドル/年で、ページキャッシュ、遅延読み込み、データベース最適化が統合され、すぐに使えます。一人のチームならパラメータ調整の手間を省けるWP Rocketがおすすめです。すでにキャッシュの仕組みがあるサイトならAutoptimizeで十分です。どちらも「すべてのJSをheadに置く」といった危険なオプションは有効にしないでください。
CSSとJSの最適化はどうやって確認しますか?
Lighthouseで3つのauditを確認します。未使用のJavaScriptの削除、未使用のCSSの削除、メインスレッドの作業量の削減です。目標は未使用CSSが20KB未満、未使用JSが50KB未満、メインスレッドの作業時間が200ms未満です。次にDevToolsのNetworkでトップページのCSSリクエスト数が2〜3個、JSリクエスト数が3〜4個に減っていること、コンソールに赤字のエラーがないことを確認します。最後にCrUXでFCPの75パーセンタイルが1.8秒以下かどうかを見ます。

六、リソースヒント:preload、preconnect、dns-prefetchの使い方

振り分け以外にもう一层の最適化がリソースヒント(resource hints)です。preloadはファーストビューで必ず使う重要なリソース、たとえばLCP画像、重要なフォント、ファーストビューのインタラクションJSに使います。headに<link rel=”preload” as=”image” href=”hero.webp”>と書くと、ブラウザが優先的に先読みします。preloadの乱用はよくある間違いです。何でもpreloadするのはpreloadしないのと同じで、ブラウザのスケジューラが汚染されるからです。1ページのpreloadは3リソースまでにしましょう。

preconnectはサードパーティドメイン、つまりCDN、フォント配信、解析サービスのドメインに対して使い、headに<link rel=”preconnect” href=”https://cdn.example.com”>を追加すると、ブラウザが先にDNS、TCP、TLSハンドシェイクを済ませ、実際にリソースを要求するときに300〜500ミリ秒を節約できます。dns-prefetchはpreconnectの簡易版で、DNS解決だけを行い、古いブラウザで使います。具体的な設定例は、独立サイトのheadでCDNドメインとフォントドメインにそれぞれpreconnectを1つ追加し、その他のサードパーティドメインにはdns-prefetchだけを追加する形です。

ヒントの種類 役割 対象リソース 上限数
rel=preload 優先度の高いものを先にダウンロード LCP画像、重要なフォント、ファーストビューのJS 1ページにつき3つまで
rel=preconnect DNS/TCP/TLSを先に完了 CDN、フォント、サードパーティAPIのドメイン 1ページにつき4つまで
rel=dns-prefetch DNSの事前解決のみ 重要度の低いサードパーティドメイン 制限なし、古いブラウザ向けの簡易版
rel=prefetch アイドル時に次のページを先読み ユーザーが次に開きそうなページ 慎重に、帯域の無駄遣いになる

最後に

CSS/JS最適化の本質は振り分けであり、すべてを圧縮することではありません。ファーストビューで必ず使うものはインライン化するかpreloadし、それ以外はすべてファーストビューの描画が終わるまで遅らせます。この考え方が整理できていれば、ツールはあくまで実現手段です。整理できていなければ、プラグインをいくら入れても問題の場所が変わるだけです。

実行は3ステップ。1つ目は、今週Lighthouseでトップページを計測し、未使用のCSS/JSの2つのauditを確認します。2つ目は、AutoptimizeかWP Rocketを有効にしてminifyと結合を行いますが、控えめに設定し、まずコンソールにエラーが出ないことを確認します。3つ目は、ファーストビューのCSSをクリティカルCSSとしてインライン化し、解析とチャットのスクリプトに遅延を加えます。2週間後にFCPとTBTを再計測します。

覚えておきたい一言。CSS/JS最適化の目標はファイル数を減らすことではなく、ファーストビューの1.8秒の間に、ブラウザが今すぐ必要なバイトだけを受け取れるようにすることです。

环形山
环形山 クレーター専門家

公式アカウント · 環形山 Crater

環形山(Crater)は、WordPress独立サイト開発+Google SEO+GEO全域成長に特化した海外展開支援会社で、スマートハードウェア、産業機器、SaaS、新エネルギーなどの分野を手がけています。

プロダクト能力方法論ホワイトペーパー業界レポート
965件のシェア
78件のナレッジベース