お役立ちコラム
フロントエンド

Webpackで出力ファイルにハッシュ値を自動で付ける方法!

※本記事には広告が含まれます

今回は、Webpackで出力ファイルにハッシュ値を自動で付ける方法を解説します。

Webpackでは、ブラウザキャッシュへの対策として、バンドルしたファイル名にハッシュ値を付与して出力することが可能です。

また、HtmlWebpackPluginなどのプラグインを活用することで、ビルドのたびに変化するハッシュ値付きのJavaScriptファイルを、HTMLへ自動的に挿入させることができます。

(参考)Webpackでバンドル後のJavaScriptをHTMLに自動で読み込ませる方法

ブラウザキャッシュ対策(キャッシュバスティング)を効率的に実現したい方は、ぜひ参考にしてみて下さい。

ハッシュとは?

ハッシュとは、特定の計算手順を用いて、元のデータを一見ランダムに見える値に変換することを言います。

このとき、変換に用いる計算手順を「ハッシュ関数」、それによって算出された値を「ハッシュ値」と呼びます。

Webpackでは、ビルドの度にハッシュ値が生成され、それをファイル名に付与することができます。

これにより、ブラウザキャッシュが効いている状態でも、コンテンツが更新された際には別ファイルとして認識させ、強制的に最新のデータを読み込ませる(キャッシュバスティング)ことが可能になります。

Webpackのハッシュの種類

Webpackでは、以下3つのテンプレート文字列を使用できます。

[fullhash]プロジェクト内のどこか1箇所でも修正があれば、生成されるすべてのファイル名が変更される。
[contenthash](推奨)ファイルの内容に基づいたハッシュ。他のファイルで修正があっても、そのファイル自体に変更がなければハッシュ値(ファイル名)が維持される。
[chunkhash]チャンク(エントリーポイントごとの塊)単位のハッシュ。特定のチャンク、およびそのチャンクが依存しているファイルに変更があった場合のみ、関連するファイルのハッシュ値が変更される。

Webpackの設定ファイル(webpack.config.js)において、output.filenameにテンプレート文字列を設定することで、ビルドごとに一意のハッシュ値をファイル名に付与できます。

const path = require("node:path"); // Node.jsに標準で用意されているpathモジュールの読み込み
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "production",
  entry: "./src/index.js", // エントリーポイントの指定
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[fullhash].js", // 出力時のファイル名の指定
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        // エントリー名が'main'の場合は'style.css'を返す
        // それ以外はエントリー名そのまま([name].css)にする
        return pathData.chunk.name === "main"
          ? "style.[fullhash].css"
          : "[name].[fullhash].css";
      },
    }),
    new HtmlWebpackPlugin({
      // ビルド時に使用するHTMLテンプレートを指定
      template: "./src/index.html",
      // 生成されたスクリプトタグを挿入する位置(bodyの末尾)
      inject: "body",
      // このHTMLに自動で読み込ませるエントリーポイントを指定(複数指定する場合は配列の中でカンマ区切りで指定)
      chunks: ["main"],
    }),
  ],
  module: {
    rules: [
      {
        test: /\.scss$/, //どの拡張子のファイルに適用させるかを指定
        use: [
          //変換されたCSSをJavaScriptとは別のCSSファイルとして抽出
          MiniCssExtractPlugin.loader,
          //CSSをJavaScriptからimportできる形に変換
          "css-loader",
          //WebpackからPostCSSを呼び出して実行
          "postcss-loader",
          //Webpackからsassを呼び出してSass→CSSを実行
          "sass-loader",
        ],
      },
    ],
  },
};

[fullhash]

[fullhash]は、プロジェクト内のどこか1箇所でも修正があれば、生成されるすべてのファイル名が変更されるハッシュです。

[fullhash]を使用している場合、修正していないファイルのキャッシュまで無効化してしまうため、利用シーンはあまりありません。

const path = require("node:path"); // Node.jsに標準で用意されているpathモジュールの読み込み
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "production",
  entry: "./src/index.js", // エントリーポイントの指定
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[fullhash].js", // 出力時のファイル名の指定
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        // エントリー名が'main'の場合は'style.css'を返す
        // それ以外はエントリー名そのまま([name].css)にする
        return pathData.chunk.name === "main"
          ? "style.[fullhash].css"
          : "[name].[fullhash].css";
      },
    }),
    //以下省略
  ],
  //以下省略
};

[contenthash]

[contenthash]は、ファイルの内容(コンテンツ)に基づいて生成されるハッシュです。

特徴は、他のファイルに修正があっても、そのファイル自体に変更がない限りハッシュ値(ファイル名)が維持される点にあります。

これにより、内容が変わったファイルのみを更新し、それ以外はブラウザキャッシュを継続利用させることができるため、不要な再ダウンロードを抑制し、サイトの高速化を実現できます。

const path = require("node:path"); // Node.jsに標準で用意されているpathモジュールの読み込み
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "production",
  entry: "./src/index.js", // エントリーポイントの指定
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[contenthash].js", // 出力時のファイル名の指定
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        // エントリー名が'main'の場合は'style.css'を返す
        // それ以外はエントリー名そのまま([name].css)にする
        return pathData.chunk.name === "main"
          ? "style.[contenthash].css"
          : "[name].[contenthash].css";
      },
    }),
    //以下省略
  ],
  //以下省略
};

[chunkhash]

[chunkhash]は、チャンク(エントリーポイントごとの塊)単位のハッシュです。

エントリーポイントが複数ある構成において、ある特定のファイルに変更を加えた場合、[chunkhash]を使用していると「変更があったエントリーポイント、およびその依存関係にあるチャンク」のハッシュ値のみが更新されます。

無関係なエントリーポイントのハッシュ値は維持されるため、ブラウザキャッシュを効率的に活用することが可能です。

const path = require("node:path"); // Node.jsに標準で用意されているpathモジュールの読み込み
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "production",
  entry: {
    main: "./src/index.js",
    top: "./src/top.js",
    about: "./src/about.js",
  }, // エントリーポイントの指定
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[chunkhash].js", // 出力時のファイル名の指定
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        // エントリー名が'main'の場合は'style.css'を返す
        // それ以外はエントリー名そのまま([name].css)にする
        return pathData.chunk.name === "main"
          ? "style.[chunkhash].css"
          : "[name].[chunkhash].css";
      },
    }),
    //以下省略
  ],
  //以下省略
};

まとめ

今回は、Webpackの3種類のハッシュ(fullhash・contenthash・chunkhash)を解説しました。

ハッシュを使いこなすことで、ブラウザキャッシュの効率に大きな差を生みます。

ご自身のプロジェクトの構成に合わせて、最適なハッシュ戦略を取り入れてみてください。

次回はWebpackで画像ファイルを読み込む方法を解説します。

今回は以上になります。最後までご覧頂き、ありがとうございました。

Webサイトのスポット修正・保守ならお任せ下さい!

ちょっとした修正や調整をしたいけれど、「制作会社に頼んだら高額になりそう」「どこに相談すればいいかわからない」そんなお悩みはありませんか?

弊所「E-VALUE WORKS」では、テキスト修正や軽微な調整などのスポット対応から、月額での保守・管理(外部Web担当)まで、ニーズに合わせたWebサイトの修正・保守サービスを提供しています。

「これって依頼できる?」という段階でも構いません。まずはお気軽にご相談ください。

E-VALUE WORKS アイコン
HOMEお役立ちコラムフロントエンドWebpackで出力ファイルにハッシュ値を自動で付ける方法!