最近、Chrome のデベロッパー コンソールに次のような警告が表示され、その内容が不明だった場合は、以下をご覧ください。
(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.
コンポーザビリティはウェブの大きな強みの一つです。サードパーティが構築したサービスと簡単に統合して、優れた新しいプロダクトを構築できます。コンポジビリティの欠点の一つは、ユーザー エクスペリエンスに関する責任を共有することです。統合が最適でない場合、ユーザー エクスペリエンスに悪影響が及ぶ可能性があります。
パフォーマンスが低下する原因として、ページ内での document.write()
の使用(特にスクリプトを挿入する使用)が知られています。以下は問題ないように見えますが、ユーザーに実際の問題を引き起こす可能性があります。
document.write('<script src="https://example.com/ad-inject.js"></script>');
ブラウザはページをレンダリングする前に、HTML マークアップを解析して DOM ツリーを構築する必要があります。パーサーはスクリプトに遭遇するたびに、HTML の解析を続行する前に、スクリプトを停止して実行する必要があります。スクリプトが別のスクリプトを動的に挿入すると、パーサーはリソースのダウンロードをさらに長く待機する必要があります。これにより、1 つ以上のネットワーク ラウンドトリップが発生し、ページの最初のレンダリング時間が遅れる可能性があります。
2G などの低速接続でアクセスするユーザーの場合、document.write()
で動的に挿入される外部スクリプトによって、メインページのコンテンツが表示されるまでに数十秒の遅れが生じたり、ページで読み込めなかったり、時間がかかりすぎてユーザーがページを離れてしまったりする可能性があります。Chrome のインストルメンテーションに基づいて、document.write()
を介して挿入されたサードパーティ スクリプトを含むページでは、通常、2G で接続した場合の読み込み速度が他のページよりも 2 倍遅くなることがわかりました。
2G 接続のユーザーに限定して、Chrome 安定版ユーザーの 1% を対象とした 28 日間のフィールド トライアルからデータを収集しました。2G でのすべてのページ読み込みの 7.6% に、トップレベル ドキュメントの document.write()
を介して挿入された、クロスサイトのパーサー ブロッキング スクリプトが 1 つ以上含まれていました。これらのスクリプトの読み込みをブロックした結果、読み込みに次のような改善が見られました。
- コンテンツの初回ペイント(ページが効果的に読み込まれていることをユーザーに視覚的に確認させるもの)に到達するページ読み込みが 10% 増加し、完全に解析された状態に到達するページ読み込みが 25% 増加し、再読み込みが 10% 減少したことから、ユーザーの不満が軽減されたことがわかります。
- First Contentful Paint までの平均時間が 21% 短縮(1 秒以上短縮)
- ページの解析にかかる平均時間が38% 短縮され、6 秒近く改善されました。これにより、ユーザーにとって重要な情報を表示するまでの時間が大幅に短縮されました。
このデータを踏まえ、Chrome バージョン 55 以降では、この既知の不正なパターンを検出すると、Chrome で document.write()
の処理方法を変更して、すべてのユーザーに代わって介入します(Chrome ステータスを参照)。具体的には、次の条件がすべて満たされている場合、Chrome は document.write()
を介して挿入された <script>
要素を実行しません。
- 接続速度が遅い場合(特に 2G を使用している場合)。(今後、この変更は、低速の 3G や低速の Wi-Fi など、低速の接続を使用している他のユーザーにも適用される可能性があります)。
document.write()
は最上位ドキュメントにあります。iframe 内の document.written スクリプトはメインページのレンダリングをブロックしないため、この介入は適用されません。document.write()
のスクリプトはパーサー ブロックです。async
属性またはdefer
属性を持つスクリプトは引き続き実行されます。- スクリプトが同じサイトにホストされていない。つまり、eTLD+1 が一致するスクリプト(js.example.org でホストされ、www.example.org に挿入されたスクリプトなど)に対して、Chrome は介入しません。
- スクリプトがブラウザの HTTP キャッシュにまだ保存されていない。キャッシュ内のスクリプトにはネットワーク遅延が発生せず、引き続き実行されます。
- ページのリクエストは再読み込みではありません。ユーザーが再読み込みをトリガーした場合、Chrome は介入せず、通常どおりページを実行します。
サードパーティ スニペットでは、document.write()
を使用してスクリプトを読み込むことがあります。幸い、ほとんどのサードパーティは非同期読み込みの代替手段を提供しています。これにより、ページの残りのコンテンツの表示をブロックすることなく、サードパーティ スクリプトを読み込むことができます。
どうすればよいですか?
簡単な答えは、document.write()
を使用してスクリプトを挿入しないことです。Google は、非同期ローダのサポートに関する既知のサービスを維持しています。このリストは定期的に確認することをおすすめします。
ご利用のプロバイダがリストに記載されておらず、非同期スクリプト読み込みをサポートしている場合は、お知らせください。ページを更新してすべてのユーザーに役立てさせていただきます。
ご利用のプロバイダが、ページにスクリプトを非同期で読み込む機能をサポートしていない場合は、プロバイダに連絡して、影響を受けることをGoogle とプロバイダに伝えることをおすすめします。
プロバイダから document.write()
を含むスニペットが提供されている場合は、スクリプト要素に async
属性を追加するか、document.appendChild()
や parentNode.insertBefore()
などの DOM API を使用してスクリプト要素を追加できます。
サイトが影響を受けているかどうかを確認する方法
制限が適用されるかどうかを判断する基準は多数あるため、制限の対象となるかどうかを判断するのは難しい場合があります。
ユーザーが 2G を使用しているかどうかを検出する
この変更がもたらす影響を把握するには、まず 2G を使用するユーザーの数を把握する必要があります。Chrome で利用可能な Network Information API を使用して、ユーザーの現在のネットワーク タイプと速度を検出し、分析システムまたはリアルユーザー測定(RUM)システムにヘッドアップを送信できます。
if(navigator.connection &&
navigator.connection.type === 'cellular' &&
navigator.connection.downlinkMax <= 0.115) {
// Notify your service to indicate that you might be affected by this restriction.
}
Chrome DevTools で警告をキャッチする
Chrome 53 以降、問題のある document.write()
ステートメントに対して DevTools で警告が表示されます。具体的には、document.write()
リクエストが条件 2 ~ 5 を満たしている場合(Chrome は、この警告を送信する際に接続条件を無視します)、警告は次のようになります。
Chrome DevTools で警告を確認することはできますが、これを大規模に検出するにはどうすればよいでしょうか。介入が発生したときにサーバーに送信される HTTP ヘッダーを確認できます。
スクリプト リソースの HTTP ヘッダーを確認する
document.write
経由で挿入されたスクリプトがブロックされると、Chrome はリクエストされたリソースに次のヘッダーを送信します。
Intervention: <https://shorturl/relevant/spec>;
document.write
を介して挿入されたスクリプトが見つかり、さまざまな状況でブロックされる可能性がある場合、Chrome は次のことを送信することがあります。
Intervention: <https://shorturl/relevant/spec>; level="warning"
介入ヘッダーは、スクリプトの GET リクエストの一部として送信されます(実際の介入の場合は非同期)。
未来に待ち受けているものとは
最初の計画では、条件が満たされたことを検出したときにこの介入を実行します。最初は、Chrome 53 のデベロッパー コンソールに警告のみを表示していました。(ベータ版は 2016 年 7 月にリリースされました。安定版は 2016 年 9 月にすべてのユーザーが利用できる予定です)。
2016 年 10 月中旬にすべてのユーザー向けに安定版がリリースされる予定の Chrome 54 以降、2G ユーザー向けに挿入されたスクリプトをブロックする措置を講じます。最新情報については、Chrome のステータスに関する記事をご覧ください。
今後、ユーザーの接続が遅い場合(3G や Wi-Fi が遅い場合など)に介入する予定です。こちらのChrome ステータスのエントリをご覧ください。
もっと詳しく知りたい場合
詳細については、以下のリソースをご覧ください。