webpackが静的リソースキャッシュを実装する方法

webpackが静的リソースキャッシュを実装する方法

導入

静的リソースのキャッシュはフロントエンドのパフォーマンス最適化のポイントであるため、フロントエンドの開発プロセスでは、キャッシュが最大限に利用されるのが一般的です (ここでは主に強力なキャッシュ)。この記事の話題に戻りますが、webpack でビルドされたプロジェクトでは、注意しないと、サーバーがキャッシュ戦略を設定しても、ビルドされたプロジェクトで静的リソースのキャッシュを実現できない可能性があります。では、webpack はキャッシュを使用する効果をどのように実現できるのでしょうか? この問題については以下で説明します。

複数の異なるハッシュを区別する

私たちは皆、webpack には各プロジェクトのビルドhash 、さまざまなエントリのchunkhash 、ファイル コンテンツのcontenthashなど、さまざまなハッシュ値があることを知っています。これほど多くのハッシュがある場合、それらの違いは何でしょうか?

ハッシュ

ハッシュは、webpack ビルド プロジェクト全体に関連しています。プロジェクト ファイルが「変更」されていない場合でも、ハッシュに対応する値はプロジェクトがビルドされるたびに異なります。

実際、これは変更されており、webpack がパッケージ化されてコンパイルされるたびに、webpack ランタイム コードが挿入され、プロジェクト全体に変更が加えられるため、ハッシュ値が毎回変更されます。

私のプロジェクト コードを例に、変更を加えずに 2 回のビルドを行う前と後のコードの比較を示します。

対応するプロジェクト ビルドのハッシュが 2 回変更されたことがわかります。ハッシュが毎回変わるため、この方法ではキャッシュを実現できないと推測できます。

チャンクハッシュ

Chunkhash は、その名前が示すように、webpack によってパッケージ化されたチャンクに関連しています。具体的には、webpack はエントリ構成ファイルの依存関係を分析し、それに基づいてエントリのチャンクを構築し、対応するハッシュ値を生成します。チャンクが異なればハッシュ値も異なります。通常、プロジェクトでは、パブリック依存ライブラリとプログラムエントリファイルを分離して別々にパッケージ化し、チャンクハッシュを使用してハッシュ値を生成します。パブリック依存ライブラリが変更されない限り、対応するチャンクハッシュは変更されないため、キャッシュの目的が達成されます。

通常、chunkhash はプロジェクトの webpack エントリに使用され、出力構成項目に具体的に反映されます。

モジュール.エクスポート = {
  エントリー: {
   アプリ: './src/main.js',
   ベンダー: ['react'、'redux'、'react-dom'、'react-redux'、'react-router-redux']
  },
  出力: {
    パス:path.join(__dirname, '/dist/js'),
    ファイル名: '[name].[chunkhash].js'
  }
 ...
}

最後に、アプリとベンダーのチャンクハッシュコンパイル結果は次のとおりです。

コンテンツハッシュ

Contenthash は、ファイル コンテンツによって生成されたハッシュ値を表します。コンテンツが異なると、異なる contenthash 値が生成されます。プロジェクトでは、プロジェクト内の CSS を参照用の対応する CSS ファイルに抽出するのが一般的です。たとえば、次のように webpack 構成で使用します。

モジュール.エクスポート = {
  ...
  プラグイン: [
     新しいExtractTextPlugin({
	ファイル名: 'static/[name]_[chunkhash:7].css',
	無効: false、
	すべてのチャンク: true
     })
  ...
  ]

上記の構成では、chunkhash が使用され、それに依存するチャンクと chunkhash が共有されるため、問題が発生します。

たとえば、上記のアプリ チャンクの例では、index.css ファイルに依存しています。index.css のハッシュは、アプリのチャンクハッシュに従います。アプリ ファイルが変更される限り、index.css ファイルが変更されなくても、そのハッシュ値も変更され、キャッシュが失敗します。

次に、extra-text-webpack-plugin のcontenthash値を使用して、CSS ファイルが配置されているモジュール内の他のファイルの内容が変更された場合でも、CSS ファイルの内容が変更されない限り、そのハッシュ値は変更されないことを保証できます。

js キャッシュの実装

webpack プラグインCommonsChunkPluginの主な機能は、webpack プロジェクト エントリ チャンクの共通部分を抽出することです。具体的な使用方法については詳しく説明しません。よくわからない場合は、webpack 公式サイトの紹介を参照してください。

このプラグインは、Webpack プロジェクトでよく使用される最適化機能であり、ほぼすべての Webpack プロジェクトで使用されます。このプラグインを使用する利点:

  • webpack のパッケージ化速度とプロジェクト サイズの改善: webpack エントリのチャンク ファイルからすべての共通コードを抽出してコード サイズを削減し、同時に webpack のパッケージ化速度を改善します。
  • キャッシュ メカニズムを活用する: 依存するパブリック モジュール ファイルは通常、ほとんど変更されないか、まったく変更されないため、独立したモジュール ファイルを抽出して長期間キャッシュすることができます。

ただし、プロジェクトでプラグインが誤って開かれると、上記の 2 番目のポイントは達成できません。その理由は次のとおりです。

変更されていないパブリック コードまたはライブラリ コードにパッケージ化されたエントリ チャンクは、他のビジネス コードの変更によって変更され、ページ上のロング キャッシュ メカニズムが失敗する原因になります。

それでは、 CommonsChunkPlugin正しく開きましょう。

CommonsChunkPlugin の誤った使用法

react、react-dom、react-router などのプロジェクトの共通ライブラリをビジネス コードから分離し、ベンダー チャンクとして抽出すると、webpack 構成は次のようになります。

webpack は、次のコードで定義されます。
定数パス = require('path');
モジュール.エクスポート = {
  エントリー: {
    アプリ: "./src/main.js",
    ベンダー: ["react","re​​act-dom", "redux", "react-redux", "react-router-redux"]
  },
  出力: {
    パス: path.resolve(__dirname, 'output'),
    ファイル名: "[name].[chunkhash].js"
  },
  プラグイン: [
    新しい webpack.optimize.CommonsChunkPlugin({names: ["vendor"]})
  ]
};

上記では、プロジェクトのいくつかの基本ライブラリが vendor と呼ばれるチャンクにパッケージ化され、ビジネス関連のコードは app と呼ばれるチャンクにパッケージ化されています。

webpack のパッケージ化とコンパイルの結果は次のとおりです。

ビジネス コード app.js を変更した後、再コンパイルの結果は次のようになります。

CommonsChunkPlugin の設定では、ビジネス コード アプリが変更されると、ライブラリ コードも変更され、ベンダーのチャンクハッシュも変更されることがわかります。このように、ベンダーの参照の名前が変更され、ブラウザー上のロング キャッシュ メカニズムが失敗する原因になります。

問題の原因

webpack がコンパイルされるたびにベンダーが変わる理由:

Webpack はビルドするたびにランタイム コードを生成します。ファイルが 1 つしかない場合は、ランタイム コードがそのファイルに直接詰め込まれます。ファイルが複数ある場合、ランタイム コードは共通ファイル、つまり上記の CommonsChunkPlugin によって構成されたベンダー チャンクに抽出されます。

グローバル webpackJsonp メソッドの定義やモジュール依存関係の維持など、コンパイルのたびに webpack によって生成されるランタイム コードについては、こちら >> を参照してください。

したがって、上記の webpack の CommonsChunkPlugin 構成では、これらのコードはコンパイルされるたびにベンダーにパッケージ化され、ベンダーのチャンクハッシュが毎回変更されることになります。

次に、ベンダー チャンクを構成して共通コード、つまり webpack ランタイム コードを抽出し、プロジェクトが依存する基本ライブラリ モジュールをビジネス モジュールから分離できるようにします。これらのファイルは変更されないため、これらのファイルはロング キャッシュの効果を実現できます。具体的な構成は以下のとおりです。

モジュール.エクスポート = {
  エントリー: {
    アプリ: "./app.js",
    ベンダー: ["react","re​​act-dom", "redux", "react-redux", "react-router-redux"]
  },
  ....
  プラグイン: [
    新しい webpack.optimize.CommonsChunkPlugin({names: ["vendor"]})、
    新しい webpack.optimize.CommonsChunkPlugin({
        名前: 'マニフェスト',
        チャンク: ['ベンダー']
    })
  ]
};

この方法では、業務アプリのコードが変更されても、プロジェクトが依存する基本ライブラリのベンダー チャンクは変更されません。抽出されたマニフェスト チャンクのみが毎回変更されますが、このファイルのサイズは非常に小さく、この方法はベンダーよりも大きなメリットがあります。以下のように表示されます。

アプリコードを変更した後のパッケージコンパイル結果は以下のようになります。ベンダーチャンクハッシュは変更されていないことがわかります。

webpack で CommonsChunkPlugin を設定する際に注意すべき点がいくつかあります。

1. webpack の出力項目を設定する場合、そのfilenamechunkFilenameは chunkhash を使用する必要があります。ハッシュを使用しないでください。そうしないと、上記の構成でも期待される効果が得られません。ハッシュとチャンクハッシュの違いについては、githubの回答を参照してください。

2. 画像やフォントなどの静的リソースを抽出するために使用されるfile-loaderの場合、構成されたハッシュは静的ファイルのコンテンツハッシュ値を表します。パッケージ化およびコンパイルされるたびに webpack によって生成されるハッシュ値ではありません。覚えておいてください。 ! !

3. 抽出された CSS スタイル ファイルには、 file-loaderの hash と同じ意味を持つcontenthashを使用する必要があります。これはチャンクハッシュにすることはできません。そうしないと、スタイル ファイルが抽出されるエントリ チャンクのチャンクハッシュと一致してしまい、キャッシュの目的が達成されません。

CSSキャッシュの実装

Webpack は、上で紹介した contenthash を使用して CSS キャッシュを実装します。hash 属性値は、実際にはextra-text-webpack-pluginによって計算されます。 CSSキャッシュを実装するには、次のようにcontenthashを使用します。

モジュール.エクスポート = {
  ...
  プラグイン: [
     新しいExtractTextPlugin({
	ファイル名: 'static/[name]_[contenthash:7].css',
	無効: false、
	すべてのチャンク: true
     })
  ...
  ]

画像/フォントのキャッシュを実装する

画像やフォントなどの静的リソースの場合、webpack を使用してビルドおよび抽出するときに、実際にはfile-loaderを使用して完了し、対応するファイル ハッシュ値は対応するfile-loaderによって計算されます。では、これらの静的ファイルにはどのようなハッシュ値が使用されるのでしょうか? 実は、それらはhash属性値です。次のコードに示すように:

モジュール.エクスポート = {
 ...
 ルール:
   ...
    {
      テスト: /\.(gif|png|jpe?g)(\?\S*)?$/,
      ローダー: require.resolve('url-loader'),
      オプション:
        制限: 10000、
        名前: path.posix.join('static', '[name]_[hash:7].[ext]')
      }
    },
    フォント:
      テスト: /\.otf|ttf|woff2?|eot(\?\S*)?$/,
      ローダー: require.resolve('url-loader'),
      オプション:
        制限: 10000、
        名前: path.posix.join('static', '[name]_[hash:7].[ext]')
      }
    }
 ]
}

上記では、ハッシュ属性値が使用されていることがわかります。このハッシュは、プロジェクトがビルドされるたびに webpack がビルドするハッシュではありません。これは、ファイルの内容に基づいて file-loader によって計算されます。webpack によってビルドされるハッシュと間違えないでください。

参照する

1. webpackのCommonsChunkPluginを開く正しい方法
2. Webpack ピット充填道路抽出独立ファイル(モジュール)
3. Webpackコード分割スキル
4. ファイル名のハッシュを処理するために webpack を使用していると聞きました。次に、生成したハッシュが正しいかどうかを確認することをお勧めします。
5. チャンクハッシュ
6. 複数のコモンズチャンク
7. Webpackを使用して永続キャッシュを実装する
8. Webpack のハッシュとチャンクアッシュの違い、および js と css のハッシュ フィンガープリント分離ソリューション

これで、webpack で静的リソース キャッシュを実装する方法についての記事は終了です。より関連性の高い webpack 静的リソース キャッシュ コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Electron-vueはwebpackを使用して複数ページのエントリファイルをパッケージ化します
  • webpackのモバイル適応ソリューションの概要
  • vue-cli を使用してプロジェクトを作成し、webpack でパッケージ化する方法
  • webpackでHMRを手動で実装するいくつかの方法
  • vue の webpack -v エラー解決の概要

<<:  dubbo での Zookeeper リクエストのタイムアウト問題: mysql8.0.15 に接続する mybatis+spring の構成

>>:  Linux で実行可能ファイルを実行するときに「そのようなファイルまたはディレクトリはありません」というプロンプトが表示される場合の解決策

推薦する

MySQL インフラストラクチャ チュートリアル: クエリ ステートメント実行プロセスの詳細な説明

序文私は以前から、SQL 文がどのように実行され、どのような順序で実行されるのかを知りたいと思ってい...

TortoiseSvn Little Turtle インストール 最新の詳細なグラフィックチュートリアル

tortoiseGit のインストール時にいつも問題があったので、単純に svn に変更しました。途...

Ubuntuのソースリスト(ソースリスト)を変更する方法詳細説明

導入Ubuntu のデフォルトのソースは国内サーバーではないため、更新されたソフトウェアのダウンロー...

マークアップ言語 - 簡略化されたタグ

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...

Dockerfileを使用してApacheイメージを作成する方法

目次1. Dockerイメージ2. 既存のイメージに基づいてインスタンスを作成する3. ローカルテン...

HTML DOM入門_PowerNode Javaアカデミー

DOMとは何ですか? JavaScript を使用すると、HTML ドキュメント全体を再構築できます...

HTML タグ dl dt dd 使用方法

基本構造:コードをコピーコードは次のとおりです。 <ダウンロード> <dt>...

Vue3 の参照と参照の詳細

エディターは、Vue3のデータの関連する問題も共有します。次のような例を見てみましょう。 Vue.c...

MySQLデータベースのマスタースレーブ同期の実際のプロセスの詳細な説明

目次インストール環境の説明MySQLデータベースサービスをインストールするメインライブラリを構成する...

HTML でフォーム コントロールを無効にする 2 つの方法: readonly と disabled

Web ページを作成する過程では、フォームがよく使用されます。しかし、フォーム上のコントロールを変更...

CSS を使用してプログレスバーと順序プログレスバーを実装する例

この半月、期末試験の準備にかなりのエネルギーを費やしました。今日はしっかり復習するべきだったのですが...

Nodejs は readline を使用してコンテンツ入力を促すサンプルコード

目次序文1. batがjsを実行する2. ターミナルにバージョン番号を入力してパッケージ化コマンドを...

ブラウザでTIF形式の画像を表示する方法

ブラウザはTIF形式の画像を表示しますコードをコピーコードは次のとおりです。 <html>...

WeChatアプレットのスワイパードットのドットをスライダーに変更する方法

目次背景ターゲット効果アイデア成し遂げるスワイパーは変更を聞きますカスタムドットモジュール変更イベン...

Ubuntu で nvidia グラフィック ドライバーをインストールする (簡単なインストール方法)

Ubuntu で nvidia グラフィック カード ドライバーをインストールします。同じ方法で ...