0.1秒の価値!フロントエンドのウェブページの高速化の問題について簡単に説明します

0.1秒の価値!フロントエンドのウェブページの高速化の問題について簡単に説明します

私が現在の仕事の面接を受けたとき、リーダーが真剣にこう言っていたのを覚えています。「今の世の中はインターネットの世界であり、IT企業間の競争は非常に熾烈です。Webページの読み込みや表示速度が、他社のサイトページと比べて0.1秒でも速ければ、それは大きな成果です。」

その後、どうやって書き続けたらいいのかわからなかったので、グループ内の軍事顧問たちに相談したところ、こうなりました。 。 。

さて、話題を変えて本題に戻りましょう。サイト ページのアクセス速度を向上させ、待ち時間を短縮し、ユーザーのアクセス エクスペリエンスを最大化するにはどうすればよいでしょうか。

この問題に対処するために、本日はフロントエンドの観点から、ページのアクセス速度を効果的に向上できる一連のソリューションを提案します。

1. サーバーへのファイルリクエストを減らす

従来の HTTP リクエストは、「リクエスト」-「レスポンス」-「切断」という形式の短い接続です。独立したリソースごとに、サーバーに get リクエストを送信し、サーバーが必要なファイルを返信するのを待ちます。各リソース要求は、実際には「接続-待機-受信」時間を消費します (もちろん、http 要求をキープアライブの長い接続ステータスに設定すると、「接続」の数と時間を減らすことができます)。サーバー ファイルに対する要求の数を効果的に減らすことができれば、ページの待機時間を節約し、サーバーの負荷を軽減できることを意味します。

この解決策として、次のことが行えます。

1. CSS スプライト技術を使用して、複数の画像を 1 つの画像ファイルに結合します。実際に使用する場合は、background-position を使用して背景の位置を特定します (これが最初に思い浮かぶことだと思います)。

2. 複数の CSS スタイル ファイルを 1 つのスタイル ファイルにマージし、複数のスクリプトを 1 つのスクリプトにマージして、マージされたスタイル/スクリプト ファイルをページ内で参照します。この作業には r.js を使用できますが、ファイルをマージした後、複数のページ間で共通のスタイル/スクリプト ファイルをクライアントにキャッシュできないため、個人的にはこの方法はお勧めしません。

3. base64 エンコードを使用して画像を表示します。 github 404 ページと同じです:

このツールを使用すると、画像を base64 でエンコードされたファイル ストリームに変換できますが、通常、この方法はユーザーがあまりアクセスしないページでのみ使用することをお勧めします。サーバーから取得する必要がないにもかかわらず、クライアントにキャッシュすることができないため、ユーザーがアクセスするたびにページが再レンダリングされることになるからです。さらに、長いファイル ストリーム コードはページ上のコード スペースを大量に占有し、ページの保守が非常に困難になる可能性があります。

4. ページに独立したスタイル/スクリプト ファイルを導入するのではなく、小さな CSS および JS コード スニペットをページに直接記述します。友人の中には、「構造 (マークアップ)、プレゼンテーション (スタイル)、動作 (スクリプト) を分離しておく」という標準に慣れている人もいると思いますので、この観点について何らかの意見を持っているかもしれません。私が言えるのは、基準は教義ではなく、自分に合うものが厳然たる真実であるということです。小さくて再利用性の低いスタイル/スクリプトをページ上に直接記述することの利点は、依然として欠点を上回ります (欠点としては、ページ コードのサイズが大きくなり、保守が容易ではないことが挙げられます)。一方、主流のポータルサイトのページソースファイルを見ると、スタイルやスクリプトをすべて外部ファイルとしてインポートしているサイトはほとんどありません(サーバーリクエストの削減を目的にしているかどうかは別として、事実はこうです)。

5. http-equiv="expires" メタ タグを使用して、将来の時点をページ ファイルの有効期限として設定します。有効期限前にユーザーが取得したページ ファイルは、キャッシュからのみ取得されます。ただし、この方法は厳格すぎるため (サーバーが期限を終了時刻に時間どおりに変更しても、クライアントが新しく変更されたルールに従ってサーバーにアクセスして新しいファイル リソースを取得できない場合があります)、一般的には推奨されません。

2. ファイルサイズを縮小する

大きなファイル(特に画像)は読み込み時間が長くなり、ページの読み込みエクスペリエンスに影響を与える最大の敵となることがよくあります。したがって、要求されたファイルのサイズを可能な限り小さくすることが非常に重要です。私たちができることは次のとおりです。

1. スタイル/スクリプト ファイルを圧縮します。これを行うには、gulp または grunt を使用できます。どちらも、css/js ファイルのサイズを縮小できます (また、js の変数と関数名を難読化できます)。

2. ターゲットを絞って画像形式を選択します。透明な背景が必要ない場合は、単色で色のグラデーションのない画像にのみ gif 形式を使用します。jpg 画像の場合は、jpg をエクスポートするときに、その鮮明度要件に応じて対応する「品質」を最適化することもできます。

新しいことを試したい場合は、Taobao のように webp 画像形式を使用できます。これにより、同じ画像品質でファイル サイズを最適化できます。

3. Font Awesome を使用してページ上のアイコンを置き換えます。原則として、@font-face を使用して、ユーザーに非常に小さな UI フォント パッケージをダウンロードさせ、ページ上で使用されるアイコンを文字の形で表示することで、画像要件とアイコン ファイル サイズを削減します。

3. CDNを適切に使用する

CDN を使用すると、いくつかの利点があります。ユーザーが他のサイトからこの CDN リソースをダウンロードした場合、当社のサイトにアクセスするときには、キャッシュから取得するだけで済みます。また、外部 CDN の場合、ユーザー自身のサイト サーバーへのファイル リクエストが減り、サーバーの負荷が軽減されます。ドメインが複数あると、ブラウザーで非同期にダウンロードできるリソースの最大数が増えます。たとえば、サイトが 1 つのドメインにのみリソースをリクエストする場合、Firefox では同時に最大 2 つのファイルしか非同期でダウンロードできません。ただし、外部 CDN を使用してリソースを導入すると、FF では現在のドメイン内の 2 つのリソースの同時非同期ダウンロードだけでなく、別のドメイン (CDN) の 2 つのリソースの同時非同期ダウンロードも可能になります。

しかし、CDN の使用には大きな問題があります。それは、DNS 解決のオーバーヘッドが増加することです。ページが複数の CDN から同時にリソースを導入すると、DNS 解決のために長い待機時間が発生し、コストがメリットを上回ってしまう可能性があります。

この問題に関して、一般的に推奨されているのは、サイト配下のさまざまな必要なリソースを導入するために、信頼性が高く高速な同じ CDN のみを使用することです。つまり、ページが 2 つの異なるドメイン (サイト ドメインと CDN ドメインなど) からリソースを要求することが最善の選択肢として推奨されます (この結論は Yahoo のフロントエンド エンジニアによって提案されたと言われています)。

4. 遅延リクエストと非同期スクリプト読み込み

すべての主要ブラウザでは、スクリプト ファイルは通常、他のリソース ファイルと同様に非同期でダウンロードされます。ただし、ここで問題があります。たとえば、Firefox がスクリプトをダウンロードした後、「実行がブロックされた」状態になります。つまり、ブラウザがスクリプトをダウンロードして実行している間、ブラウザの他の動作がブロックされ、ページ上の他のリソースを要求してダウンロードできなくなります。

ページ内の js コードの実行に時間がかかりすぎると、ユーザーは明らかにページの遅延を感じることになります。この問題を解決する簡単な方法があります。スクリプト要求タグを </body> 終了タグの前に配置します。これにより、ページ上のスクリプトが最後に要求されるリソースになり、他のページ リソースの要求イベントが自然にブロックされなくなります。

また、上記で「弊社のスクリプトファイルは他のリソースファイルと同様に非同期でダウンロードされます」と記載しましたが、非同期ダウンロードは非同期実行を意味するものではありません。スクリプトのロジック順序と依存関係の正確性を厳密に保証するために、ブラウザはスクリプトが要求された順序でスクリプトを実行します。ここで問題が発生します。ページ上のスクリプトに依存関係がほとんどないか、または相互にまったく依存関係がない場合、ブラウザーのルールによってページ リクエストのブロック時間が長くなるだけです (保険を購入するために多額のお金を費やしたのに、保険期間中は何も起こらないのと同じです... まあ、この比喩は少し反人間的ですが...)。

この問題の解決策は、スクリプト タグに defer 属性と async 属性を追加したり、スクリプトを動的に挿入したりして、スクリプトをブロックせずに非同期で実行することです (こちらを参照)。ただし、これらは良い解決策ではありません。互換性の問題があるか、面倒すぎて依存関係を処理できないかのどちらかです。

個人的には、スクリプトを非同期にロードし、モジュールの依存関係を処理するために、requireJS (AMD 仕様) または seaJS (CMD 仕様) を使用することをお勧めします。前者は「依存関係を事前に配置」 (すべての依存スクリプト モジュールを事前にロードして実行速度を最速にする) し、後者は「最も近いものに依存」 (依存スクリプト モジュールを遅延ロード、スクリプトを要求する方が科学的) します。プロジェクトの特定のニーズに基づいて、最も適切なものを選択できます。

5. 最初の画面以外でのファイルのリクエストを遅らせる

まず最初に説明させてください。「ファーストスクリーン」とは、ページが初期化されたときのページコンテンツ表示領域、つまりページが読み込まれたときにユーザーが最初に目にする領域を指します。

たとえば、JD.com と Taobao は、ページを見るためにスクロールする必要がある画像に対して同様の遅延読み込み処理を実装しています。これらはプロキシ モデルの概念に過ぎませんが、画面上のコンテンツをすぐに見ることができるため、ページの読み込みが速くなったという錯覚をユーザーに与えます (スクロール バーをプルダウンしておらず、ページの後ろのファイルが実際にはまだ読み込まれていない場合でも)。

このソリューションは、遅延ロード ライブラリに頼ることなく、次のように実装できます。写真を例にとると、写真の img タグを最初の画面の外側に次のように記述できます (写真のアドレスが a.jpg であると仮定)。

<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="a.jpg">

上記のように、ページが最初にこの画像を読み込むときに、base64 を直接使用して (もちろん、代わりにプレースホルダー画像 loading.gif を使用することもできます)、非常に小さな画像をすばやく表示します。画像自体の実際のパスは data-src 属性にあります。サーバーから実際のファイルを要求し、ページが読み込まれた後に置き換えることができます。

関数init(){

var imgDefer = document.getElementsByTagName('img');

(var i=0; i<imgDefer.length; i++) の場合 {

if(imgDefer[i].getAttribute('data-src')) {

imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));

}

}

}

ウィンドウを初期化します。

上記は画像の遅延読み込みプロセスです。ビデオファイルやオーディオファイルの場合も、同じ原理で読み込みを遅延させることができ、ページの初期化の待ち時間を効果的に短縮できます。

6. ページモジュールの配置順序を最適化する

ここに良い例があります。たとえば、次のようなページがあります。左側には、ユーザーのアバター、情報、Web サイトに掲載されている広告を保存するために使用されるサイドバーがあり、右側には記事のコンテンツ領域があります。

コードは次のようになります。

<本文>

<サイドバー>

<!-- サイドバーコンテンツ -->

</サイドバー>

<コンテンツ>

<!-- 記事の内容 -->

</コンテンツ>

</本文>

したがって、ブラウザは UI のシングルスレッド原則に従って、まずサイドバーを上から下に読み込み、次に記事を読み込みます。 。 。

明らかに、これは人道的な読み込み順序ではありません。ページ上のどのエリア モジュールがユーザーにとって最も重要で、どれを最初に表示する必要があるかを把握する必要があります。

上記の例では、記事のコンテンツはユーザーが最初に見る領域であり、ブラウザが最初に要求して表示する領域である必要があります。したがって、コードを次のように変更する必要があります。

<本文>

<コンテンツ>

<!-- 記事の内容 -->

</コンテンツ>

<サイドバー>

<!-- サイドバーコンテンツ -->

</サイドバー>

</本文>

もちろん、これはあなたの想像力を刺激するための小さな例にすぎません。推論を導き出し、それを実際に適用する方法を知ることこそが真実なのです。

VII. その他の提案

1. CSS で @import を使用しないでください。これにより、1 つのスタイル ファイルが別のスタイル ファイルの要求を待機することになり、ページの待機時間が長くなります (もちろん、scss を使用する場合は @import は別の問題ですが、それは話題から外れます~)。

2. ページまたはページ ファイルのリダイレクトは避けてください。これは、トイレに入ってから「ここは違います。正面左側のトイレに行ってください」という標識を見て、もう一度そこを通らなければならないようなものです。

3. 無効なリクエストを減らす - たとえば、CSS/JS を介して存在しないリソースをリクエストすると、待機時間が長くなり、ブロックされる可能性があります (エラー メッセージが返されるまで)。

4. スクリプトをページの最後に配置するかどうかにかかわらず、スクリプトはスタイル ファイルの後に配置されていることを確認してください。

5. .htaccess ファイルの構成、Gzip ページ圧縮の使用、キープアライブ接続モードの有効化などのバックエンド ソリューションの詳細については説明しません。

ページを高速化するソリューションは、必ずしも上記に限定されるものではなく、プロジェクトごとにさまざまなニーズや状況があるため、必要に応じて自分に合ったソリューションを選択するしかないと思います。

しかし、最も重要なことは、ユーザーエクスペリエンスを第一に考えることです。ページの読み込みであれ、インタラクションであれ、ユーザーの視点から最適なソリューションを考え、設計する必要があります。こうすることで、優れた人気のある作品を作成できると信じています。

今日はここまでです。お互いに励まし合いましょう〜

<<:  トップナビゲーションバー機能を実現するCSS+HTML

>>:  Linux の RPM パッケージでインストールされた xinetd ベースのサービスの管理

推薦する

CSS ハック \9 と \0 は IE11\IE9\IE8 のハッキングには機能しない可能性があります

Web ページやフォームを設計するたびに、さまざまなブラウザ、特に IE ファミリの互換性の問題に悩...

MYSQL の 10 の典型的な最適化ケースとシナリオ

目次1. SQL最適化の一般的な手順1. SQL実行計画の分析を説明する2. プロフィール分析を表示...

ハイパーリンクの表示と開き方

<br />関連記事: ハイパーリンクを表示して開く方法症状<br />ユー...

nginx を使用したプロキシ サーバーの設定

Nginx は、リバース プロキシ機能を使用して負荷分散を実装できるほか、フォワード プロキシ機能を...

ES5とES6の違いを分析する

目次概要関数シグネチャオプションパラメータ非厳密モード例外処理実用要約する概要ご存知のとおり、ES6...

Vueプロジェクトの最適化とパッケージ化の詳細な説明

目次序文1. ルーティングの遅延読み込み1. ルートの遅延読み込みが必要なのはなぜですか? 2. ル...

MySQL 8.0.17 winx64 (Navicat 付き) 手動構成バージョンのインストール チュートリアル図

1. ダウンロードアドレス: mysql-8.0.17-winx64ダウンロードして解凍する2. フ...

Linux sshのデフォルトのリモートポート番号を変更する6つの手順

Linux のデフォルトの ssh リモート ポートは 22 です。デフォルトのポートは、悪意のある...

Ubuntu 16.04 mysql5.7.17 リモートポート 3306 を開く

MySQLへのリモートアクセスを有効にするデフォルトでは、MySQL ユーザーにはリモート アクセス...

MySQL 重複インデックスと冗長インデックスの例の分析

この記事では、例を使用して MySQL の重複インデックスと冗長インデックスについて説明します。ご参...

Ubuntu 18.04 のsources.listをAlibabaまたはTsinghuaミラーに変更する方法

1. バックアップソースリストUbuntu のデフォルトのソースは国内サーバーではないため、更新され...

HTML検証 HTML検証

HTML 検証はHTML 検証を指します。これは、HTML ドキュメントを分析し、標準の HTML ...

Vueライフサイクル機能の詳細な説明

目次ライフサイクル関数一般的なライフサイクルフックVue のインスタンス破棄について:要約するライフ...

MySQL ストアド関数(カスタム関数)の定義と使用方法の詳細な説明

ストアド関数ストアド関数とは: SQL コードの一部をカプセル化し、特定の関数を完了して、結果を返し...

MySQLクエリのソートとページング関連

概要通常、データベース内のデータを直接表示することは望ましくないため、最後の 2 つのセクションでは...