プロンプトとコンテキスト
あるEコマースの製品ページで、アナリティクス、チャット、広告、A/Bテストのスクリプトを読み込んでいます。モバイルの実ユーザーp75 LCPは3.8秒、INPは280ミリ秒であり、サードパーティ製JavaScriptは14個のオリジンから約1.2 MB転送されていますが、デスクトップのラボテストは良好に見えます。ネットワーク、メインスレッド、プライバシー、ページの可用性に対するサードパーティの影響を抑えつつ、必要なビジネス機能を維持しなければなりません。
まず4つの境界を明確にします。どのスクリプトがファーストビューの前に実行される必要があるか、どれがインタラクション後にのみ必要か、スクリプト同士の実行順序に依存関係があるか、同意前にデータを送信できるか、サードパーティの障害がチェックアウトをブロックする可能性があるかです。サードパーティ製コードはページの実行環境の一部であり、他チームが永久に所有する単なる静的アセットとして扱うことはできません。
これはフロントエンド、Webプラットフォーム、パフォーマンスエンジニアリングの面接に適した設問です。公開されているフロントエンド面接の教材では、async、defer、スクリプトの実行順序、パフォーマンスのトレードオフが頻出の基礎知識として扱われています。web.dev、MDN、W3Cのリソースは、読み込みタイミング、Long Tasks、CSP、ソース制御の技術的基盤を提供しています。この質問の中心は、特定のフレームワークコンポーネントの暗記ではなく、ガバナンスと検証の証明です。
面接官が見ているポイント
不十分な回答は「至る所にasyncを追加する」や「スクリプトをページ下部に配置する」といったものです。優れた回答では、ユーザー価値とクリティカルパスへの影響によってスクリプトを棚卸しし、依存関係と障害境界に基づいてasync、defer、モジュール、インタラクション駆動の読み込み、またはiframeファサードを選択します。
面接官は次の5つのシグナルを求めています:候補者がダウンロード時間と実行時間を区別できるか、順不同のasyncと順序維持のdeferの違いを説明できるか、パフォーマンスバジェット、同意、CSP/SRI、サプライチェーンリスクを組み合わせられるか、チェックアウトをブロックすることなくベンダーの障害を隔離できるか、そしてRUM、Long Tasksデータ、対照比較を使用して変更を証明できるかです。
Lighthouseのスコアだけでは不十分です。ラボ環境の条件は、ローエンド端末、低速ネットワーク、コンテンツブロッカー、応答が停止したベンダーサーバーを反映していません。回答には実ユーザーのパーセンタイル、スクリプト実行時間、ビジネス完了率を含める必要があります。
最初に確認すべき明確化のための質問
- ファーストペイントや初回インタラクションに真に必要なスクリプトはどれですか? 決済や必須の不正検知はクリティカルな場合がありますが、チャット、レコメンド、セッションリプレイは通常、インタラクションやアイドル時まで遅延できます。
- スクリプト間に依存関係はありますか? 独立したアナリティクスには
asyncを使用できます。DOMや順序に依存するアプリケーションコードには通常deferを使用します。未知の依存関係を持つものを並列化してはいけません。 - 同意前に何が許可されていますか? スクリプト、Cookie、ネットワークリクエスト、匿名計測を作成する前に、目的、地域、同意状態を定義します。
- ベンダーがアクセスできるページデータは何ですか? 同一オリジンのコードはページのコンテキストを読み取ることができます。チャットや広告が表示のみを必要とする場合は、権限サーフェスがより小さいiframeまたはサーバーサイドイベントを優先します。
- 障害発生時のユーザー体験はどうなりますか? 購入、ログイン、ナビゲーションにはファーストパーティのパスが必要です。ベンダーのタイムアウトによって重要なボタンやメインスレッドが無期限に待たされることがあってはなりません。
- ベンダーを置き換えるか、セルフホストできますか? セルフホストによりDNSやベンダーの可用性リスクを排除できる場合がありますが、更新、整合性、ライセンス、キャッシュの管理責任が生じます。自動的に安全になるわけではありません。
30秒の回答フレームワーク
「ビジネス価値、依存関係、バイト数、リクエスト数、メインスレッド時間、データの目的、障害時の影響を記録したインベントリを作成し、各スクリプトをクリティカル、遅延可能、削除可能に分類します。独立したスクリプトにはasyncを使用し、DOMや順序に依存するスクリプトにはdeferを使用し、インタラクティブなウィジェットにはファサードやiframeを使用します。同意前に非必須のトラッカーは作成しません。CSPでレビュー済みのオリジンのみを許可し、固定アセットにはSRIを使用します。各ベンダーにバイト数、実行時間、エラーのバジェットを設定します。RUMを用いて、デバイスや同意状態ごとにLCP、INP、Long Tasks、コンバージョン率、スクリプトエラーを比較します。まず削除や遅延を段階的にロールアウトし、フォールトインジェクションとロールバックを使用してページがコアタスクを完了できることを証明します。」
ステップごとの詳細な回答
1. インベントリの構築とクリティカルパスの特定
各スクリプトのベンダー、バージョン、トリガー、依存関係、リクエスト元、転送バイト数、パースおよび実行時間、Long Tasks、読み取られるデータ、オーナー、削除条件を記録します。「体験を向上させる」ではなく、「チェックアウト失敗の原因を特定する」といった検証可能な成果として価値を明記します。明確な目的、オーナー、メトリクスがないスクリプトは削除候補です。
ファーストペイントと初回インタラクションの依存関係グラフを作成します。初期画面、ログイン、カート、決済に必要なファーストパーティコードのみをクリティカルパスに残します。アナリティクス、チャット、レコメンド、リプレイ、マーケティングタグは、多くの場合ペイント後や明示的なインタラクション後まで待つことができます。非同期ダウンロードを行っても、パース、コンパイル、メインスレッドでの実行コストは排除されません。
2. 依存関係に基づく読み込みセマンティクスの選択
属性のないクラシックスクリプトはHTMLのパースをブロックします。asyncは並列でダウンロードされ、準備ができ次第実行されるため、順序の保証はありません。これは独立したアナリティクスや広告に適しています。deferも並列でダウンロードされますが、パース完了後にドキュメント順で実行されるため、DOMや他のスクリプトを必要とするコードに適しています。モジュールスクリプトはデフォルトで遅延されますが、その依存関係グラフは依然としてレビューが必要です。
決定表を活用します:
| 方式 | 実行タイミング | 実行順序 | 適した用途 | 主なリスク |
|---|---|---|---|---|
| 通常のクラシックスクリプト | ダウンロード後に実行されパースをブロック | ドキュメント順 | まれな同期的ブートストラップ | パースとファーストペイントを遅延 |
async | ダウンロード完了時に実行 | 保証なし | 独立したアナリティクス、広告、シンプルなウィジェット | パースを中断する可能性、依存関係の競合 |
defer | パース完了後に順番に実行 | 維持される | DOMや起動に依存するコード | DOMContentLoadedを依然として遅延 |
| インタラクション駆動 | ユーザーのアクションまたはアイドル時 | ローダー制御 | チャット、地図、動画、リプレイ | 初回展開時に追加のレイテンシ |
| iframeファサード | 最初に静的シェル、後から分離して埋め込み | ドキュメント間境界 | 動画、決済UI、複雑なウィジェット | 通信コストとアクセシビリティの課題 |
依存関係のあるスクリプトすべてにasyncを付与してはいけません。plugin.jsがvendor.jsを必要とする場合、ダウンロードタイミングの偶然に頼るのではなく、順序が保証されたdefer、モジュールインポート、または明示的なローダーを使用します。
3. 機能の遅延、削減、または置き換え
クリティカルでない処理には、ユーザーインタラクション、タイムアウトフォールバック付きのrequestIdleCallback、またはペイント後のキューを使用します。チャットボタンは、クリック時にのみウィジェットを生成するファーストパーティの静的な入り口にすることができます。動画は、iframeを埋め込む前にサムネイルと再生コントロールを表示できます。これにより、初期画面のネットワークおよびメインスレッドの処理が軽減され、ユーザーが使用しない機能へのコスト支払いを回避できます。
重複したタグマネージャー、アナリティクスSDK、放置された実験を削除します。ベンダーに対して、軽量ビルド、ページ専用バンドル、圧縮、キャッシュの適用を要求します。セルフホストはサードパーティのDNSや可用性リスクを軽減できますが、バージョン更新、SRI、ライセンス管理、キャッシュの無効化、ロールバックの運用が必要となり、実行コスト自体をなくすわけではありません。
4. プライバシー、セキュリティ、障害境界の定義
同意が得られる前に、非必須のトラッキングスクリプトを作成したり、それらを読み込んで後から送信のみを無効化したりしてはいけません。同意が撤回された場合に、Cookieがクリアされ、キューが停止し、以降のリクエストが防止されるかどうかを定義します。CSPのscript-srcおよび関連する接続ディレクティブでオリジンを制限し、バージョン固定の外部リソースにはSRIを使用します。最初のドメインのみを信頼するのではなく、動的読み込み、ベンダーが読み込む依存関係、strict-dynamicを個別に監査します。
同一オリジンで実行されるサードパーティコードは広範な権限を持ちます。描画のみを行うコンポーネントはiframe内に配置し、postMessageを介して最小限のフィールドのみを送信します。購入、ログイン、ナビゲーション、エラーリカバリはファーストパーティで保持し、コアフローをブロックする代わりに、タイムアウト、サーキットブレーカー、またはプレースホルダーでベンダーのタイムアウトを終了させます。
5. バジェットの設定とモニタリング
ベンダーおよびページタイプごとに、転送バイト数、リクエスト数、メインスレッド実行時間、Long Tasks、エラー率、LCP/INPへの寄与度に対するバジェットを設定します。バジェットの超過は、将来のクリーンアップタスクではなく、レビューや自動デグラデーション(機能縮退)のトリガーとします。平均値はロングテールを隠してしまうため、ローエンド端末、低速ネットワーク、同意状態ごとにバジェットをセグメント化します。
ラボ環境では、DevToolsのPerformanceパネルとNetworkパネル、WebPageTest、フォールトインジェクションを使用して、パース、実行、Long Tasks、単一障害点を観察します。本番環境では、RUMを使用してソース、リソースタイミング、PerformanceObserverのLong Tasks、LCP、INP、CLS、コンバージョン、エラーを記録します。トラフィック構成の変化を最適化と誤認しないよう、デバイス、ブラウザ、地域、ページテンプレートのセグメントを比較します。
6. ベンダー変更のロールアウト、ロールバック、ガバナンス
まず1つのページテンプレートとモバイルトラフィックのごく一部を対象に段階的リリース(カナリアリリース)を行います。すべてのスクリプト変更にはバージョン、ソース、同意設定、ロールバックスイッチが付与され、ベンダーの更新も同じ経路をたどります。スクリプトがタイムアウトしたり例外をスローしたりした場合は、無制限にリトライするのではなく、スキップするかデフォルトでデグラデーションします。ロールバック時は、ベンダーのURLから未知のバージョンを取得するのではなく、最後にレビュー済みのマニフェストを復元します。
不変条件を検証します:ベンダーに障害が発生してもユーザーが閲覧、カート追加、購入を行えること、同意なしに制限対象データが要求されないこと、スクリプトのバジェットが制限値内に収まっていること、CSPレポートに新しいオリジンが表示されないこと、重要なインタラクションのINPが悪化しないことです。各ベンダーに対して明示的な削除または置き換えの基準を維持します。
7. 検証を実行可能にする
低速DNS、ベンダーの5xxエラー、途中で中断されたダウンロード、スローされた例外、メインスレッドのLong Task、同意の撤回、サードパーティCookieの無効化、コンテンツブロッカー、レガシーブラウザをテストします。視覚的なレンダリングだけでなく、購入状態、リカバリ、キーボード操作、スクリーンリーダーの読み上げ、データリクエストの境界もアサートします。
コンテンツとトラフィックのルールを一定に保ちながら、同期的から遅延への変更など読み込み戦略を1つだけ変更したコントロールグループ(対照群)を使用します。p75/p95のLCP、INP、Long Tasks、リソースバイト数、コンバージョン、ベンダーエラーを検証します。チェックアウトが改善したもののチャットの展開が遅くなった場合は、単一の都合の良いスコアを報告するのではなく、トレードオフを報告してトリガーを調整します。
高品質な回答サンプル
「14個すべてのスクリプトにいきなりasyncを追加することから始めるのではなく、各スクリプトの目的、依存関係、リクエスト、バイト数、メインスレッド時間、データ使用状況、オーナー、障害時の影響を棚卸しし、クリティカル、遅延可能、削除可能に分類します。決済とログインはファーストパーティのクリティカルパスに残し、独立したアナリティクスは非同期に、DOMや順序に依存するコードにはdeferを使用し、チャット、地図、動画はインタラクション時またはiframeファサードの背後で読み込みます。
同意前には非必須のトラッカーを作成しません。CSPでレビュー済みのソースを許可し、固定アセットにはSRIを使用します。描画専用ウィジェットはiframe内に配置し、購入やナビゲーションにはファーストパーティのフォールバックを維持します。すべてのベンダーにバイト数、実行時間、Long Tasks、エラーのバジェットを設定します。
変更はモバイルの小規模なコホートへ段階的に適用します。ラボではネットワークをスロットリングし、Performanceトレースを検査し、ベンダー障害を注入します。本番環境ではRUMをデバイス、地域、同意状態ごとにセグメント化し、LCP、INP、CLS、Long Tasks、リソースタイミング、コンバージョン、エラーを比較します。すべての変更はロールバック可能とし、ベンダーの更新はレビュー対象とします。ベンダーがダウンしてもコアの購入機能は動作し続け、同意前にデータが送信されたりガードレールがバジェットを超過したりした場合は展開を停止します。」
よくある間違い
- すべてのスクリプトに
asyncを付与する → 依存関係のあるスクリプトが順不同で実行され、実行処理がパースを中断する可能性があります → 依存関係をマッピングし、独立した処理にはasync、順序が重要な処理にはdeferまたはモジュールを使用します。 - タグをbodyの末尾に移動するだけにする → ダウンロードと実行が依然としてメインスレッドを圧迫し、インタラクションが劣化する可能性があります → 機能に応じて遅延、削減、分割、トリガー設定を行い、実行コストを測定します。
- Lighthouseのみを使用する → ラボ環境の条件では、ローエンド端末、低速ネットワーク、ベンダーの応答遅延が反映されません → 実ユーザーのパーセンタイル、Long Tasks、ビジネスメトリクスを比較します。
- 同意が拒否された後にトラッキングを無効化する → スクリプトはすでに実行されており、リクエストが送信されてしまっている可能性があります → スクリプトやネットワークリクエストを作成する前に同意を確認します。
- セルフホストを完全なセキュリティ対策として扱う → 更新、整合性、ライセンス、実行コストの課題は残ります → レビュー済みバージョン、SRI、CSP、バジェット、ロールバックを組み合わせます。
- 障害が発生したベンダーを成功するまでリトライし続ける → ベンダーが重要なページの単一障害点(SPOF)になってしまいます → タイムアウト、デグラデーション用プレースホルダー、ファーストパーティのコアパスを使用します。
フォローアップ質問と回答
フォローアップ1:アナリティクスがファーストビューのイベントを即座に送信する必要があります。クリティカルにできますか?
まず、それが本当にファーストペイント前に送信される必要があるかを確認します。ページビューイベントをペイント後にバッチ処理でき、ある程度の欠損が許容される場合は遅延させます。アトリビューションやコンプライアンスにより早期送信が必須である場合は、独立したasyncスクリプト、短いタイムアウト、小さなファーストパーティキューを使用し、レンダリングをブロックしないようにします。イベントの遅延とLCP/INPのビジネス価値を比較してバジェットを設定します。
フォローアップ2:ベンダーが動的URLのみを提供しています。SRIをどのように使用すればよいですか?
絶えず変化するコンテンツに対して信頼できるハッシュを固定することはできません。バージョン管理されたアセットを要求するか、セルフホストの署名付きリリースプロセスを構築するか、iframeやサーバーサイド連携で機能を分離します。CSP、アクセス監査、変更監視によってリスクを軽減します。偽のハッシュを使用したり、unsafe-inlineに置き換えたりしてはいけません。
フォローアップ3:deferを指定してもサードパーティスクリプトがLong Tasksを発生させています。次は何をすべきですか?
deferは実行タイミングを変更するだけであり、パースや実行の負荷を減らすわけではありません。Performanceトレースを使用してスクリプトとタスクを特定し、ベンダーにタスクの分割、インタラクション駆動への変更、機能の削除、またはiframeやサーバーサイドイベントへの処理の移行を要請します。どうしても実行する必要がある場合は、タイムアウトを設定してアイドル時に小さなチャンクでスケジューリングし、RUMでテールレイテンシを検証します。
フォローアップ4:マーケティング部門が一度に5つのタグを追加したいと言っています。どう答えますか?
各タグに対して、目的、オーナー、期待される意思決定、同意カテゴリ、パフォーマンスバジェット、削除条件の提示を求めます。重複したデータ収集がないか、既存のイベントですでに解決できないかを確認します。サンドボックスで測定し、価値が明確になってから段階的にリリースします。測定可能な価値がないタグやバジェットを超過するタグは本番環境に導入しません。