ウェブサイトのフロントエンドパフォーマンスの最適化: JavaScript と CSS

ウェブサイトのフロントエンドパフォーマンスの最適化: JavaScript と CSS

Yahoo チームが書いた、ウェブサイトのパフォーマンス最適化に関する記事を読みました。この記事は 2010 年頃に書かれたものです。少し古いものですが、多くの点で今でも非常に参考になります。 CSS のパフォーマンス最適化に関しては、次のような点を指摘しました。

CSSパフォーマンスの最適化

1. スタイルシートを先頭に配置する

スタイルシートをドキュメントの <head /> 内に配置すると、ページのダウンロードが高速化されるようです。これは、スタイルシートを <head /> に配置すると、ページが段階的に読み込まれて表示されるようになるためです。

パフォーマンス重視のフロントエンド サーバーでは、多くの場合、ページが順番に読み込まれることが求められます。同時に、受信したコンテンツをブラウザが可能な限り表示してくれることも期待しています。これは、コンテンツが多いページや接続速度が遅いユーザーにとって特に重要です。進捗状況ポインターなどの視覚的なフィードバックをユーザーに返すことは、十分に研究され、文書化されています。私たちの研究では、HTML ページがプロセス ポインターです。ブラウザがファイル ヘッダー、ナビゲーション バー、トップ ロゴなどを順番に読み込むと、ページの読み込みを待っているユーザーへの視覚的なフィードバックとして機能します。これにより、全体的なユーザー エクスペリエンスが向上します。

スタイルシートをドキュメントの下部に配置すると、Internet Explorer を含む多くのブラウザーでコンテンツが整然とレンダリングされなくなるという問題があります。ブラウザは、スタイルの変更によってページ要素が再描画されるのを避けるためにレンダリングを一時停止します。ユーザーは空白のページに直面します。

HTML 仕様では、スタイル シートはページの <head /> セクションに配置する必要があることが明確に規定されています。「<a /> とは異なり、<link /> はドキュメントの <head /> セクションにのみ表示できますが、複数回使用できます。」白い画面が表示されたり、スタイルが設定されていないコンテンツが表示されたりするので、試してみる価値はありません。最善の解決策は、HTML 仕様に従ってドキュメントの <head /> にスタイルシートを読み込むことです。

2. CSS式の使用を避ける

式の問題は、私たちが考えるよりも頻繁に評価されることです。ページを表示してズームするときだけでなく、ページをスクロールしたり、マウスを動かしたりしたときにも再計算する必要があります。 CSS 式にカウンターを追加すると、式が評価される頻度を追跡できます。ページ上でマウスを動かすだけで、簡単に 10,000 を超える計算を実行できます。

CSS 式の計算回数を減らす 1 つの方法は、初めて実行するときに結果を指定されたスタイル プロパティに割り当て、CSS 式の代わりにこのプロパティを使用する 1 回限りの式を使用することです。ページのライフサイクル中にスタイル プロパティを動的に変更する必要がある場合は、CSS 式の代わりにイベント ハンドラーを使用するのが有効な方法です。 CSS 式を使用する必要がある場合は、何千回も評価され、ページのパフォーマンスに影響を与える可能性があることに留意してください。

3. 外部JavaScriptとCSSを使用する

多くのパフォーマンス ルールは、外部ファイルの処理方法に関するものです。ただし、これらの手順を実行する前に、より基本的な質問をする必要があります。JavaScript と CSS は外部ファイルに配置する必要がありますか、それともページ自体に配置する必要がありますか?

実際には、JavaScript ファイルと CSS ファイルの両方をブラウザにキャッシュできるため、外部ファイルを使用するとページ速度が向上します。 HTML ドキュメントに埋め込まれた JavaScript と CSS は、リクエストごとに HTML ドキュメントとともに再度ダウンロードされます。これにより、HTTP リクエストの数は減りますが、HTML ドキュメントのサイズは増加します。一方、外部ファイル内の JavaScript や CSS をブラウザでキャッシュすると、HTTP リクエストの数を増やすことなく HTML ドキュメントのサイズを縮小できます。

重要な点は、外部の JavaScript および CSS ファイルがキャッシュされる頻度が、HTML ドキュメントが要求される回数に関連しているということです。多少難しいですが、それを測定できる指標はまだいくつかあります。ユーザーがセッション中にサイト上の複数のページを閲覧し、それらのページ間で同じスクリプトとスタイルシートが再利用される場合、外部ファイルをキャッシュするとより大きなメリットが得られます。

トラフィック量の多いホームページの場合、組み込みコードによる HTTP リクエストの削減と外部ファイルの使用によるキャッシュの利点のバランスをとることができる手法があります。その 1 つは、ホームページに JavaScript と CSS を埋め込むが、ページのダウンロード後に外部ファイルを動的にダウンロードすることです。これらのファイルがサブページで使用される場合、それらはすでにブラウザにキャッシュされています。

4. JavaScriptとCSSを減らす

縮小とは、コードから不要な文字を削除してファイル サイズを縮小し、ダウンロード時間を節約することを指します。コードを縮小するときは、すべてのコメント、不要な空白文字 (スペース、改行、タブインデント) などを削除する必要があります。 JavaScript では、ダウンロードする必要があるファイルのサイズが小さくなるため、応答時間が短縮されます。 JavaScript を縮小するために最も広く使用されている 2 つのツールは、JSMin と YUI Compressor です。 YUI Compressor は CSS を縮小するためにも使用できます。フロントエンドのデプロイメント、ant+YUI コンプレッサーに関する以前の記事のアドレスは次のとおりです: http://www.haorooms.com/post/ant_yuicom ガジェットでの ant の使用についても説明しています: http://www.haorooms.com/tools/ant_book/

難読化は、ソース コードの最適化に使用できるもう 1 つの方法です。このアプローチは簡略化よりも複雑であり、難読化プロセス中に問題が発生しやすくなります。米国のトップ 10 ウェブサイトの調査では、合理化によって元のコード サイズを 21% 削減できる一方、難読化によって 25% 削減できることが判明しました。難読化はコードの縮小には効果的ですが、JavaScript の場合、縮小化の方がリスクが低くなります。

外部のスクリプトおよびスタイルシート ファイルを縮小することに加えて、<script> および <style> コード ブロックも縮小できます。また、縮小する必要があります。スクリプトとスタイルシートを Gzip で圧縮した場合でも、それらのファイルを縮小すると 5% 以上のスペースを節約できます。 JavaScript と CSS の性能とサイズが増大するにつれて、コードを削減することが有益になります。

5. @importの代わりに使用する

以前のベストプラクティスでは、整然とした読み込みと表示を容易にするために、CSS を上部に配置する必要があると説明されていました。

IE では、ページ下部の @import は <link> を使用するのと同じ効果を持つため、使用しないことをお勧めします。

6. フィルターの使用を避ける

IE 固有のプロパティ AlphaImageLoader は、バージョン 7.0 未満で表示される PNG 画像の半透明効果を修正するために使用されます。このフィルターの問題点は、画像の読み込み中にコンテンツのレンダリングが停止し、ブラウザがフリーズしてしまうことです。画像だけでなく各要素ごとに一度計算されるため、メモリ使用量が増加するため、問題は多面的です。

AlphaImageLoader の使用を完全に回避する最善の方法は、代わりに IE で適切に動作する PNG8 形式を使用することです。 AlphaImageLoader を本当に使用する必要がある場合は、アンダースコア フィルターを使用して、IE7 以上のユーザーに対してこれを無効にしてください。

JavaScript パフォーマンスの最適化

1. スクリプトをページの下部に配置する

このスクリプトの問題は、ページが並行してダウンロードされないようにすることです。 HTTP/1.1 仕様では、ブラウザがホスト名ごとに同時にダウンロードする項目は 2 つ以下にすることを推奨しています。画像が複数のホスト名でホストされている場合は、各並列ダウンロードで同時に 2 つ以上のファイルをダウンロードできます。ただし、スクリプトをダウンロードする場合、ホスト名が異なっていても、ブラウザは他のファイルを同時にダウンロードしません。

場合によっては、スクリプトをページの下部に移動するのが簡単ではないことがあります。たとえば、スクリプトが document.write を使用してページ コンテンツを挿入する場合、下に移動することはできません。ここでも範囲の問題がある可能性があります。多くの場合、この問題が発生します。

よく使用される代替手段は、遅延スクリプトを使用することです。 DEFER 属性は、スクリプトに document.write が含まれていないことを示し、ブラウザに表示を続行するように指示します。残念ながら、Firefox は DEFER 属性をサポートしていません。 Internet Explorer では、スクリプトが遅延する可能性がありますが、その効果は期待どおりではない可能性があります。スクリプトを遅延できる場合は、ページの下部に移動できます。これにより、ページの読み込みが速くなります。

2. 外部JavaScriptとCSSを使用する

上と同じく、CSSで記述されています。前回の記事で外部から呼び出せるCDNを記載しました。

3. JavaScriptとCSSを削減する

上記と同じ、CSSで記述

4. 重複したスクリプトを排除する

同じページ内で JavaScript ファイルを繰り返し参照すると、ページのパフォーマンスに影響します。これはよくあることではないと思うかもしれません。米国のトップ 10 ウェブサイトを調査したところ、そのうち 2 つに重複したスクリプトがあることが判明しました。スクリプトが繰り返し参照されるという奇妙な現象を引き起こす主な要因は、チームの規模とスクリプトの数の 2 つです。この場合、重複したスクリプトによって不要な HTTP リクエストと無駄な JavaScript 計算が発生し、Web サイトのパフォーマンスが低下します。

Internet Explorer では不要な HTTP リクエストが行われますが、Firefox では行われません。 Internet Explorer では、スクリプトが 2 回参照され、キャッシュできない場合、ページの読み込みプロセス中に 2 つの HTTP 要求が生成されます。スクリプトはキャッシュできますが、ユーザーがページをリロードすると追加の HTTP リクエストが行われます。

追加の HTTP リクエストが作成されるだけでなく、スクリプトを複数回実行すると時間の無駄になります。 Internet Explorer と Firefox はどちらも、スクリプトがキャッシュ可能かどうかに関係なく、JavaScript を再評価するという問題があります。

同じスクリプトを誤って 2 回参照することを避ける 1 つの方法は、スクリプト管理モジュールを使用してテンプレート内のスクリプトを参照することです。 HTML ページでスクリプトを参照する最も一般的な方法は、<script /> タグを使用することです。

 <script type="text/javascript" src="menu_1.0.17.js"></script>

PHP では、代わりに insertScript というメソッドを作成できます。

 <?php insertScript("menu.js") ?>

複数のスクリプト参照を防ぐために、このメソッドでは、スクリプトが属するディレクトリをチェックしたり、Expire ファイル ヘッダーで使用するためにスクリプト ファイル名にバージョン番号を追加したりするなど、スクリプトを処理するための他のメカニズムも使用する必要があります。

5. DOMアクセスを減らす

JavaScript を使用して DOM 要素にアクセスすると速度が遅くなるため、ページのより多くの部分を取得するには、次の操作を行う必要があります。

訪問したキャッシュ関連要素

ドキュメントツリーに追加する前にノードをオフラインで更新する

JavaScriptを使用してページレイアウトを変更することは避けてください

6. インテリジェントなイベントハンドラを開発する

DOM ツリー要素にアタッチされたイベント ハンドラーが多すぎて、これらのイベント ハンドラーが頻繁にトリガーされるため、ページが応答しないと感じる場合があります。そのため、イベント委任を使用するのが適切なアプローチです。 div に 10 個のボタンがある場合は、ボタンごとにハンドラーを追加するのではなく、div にイベント ハンドラーを 1 回だけアタッチする必要があります。イベントがバブルアップすると、イベントをキャプチャし、どのイベントが送信されたかを判断できます。

また、DOM ツリーを操作するために onload イベントが発生するのを待つ必要もありません。アクセスしたい要素がツリー構造に表示されるまで待つだけです。すべての画像が読み込まれるのを待つ必要もありません。

JS をロードする方法と JS を配置する場所

外部JSのダウンロードをブロックする

JS をダウンロードすると、すべてのブラウザは他のリソースのダウンロード、コンテンツの表示など、他のすべてのアクティビティをブロックします。 JS がダウンロードされ、解析され、実行された後にのみ、他のリソースの並行ダウンロードとコンテンツの表示が開始されます。

「なぜ JS は CSS や画像のように並行してダウンロードできないのか」と疑問に思う人もいるかもしれません。ここで、ブラウザ ページ構築の原理を簡単に紹介する必要があります。ブラウザがサーバーから HTML ドキュメントを受信し、HTML をメモリ内の DOM ツリーに変換するときに、変換プロセス中にノードで CSS または IMAGE が参照されていることがわかった場合、ブラウザは CSS または画像を要求するために別のリクエストを送信し、リクエストが返されるのを待たずに次の変換を続行します。リクエストが返されたら、返されたコンテンツを DOM ツリーの対応する位置に配置するだけで済みます。しかし、JS が参照されると、ブラウザは js リクエストを送信し、リクエストが返されるのを待ちます。ブラウザは安定した DOM ツリー構造を必要としており、JS には document.write や appendChild を使用したり、location.href を直接使用してジャンプしたりするなど、DOM ツリー構造を直接変更するコードが含まれている可能性が高いためです。JS が DOM ツリーを変更するのを防ぐために、ブラウザは DOM ツリーを再構築する必要があり、他のダウンロードやレンダリングをブロックします。

ダウンロード ブロック グラフ: 次の図は、blogjava ホームページへのアクセスの時間ウォーターフォール グラフです。最初の 2 つの画像は並行してダウンロードされますが、次の 2 つの JS はダウンロードがブロックされている (1 つずつダウンロードされる) ことがわかります。

埋め込まれた JS によるダウンロードのブロック

埋め込み JS とは、HTML ドキュメントに直接記述された JS コードを指します。前述のように、外部 JS を参照すると、後続のリソースのダウンロードとコンテンツの表示がブロックされます。埋め込み JS はこれをどのようにブロックするのでしょうか? 次の 2 つのコードを参照してください。

 **コード1:** 

<div>
         < ul >
             < li > ブログJava </ li >
             < li > CSDN </ li >
             < li > haorooms ブログ </ li >
             < li > ABC </ li >
             < li > AAA </ li >
         < ul >     
     </div>
     < スクリプトタイプ ="text/javascript">
        // 5秒間ループします var n = Number( new Date());
     var n2 = Number(新しい日付());
    ただし、((n2 - n) < ( 6 * 1000 )){
       n2 = 数値(新しい日付());
     }
     </スクリプト>
   <div>
         < ul >
             < li > MSN </ li >
             < li > グーグル </ li >
             < li > ヤフー </ li >
         < ul >     
</div>

実行すると、コード 1 では最初の 5 秒間はページが空白になり、5 秒後にページ全体が表示されることがわかります。 コード2では、最初の5秒間にblogjava、csdnなどが表示され、5秒後にMSNが表示されます。

埋め込まれた JS はすべてのコンテンツの表示をブロックしますが、外部 JS は後続のコンテンツの表示のみをブロックすることがわかります。どちらの方法でも、後続のリソースのダウンロードはブロックされます。

JSを埋め込むとCSSの読み込みがブロックされる

CSS はどのようにして読み込みをブロックできるのでしょうか? CSS は並行してダウンロードできます。どのような状況で読み込みがブロックされますか? (テスト観察では、CSS は IE6 で読み込みがブロックされています。次のテストは IE6 以外で実行されます):

コード 1 (効果を上げるため、ここでは外部サーバーからの CSS が選択されています):

 < html xmlns ="http://www.w3.org/1999/xhtml" >
         < ヘッド >
           < タイトル > js テスト </ タイトル >
           < meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" />  
           < リンク タイプ ="text/css" rel ="スタイルシート" href ="http://69.64.92.205/Css/Home3.css" />
         </ ヘッド >
         < 本文 >
             < 画像 src ="http://www.haorooms.com/images/logo.gif" />< br />
              <img src="http://www.haorooms.com/images/csdnindex_piclogo.gif" />
         </本文>
</html>

時間ウォーターフォールチャート:

コード 2 (空の埋め込み JS が 1 つだけ追加されます):

 < ヘッド >
     < タイトル > js テスト </ タイトル >
     < meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" />  
   < リンク タイプ ="text/css" rel ="スタイルシート" href ="http://69.64.92.205/Css/Home3.css" />
   < スクリプトタイプ ="text/javascript">
         関数a(){}
   </スクリプト>
</ ヘッド >
< 本文 >
         < 画像 src ="http://www.haorooms.com/images/logo.gif" />< br />
         <img src="http://www.haorooms.com/images/csdnindex_piclogo.gif" />
</本文>

時間ウォーターフォールチャート:

タイム ウォーターフォール チャートから、コード 2 では CSS と画像が並行してダウンロードされていないことがわかります。代わりに、CSS のダウンロード後に次の 2 つの画像のダウンロードが開始されます。CSS の後に埋め込み JS が続く場合、CSS は後続のリソースのダウンロードをブロックします。

埋め込まれた JS が後続のリソースをブロックすることについては触れず、CSS がブロックされると言えばよいのでは、と疑問に思う人もいるかもしれません。 考えてみてください。現在、空の関数を使用していますが、この空の関数を解析するのにかかる時間はわずか 1 ミリ秒です。一方、次の 2 つの画像は、CSS がダウンロードされてから 1.3 秒経過するまでダウンロードが開始されません。 CSS の前に JS を埋め込むこともできます。ブロックは発生しません。

根本原因: ブラウザは HTML 内の CSS と JS の順序を維持するため、埋め込まれた JS が実行される前にスタイルシートを読み込んで解析する必要があります。埋め込まれた JS は後続のリソースの読み込みをブロックするため、上記のような CSS によるダウンロードのブロック状況が発生します。

埋め込まれた JS はどこに配置すればよいですか?

1. 一番下に置きます。すべてのプレゼンテーションがブロックされますが、リソースのダウンロードはブロックされません。
2. ヘッド内にJSを埋め込む場合は、埋め込まれたJSをCSSの前に配置してください。
3. deferを使用する
4. 埋め込み JS では実行に時間のかかる関数を呼び出さないでください。どうしても使用する必要がある場合は、setTimeout を使用して呼び出すことができます。settimeout については以前の記事で説明しましたので、こちらを参照してください: https://www.jb51.net/article/20741.htm

<<:  JavaScript における var、let、const の違いの詳細な説明

>>:  初心者のためのMySQL外部キーの設定方法

推薦する

MySQL ビューの原則と使用例の概要

この記事では、MySQL ビューの原理と使用法についてまとめます。ご参考までに、詳細は以下の通りです...

Linux ディレクトリ切り替え実装コード例

ファイルの切り替えは Linux でよく行われる操作です。Linux を初めて学ぶときに最初に触れる...

エラー mysql テーブル 'performance_schema...解決方法

テスト環境は、JDBCドライバを使用してMariaDB 5.7でセットアップされています。 <...

CSS の新機能には、コントロールページの再描画と再配置の問題が含まれています

新しい CSS プロパティ contain を紹介する前に、読者はページの再描画と再配置が何であるか...

CentOS 7.4 にソースコードから MySQL 8.0 をインストールするための詳細なチュートリアル

目次1. 環境2. 準備3. MySQL 8.0.11をインストールするMySQL 8 の公式バージ...

JavaScript イベント委任の原則

目次1. イベント委任とは何ですか? 2. イベント委任の原則3. イベント委託の役割1. イベント...

CSS3 は反転可能なホバー効果を実現します

CSS3 は反転可能なホバー効果を実装します。具体的なコードは次のとおりです。 1.css /*基本...

MySQL 8.0.11 Mac 用インストール ガイド

MACはmysql8.0をインストールします。具体的な内容は次のとおりです。 1. ダウンロードアド...

フロントエンドエンジニアが作ったクールなインタラクティブウェブサイトを推薦します

ウェブサイトリンク: http://strml.net/サミュエル・リード著ヒント: 昨日、Mome...

vueの実践的な応用におけるvuexの永続性の詳細な説明

目次vuex 永続性要約するvuex 永続性vuex: ブラウザを更新すると、vuexの状態は初期状...

Windows での MySQL 5.7.18 のインストールと設定のチュートリアル

この記事では、WindowsでのMySQL 5.7.18のインストールと設定のチュートリアルを参考ま...

MySQL サーバー 5.7.20 のインストールと設定方法のグラフィック チュートリアル

この記事ではMySQL 5.7.20のインストールと設定方法を記録し、皆さんと共有します1. MyS...

MySQL の null 可能フィールドは NULL に設定する必要がありますか、それとも NOT NULL に設定する必要がありますか?

MySQL を頻繁に使用する人は、次のような状況に遭遇する可能性があります。 1. フィールド タ...

MySQL の結合クエリとサブクエリの問題

目次複数テーブル結合の基本構文クロス結合と直積現象クロスコネクトデカルト積現象内部結合外部結合左外部...

要素の幅(高さ)の適応を実現するCSSおよびCSS3の柔軟なボックスモデル

1. CSSは左の固定幅と右の適応幅を実現します1. ポジショニング <!DOCTYPE ht...