ページ速度のためのJavaScriptアセットの最適化

公開: 2020-05-05

以下の例は、大規模で複雑なニュースWebサイトからのものです。 彼らは何年もの間有機的なトラフィックを失っています。 それらのDOMContentLoadedイベントのタイミングは2615.2MSです。 DOMのサイズは非常に大きいと思われるかもしれませんが、そうではありません…

これはGoogleが推奨するものとほぼ同じであり、このドキュメントには1230個のHTMLノードしか存在しません。

DevToolsを使用して、domContentLoadedイベントのタイミングとプロセスを計算し、競合他社と比較できます。

この例を調べると、DOMサイズが必ずしも重要なポイントではないことがわかります。 ここでの主な問題はリソースの順序です。「メインタブ」の青い部分はHTML解析用です。 ただし、このWebサイトは、HTML解析プロセスが終了する前に、JavaScriptレンダリングでブラウザーを中断します。

(コールツリーセクションを使用して、ITチームの同様の間違いを見つけるのに役立てることもできます。)

この例は、JavaScriptアセットを最適化することの重要性と、ページ速度の最適化でJavaScriptを無視すると何がうまくいかないかを明確に示しています。

これは、一連の4つの記事の3番目です。 この記事をよりよく理解するために、シリーズの最初の2つの記事を読むことをお勧めします。

  • Javascriptのレンダリングとページ速度は、ブラウザのレンダリングエンジンがWebページを作成する方法と密接に関連しています。
  • この記事に入る前に、高度なページ速度メトリックも理解する必要があります。

最初の2つの記事のいくつかの例を使用して、この記事のコンテキストを提供します。

Javascriptレンダリングとは何ですか?それがページ速度にどのように影響しますか?

Javascriptレンダリングは、DOMとCSSOMを使用して作成された構造をインタラクティブに変更できる最後のページ読み込みセクションです。 すべてのページ要素は、ユーザーがトリガー可能な形式で変更することも、通常どおりに表示することもできます。 レンダリングツリーからアクセスできなかったdisplay:noneプロパティを持つ要素は、JavaScriptで表示したり、さまざまなHTML要素を介してDOMに挿入したりできます。

JavaScriptは、ブラウザによる読み取り時にDOMとCSSOMを変更するため、DOMとCSSOMに割り込みます。 したがって、ページの読み込み時間と速度に悪影響を与えないようにするには、DOM、CSSOM、およびJavaScriptレンダリングの関係を調べる必要があります。

上記はレンダリングツリーの例です。 CSSOMノードとHTMLノードのすべての連動するコードスニペットには、レンダリングツリーに同等のセマンティックがあります。 注意深く見ると、「アクションボタン」HTMLノードがレンダリングツリーにないことがわかります。 この主な理由は「display:none;」です。 CSSプロパティ。 この非表示コマンドのため、レンダリングツリーには含まれていません。 このツリーの要素がどのように構築されたかを確認するには、このシリーズの最初の記事を読むことをお勧めします。

ユーザーの動作に依存するために最初の読み込みで表示されないページ要素が多数ある場合は、リソースの読み込み順序で、これらの項目を分離して最後の行に配置する必要があります。 現時点では、シャドウDOMまたは仮想DOMを使用することをお勧めします。

JavaScriptリソースの延期および非同期属性

JSファイルをセクションに配置し、「defer」または「async」属性を使用しない場合、おそらくDOMContentLoaded時間が遅れます。 この状況を防ぐために、これら2つの属性を使用する場合があります。 DeferはJSファイルのロードプロセスを遅らせることであり、「Async」はJSと他のソースを並行してロードすることです。 どちらにも長所と短所があります。 ここでは主なものについてのみ説明します。

  • メインのJSファイルでdeferを使用する場合、インストールされるまで、その「イニシエーター」効果はおそらく表示されません。
  • deferを使いすぎると、ページロードの最後にCPUボトルネックが発生する可能性があります。

この記事が書かれたので、Chrome80アップデートがリリースされました。 [イニシエーター]列で、どのリソースがどのリソースによって呼び出されているかを確認するのがはるかに簡単になりました。 たとえば、JSによって呼び出された画像またはCSSファイルを見ることができます。 Shiftキーを押しながらリソースをスクロールすると、他のリソースをロードしないと使用できないリソースも表示されます。

Shiftキーを押しながらスクロールする:赤い色は、緑で強調表示されているリソースの条件付きリソースを示します。

Chromeの新しいイニシエーターセクションを使用して、リソースの読み込み順序、イニシエーター、優先度の詳細を確認することもできます。 これにより、以下のような非常に長くてコストのかかるJSコールチェーンを検出できます。

同じサイトからの長くて費用のかかるJSコールチェーンの例。 選択したリソースの上には、そのイニシエーターがあります。 次の部分は、選択したリソースによって開始されたリソースを示しています。

  • 遅延JSファイルはdomInteractiveイベントの後にダウンロードされるため、CSSファイルと画像に応じて選択する必要があります。
  • 一部のユーザートラッカーのサードパーティJSファイルを延期すると、特定のユーザーの行動を追跡できない場合があります。
  • 通常、DeferはDOMプロセスをブロックしませんが、Asyncはブロックします。 非同期属性を持つJSファイルは、HTML解析およびCSSOM処理中にブラウザーによってダウンロードされます。
  • async属性を使いすぎると、CPU処理のボトルネックが発生し、DOMおよびCSSOMプロセスの速度が低下する可能性があります。 何を延期または非同期にするかを慎重に選択する必要があります。

非同期属性と延期属性のスキーム例を次に示します。 最初のものは、フェッチ中にHTML解析を分割せずに、domContentLoadedの前にロードされます。 2番目の例では、フェッチされたJSファイルは、HTMLの解析が完了する前に実行されません。

Javascriptのレンダリングとパフォーマンスに関する提案とヒント

実例に入る前に、JavaScriptレンダリングのパフォーマンスを改善するためのいくつかの提案があります。 これは、ページ速度とブラウザの動作をよりよく理解するのにも役立つ場合があります。

不要な変数は使用しないでください。

SEOの場合、JavaScriptファイルに不要な変数や未使用の変数があることに気付くかもしれません。 この種のエラーを検出するために使用できるツールはたくさんあります。 未使用の変数と不要な変数の2つの基本的な例を以下に示します。

var carName = brand +””+年;
document.getElementById(“ demo”)。innerHTML = carName;

ここでは、変数「carName」は不要です。 次の変更を提案できます。
document.getElementById(“ demo”)。innerHTML = brand +”” + year

または:

[a、b、c、d、e] .forEach(function(value、index){
console.log(index);
});

ここでは、「value」パラメータは使用されていないため、必要ありません。 あなたはそれを削除することができます:
[a、b、c、d、e] .forEach(function(index){
console.log(index);
});

右側では、「非同期」Javascriptのおかげで、接続時間が長くなり(白い線)、CSSファイルとJSファイルが非対称の順序で読み込まれていることがわかります。

左側では、各ソースが行にロードされるため、接続時間が短くなり、CSSファイルとJSファイルが混在していません。 非同期属性はTBT時間を延長する可能性があるため、スピードインデックスを低下させる可能性があるため、調査を実行して、[パフォーマンス]タブからパフォーマンストラッカーJSファイルについて開発者チームに報告するか、自分でいくつかの実験を実行する必要があります。

難しいタスクにツールを使用する

コードの初心者にとって、不要または未使用の変数を見つけるのは難しい場合があります。 Chrome DevToolsやUnused(Kami / node-unused:定義されているが、コード内の未使用の変数を報告するモジュール、またはより多くの未使用の変数)などのNode.jsパッケージなど、これらのタスクにいくつかのツールを使用することをお勧めします。 小さなエラーが見つかった場合でも、ITチームがJavaScriptファイルを改善するためにあなたの話を聞いてくれると思います。

Chrome DevToolsカバレッジレポートを使用して、未使用のJavaScriptコードを検索する

Chrome DevToolsカバレッジレポートには、未使用のJavaScriptコードスニペットが表示されますが、あまり実用的ではありません。 コードからすべての赤い部分を削除できると思うかもしれませんが、そうではありません…代わりに、多数のカテゴリページに対して完全に未使用の関数または変数を見つける必要があります。 このようにして、開発者チームはTreeShakingプロセスを使用することを確信できます。

TreeShakingは、ファイルからデッドコードを削除することを意味します。 時間を稼ぐために、未使用のJS変数と関数ファインダーパッケージを使用して学習することをお勧めします。

DOMサイズを小さくすると、JavaScriptのレンダリングにも役立ちます。 すべての(getElementsByTagName)コマンドはDOMをスキャンします。 DOMサイズが小さいほど、JavaScriptをレンダリングするときに、ブラウザーとデバイスのCPU/ネットワークから必要なリソースが少なくなります。

新しいChrome80アップデートでは、カバレッジレポートにも変更が加えられました。 オプションの機能ごととブロックごとの選択肢が追加されました。 ここでは、ブロックごとがデフォルト値です。

関数ごとを選択すると、レポートに大きな違いが見られます。 この状況の主な理由は、関数ごとのビューがすべての関数が使用されているかどうかをチェックすることです。 関数の95%が使用されている場合、関数の大部分は使用されますが、コードの5%は使用されないため、[関数ごと]オプションはそれを未使用のコードとして定義します。

JSファイルを圧縮、縮小、またはUglifyします。

これは2つの方法で行うことができます。 まず、スペースと不要なコメントを削除します。 次に、JSファイルとマングル名、変数、すぐに使えるテクノロジーを備えた関数に、改善されたJavaScript演算子を使用します。

この種の圧縮の矢印関数について知っておく必要があります。 たとえば、この84文字の例の代わりに:

関数矢印Islev(a、b){
console.log(a + b);
}
arrowFonksiyon(5、6);

矢印関数を使用して、50文字のみに圧縮できます=>
const ab =(a、b)=> b + a;
console.log(ab(5、6));

別の短縮/圧縮メソッドは、Ifステートメントに有効です。 63文字のこのコードスニペットの代わりに:
if(a <b){
console.log(ab);
}
そうしないと {
console.log(a + b);

以下の43文字のものを使用できます。
(a <b)? console.log(ab):console.log(a + b);

ITチームに、圧縮に$と_の記号を使用することを提案することもできます。 ほとんどのJavaScriptファイルはDOMを再解釈するために機能します。 これに対して、たくさんのdocument.getElementById(x);が表示される場合があります。 ファイル内のコードスニペット。 このタスクには$記号を使用できます。 これにより、無駄なサイズの膨大な山からあなたを救うことができます。

ほとんどのJavaScriptライブラリは、関数定義にデフォルトで$を使用しますが、$も英字であるため、すべてではありません。

この状況では、ITチームが以下を使用することを提案できます。
function $(x){return document.getElementById(x);}。

適切なレンダリングタイプを使用する

SEOの互換性に関するJavaScriptとWebページのレンダリングタイプ。
SSR Hydrationは、一部のJSコンポーネントがクライアント側レンダリングを使用してレンダリングされることを意味します。 これはFPおよびFMPには役立ちますが、TTIおよびスピードインデックススコアにはいくつかの欠点がある可能性があります。
画像ソース:Notprovided.eu

JavaScriptレンダリングパフォーマンスのコーディングのベストプラクティス

  • もう1つの重要な圧縮の寄与は、「_」の使用によるものです。 「underscore.js」を使用して、JavaScriptの書き込み形式と関数を改善できます。 このようにして、組み込みのJS関数を使用せずに短いJS関数を使用してリストやコレクションを操作しながら、より小さなJSファイルを作成します。
  • 長くて疲れ果てた変数の変更やグローバル変数の汚染をたくさん使用することも、レンダリングが遅くなる原因です。 関数の一般的なスコープの選択とグローバル変数/long変数の型を決定する必要があります。 'Let'でローカル変数を使用すると、レンダリングに適しています。 ローカル変数があるため、ブラウザは他のグローバル関数(次の変更のための変数)を監査しません。

たとえば、ローエンドの携帯電話で見られるような、より現実的なパフォーマンス検査をシミュレートするには、ChromeDevToolsのCPUスロットリングと高速/低速3G接続の設定を使用する必要があります。
画像出典:Addy Osmani

  • より小さなJS関数と変数チェーンを使用すると、レンダリングパフォーマンスが向上します。 さらに、「with」セレクターの代わりに「this」セレクターを使用する方が適切です。 Javascriptの「this」セレクターは「with」とは異なりローカルで機能するコードであり、letとvarを使用した同じロジックがここでも有効です。
  • Forループコードスニペットでステートメントを使用すると、レンダリング速度も少し遅くなります。 関数ステートメントはループの各要素を反復処理するためです。 ループ要素の新しい変数を作成するだけで、Forループの外側にある関数を使用してこれらの要素を呼び出すことができます。
  • HTML要素に何度もアクセスしたい場合は、その変数を作成して、必要な関数を使用して呼び出すことができます。 JavaScriptを使用してHTML要素に到達することは、高速なプロセスではありません。 あなたは単にあなたのブラウザにより多くの負担をかけるかもしれません。

Javascriptレンダリングのパフォーマンスを向上させる別の方法は、ServiceWorkerを介したTrisomorphicレンダリングです。 将来のセッションのために、JSファイルの一部をクライアントのブラウザメモリに入れることができます。 このようにして、Webサイトをオフラインで機能させることができます。
ここで、サービスワーカーとの理解を深め、練習するための簡単なデモを見つけることができます。

それを縛る:JavaScriptとページ速度の最適化がSEOにどのように影響するか

JavaScriptアセットがページの速度を妨害しないようにするために、DeferとAsyncがどのように大きな違いを生むかを見てきました。 また、JavaScriptアセットを使用してページの速度を向上させるのに役立つ「デバッグ」戦略とコーディングのヒントをいくつか見てきました。

ブラウザがWebページを構築する方法、ページ速度の測定と影響、およびJavaScriptの最適化がページの読み込み時間に果たす役割について説明したので、次の記事では、リソースの読み込み順序がページの速度とクロールの予算にどのように影響するかを示します。

この一連の4つの記事の以前の記事を確認することに興味がある場合は、次の場所で見つけることができます。

  • 「ブラウザはどのようにWebページを作成しますか」
  • 「高度なページ速度メトリック」。
無料トライアルを開始する