LoginSignup
3
1

More than 1 year has passed since last update.

Webpack hashの種類

Posted at

TL;DR

fullhashはビルド単位でハッシュ値を計算
chunkhashはエントリーポイント単位でハッシュ値を計算
contenthashはファイル単位でハッシュ値を計算

ハッシュの種類

webpackがビルドした後の出力ファイル名にハッシュを付与する場合、いくつかのハッシュ付与方法が存在する

  • hash/fullhash
  • chunkhash
  • contenthash

hash/fullhash

hashはdeprecatedになっているので、fullhashを使用するのが良い。

この方法によるハッシュはビルド単位で作成される。

frontend
└── javascripts
    └── packs
        ├── application.js
        └── test.js
const path = require("path");

module.exports = {
  context: path.resolve(__dirname),
  entry: {
    application: "./frontend/javascripts/packs/application.js",
    test: "./frontend/javascripts/packs/test.js",
  },
  output: {
    path: path.resolve(__dirname, "public/packs"), // output <absolute path>/public/packs
    filename: "[name]-[fullhash].js",
    chunkFilename: "[name].bundle-[fullhash].js", // [hash] is deprecated
    publicPath: "/packs/",
  },
};

この状態で npx webpackによりビルドすると、

public/
├── packs
│   ├── application-c49cafe8d5713d24946e.js
│   └── test-c49cafe8d5713d24946e.js

上記のように 2つのエントリーポイントに対して同じハッシュが付与される。

片方のエントリーポイントしか修正していないのに、もう片方のハッシュも変更されるので、キャッシュの面で不利になる。

chunkhash

fullhashの場合は、あるチャンク内(あるエントリーポイント内で使用されるファイル群)のファイルが変更されたら他のチャンクのハッシュも変更されていた。
chunkhashの場合は、変更されたファイルを含んでいるチャンクのみハッシュ値が変更される。

application.js
console.log("hello Webpack!");
test.js
console.log("test.js");
❯❯❯ npx webpack
asset application-d75b5929b37355efec43.js 1.39 KiB [emitted] [immutable] (name: application)
asset test-00d31fb47a5466fd5acf.js 1.35 KiB [emitted] [immutable] (name: test)
./frontend/javascripts/packs/application.js 31 bytes [built] [code generated]
./frontend/javascripts/packs/test.js 30 bytes [built] [code generated]

hash値は以下
application.js -> d75b5929b37355efec43
test.js -> 00d31fb47a5466fd5acf

application.js
console.log("hello Webpack!");
test.js
// このファイルのみ変更(application.jsとは違うエントリーポイント)
console.log("chunk hash!!");
❯❯❯ npx webpack
assets by status 1.39 KiB [cached] 1 asset
asset test-9d106a1d904530f7c882.js 1.34 KiB [emitted] [immutable] (name: test)
./frontend/javascripts/packs/application.js 31 bytes [built] [code generated]
./frontend/javascripts/packs/test.js 28 bytes [built] [code generated]
webpack 5.73.0 compiled successfully in 82 ms

test.js のみハッシュ値が変更されているのがわかる。

次に、
test.jsからimportするファイルを作成してみる

test.js
import hoge from "./hoge.js";
hoge();
console.log("chunk hash!");
hoge.js
export default () => {
  console.log("hoge.js");
};
npx webpack
assets by status 1.39 KiB [cached] 1 asset
asset test-22ad79f1d4a9552d9dd0.js 4.46 KiB [emitted] [immutable] (name: test)
runtime modules 670 bytes 3 modules
cacheable modules 149 bytes
  ./frontend/javascripts/packs/application.js 31 bytes [built] [code generated]
  ./frontend/javascripts/packs/test.js 66 bytes [built] [code generated]
  ./frontend/javascripts/packs/hoge.js 52 bytes [built] [code generated]
webpack 5.73.0 compiled successfully in 141 ms

test.js のハッシュ値は 22ad79f1d4a9552d9dd0

次に、test.js本体ではなく、test.jsからimportしているhoge.jsの内容を変更してみる。

hoge.js
export default () => {
  console.log("modified!");
};
npx webpack
assets by status 1.39 KiB [cached] 1 asset
asset test-c0c483b67ef7151c01ba.js 4.48 KiB [emitted] [immutable] (name: test)
runtime modules 670 bytes 3 modules
cacheable modules 166 bytes
  ./frontend/javascripts/packs/application.js 31 bytes [built] [code generated]
  ./frontend/javascripts/packs/test.js 66 bytes [built] [code generated]
  ./frontend/javascripts/packs/hoge.js 69 bytes [built] [code generated]

test.js のハッシュ値が c0c483b67ef7151c01ba に変わっている。

よって chunkhash の場合は、 entrypointとなるjsファイルだけでなく、entrypointからimportしているファイルの変更に対してもハッシュ値の変更が行われる。

cssを絡ませてcontenthashとchunkhashの挙動の違いを探る

chunkhash

webpack.config.js
const path = require("path");

module.exports = {
  mode: "development",
  context: path.resolve(__dirname),
  entry: {
    application: "./frontend/javascripts/packs/application.js",
  },
  output: {
    path: path.resolve(__dirname, "public/packs"), // output <absolute path>/public/packs
    filename: "[name]-fiilename-[chunkhash].js",
    chunkFilename: "[name].chunkFilename-[chunkhash].js", // [hash] is deprecated
    publicPath: "/packs/",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        // 配列の最後尾から順に実行される。
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name]-[chunkhash].css", // <- この chunkhashに注目
    }),
  ],
};
❯❯❯ npx webpack
asset application-fiilename-9b7d9841aa7d632e513f.js 5.12 KiB [emitted] [immutable] (name: application)
asset application-9b7d9841aa7d632e513f.css 310 bytes [emitted] [immutable] (name: application)
Entrypoint application 5.42 KiB = application-9b7d9841aa7d632e513f.css 310 bytes application-fiilename-9b7d9841aa7d632e513f.js 5.12 KiB
orphan modules 2.78 KiB (javascript) 937 bytes (runtime) [orphan] 7 modules
runtime modules 670 bytes 3 modules
cacheable modules 194 bytes (javascript) 28 bytes (css/mini-extract)
  modules by path ./frontend/javascripts/packs/*.js 144 bytes
    ./frontend/javascripts/packs/application.js 90 bytes [built] [code generated]
    ./frontend/javascripts/packs/hoge.js 54 bytes [built] [code generated]
  modules by path ./frontend/javascripts/packs/*.css 50 bytes (javascript) 28 bytes (css/mini-extract)
    ./frontend/javascripts/packs/index.css 50 bytes [built] [code generated]
    css ./node_modules/css-loader/dist/cjs.js!./frontend/javascripts/packs/index.css 28 bytes [built] [code generated]
webpack 5.73.0 compiled successfully in 455 ms

application-fiilename-9b7d9841aa7d632e513f.js
application-9b7d9841aa7d632e513f.css
でhashが一緒。

contenthash

webpack.config.js
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name]-[chunkhash].css", // <- ここだけ contenthashに変更
    }),
  ],
❯❯❯ npx webpack
asset application-fiilename-fd0333cc80317b8b2be1.js 5.12 KiB [emitted] [immutable] (name: application)
asset application-1d6012e7893a7eca9678.css 310 bytes [emitted] [immutable] (name: application)
Entrypoint application 5.42 KiB = application-1d6012e7893a7eca9678.css 310 bytes application-fiilename-fd0333cc80317b8b2be1.js 5.12 KiB
orphan modules 2.78 KiB (javascript) 937 bytes (runtime) [orphan] 7 modules
runtime modules 670 bytes 3 modules
cacheable modules 187 bytes (javascript) 28 bytes (css/mini-extract)
  modules by path ./frontend/javascripts/packs/*.js 137 bytes
    ./frontend/javascripts/packs/application.js 90 bytes [built] [code generated]
    ./frontend/javascripts/packs/hoge.js 47 bytes [built] [code generated]
  modules by path ./frontend/javascripts/packs/*.css 50 bytes (javascript) 28 bytes (css/mini-extract)
    ./frontend/javascripts/packs/index.css 50 bytes [built] [code generated]
    css ./node_modules/css-loader/dist/cjs.js!./frontend/javascripts/packs/index.css 28 bytes [built] [code generated]
webpack 5.73.0 compiled successfully in 477 ms

application-fiilename-fd0333cc80317b8b2be1.js
application-1d6012e7893a7eca9678.css
ハッシュが異なっている!

jsファイルを変更してみる。

hoge.js
export default () => {
  console.log("updated only js file!");
};
❯❯❯ npx webpack
assets by status 310 bytes [cached] 1 asset
asset application-fiilename-195324247dbe25d9fa84.js 5.13 KiB [emitted] [immutable] (name: application)
Entrypoint application 5.44 KiB = application-1d6012e7893a7eca9678.css 310 bytes application-fiilename-195324247dbe25d9fa84.js 5.13 KiB
orphan modules 2.78 KiB (javascript) 937 bytes (runtime) [orphan] 7 modules
runtime modules 670 bytes 3 modules
cacheable modules 206 bytes (javascript) 28 bytes (css/mini-extract)
  modules by path ./frontend/javascripts/packs/*.js 156 bytes
    ./frontend/javascripts/packs/application.js 90 bytes [built] [code generated]
    ./frontend/javascripts/packs/hoge.js 66 bytes [built] [code generated]
  modules by path ./frontend/javascripts/packs/*.css 50 bytes (javascript) 28 bytes (css/mini-extract)
    ./frontend/javascripts/packs/index.css 50 bytes [built] [code generated]
    css ./node_modules/css-loader/dist/cjs.js!./frontend/javascripts/packs/index.css 28 bytes [built] [code generated]
webpack 5.73.0 compiled successfully in 450 ms

application-fiilename-195324247dbe25d9fa84.js
application-1d6012e7893a7eca9678.css

jsファイルのhashだけ変更されていて、cssのhashは変更されていない!!

結論、 MiniCssExtractPlugin のように別ファイルとしてbundle fileを出力したい場合、 chunkhashだと他のファイルが変更されてもhash値が変わってしまう。
今回の例でいうとcssを修正していないのに、jsファイルが変更されたことでcssのハッシュ値、ひいてはファイル名が異なることでブラウザのキャッシュが効かなくなり余計なリロードが発生してしまう。
そこで、別ファイルとして出力したいファイルに対しては、contenthashを指定してあげることで他のファイルの変更によって、自身のハッシュ値が変更されることがなくなる。

参考記事

https://webpack.js.org/configuration/output/#outputfilename
https://webpack.js.org/plugins/mini-css-extract-plugin/

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1