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

推薦する

lastInfdexOf 関数の MySQL 実装例

MySQL では lastIndexOf に似た関数を使用する必要がある場合もありますが、すぐに使用...

mysql5.7 でユーザーの初期パスワードを変更する方法

ユーザーが初めて MySQL データベースをインストールするとき、初期のルート パスワードを変更する...

Nginx イントラネット スタンドアロン リバース プロキシの実装

目次1 Nginxのインストール2 Nginxの設定3 ホストファイルを変更する4 テストNginx...

CentOS の MySQL に MariaDB をインストールするときに発生する方法と問題

以前にインストールしたmariadbを削除する1. rpm -qa | grep mariadb を...

Tomcat および Web アプリケーションの Docker デプロイメントの実装

1.dockerをオンラインでダウンロードする yum インストール -y epel-release...

Pengyou.com モバイル クライアントのダウンロード ページのデザイン共有 (画像とテキスト)

まずは簡単なデータを見てみましょう。 Googleが発表したレポートによると、 ①中国の都市の97%...

mysql-5.7.21-winx64 無料インストール版のインストール - Windows チュートリアル詳細説明

1 ダウンロードアドレスは https://dev.mysql.com/downloads/mysq...

ECMAscript の新機能の紹介

目次1. 関数パラメータのデフォルト値1.1 関数パラメータのデフォルト値の指定1.2 分離割り当て...

HTML ウェブページの段落レイアウトと改行

Web ページの外観はレイアウトに大きく左右されます。ページ内に長い段落のテキストがある場合、通常は...

HTML文書の基本構造(Webページ作成の基礎知識)

HTMLの動作原理: 1. ローカル操作: ブラウザでhtmlファイルを開く2. リモートアクセス...

Vue から React への変換入門ガイド

目次デザインコンポーネント通信ライフサイクルイベント処理品格とスタイルクラススタイル条件付きレンダリ...

CSS クラスと ID の一般的な命名規則

ページの公開名: #wrapper - ページの外側の端が全体のレイアウト幅を制御します#conta...

mysql バッチで大量のデータを削除する

mysql バッチで大量のデータを削除する1000万件のレコードを持つテーブル(syslogs)があ...

MySQLの基本操作学習ノートテーブル

テーブルを作成テーブルテーブル名を作成create table if not exists 表名 m...