webpack:hash、chunkhash、contenthash三者區別


Webpack里面有三種hash,分別是:hash, chunkhash, contenthash.在我們嘗試去區分他們仨之前,先來看看為什么我們需要hash。

一:為什么我們需要hash?

hash是跟整個項目的構建相關,構建生成的文件hash值都是一樣的,所以hash計算是跟整個項目的構建相關,同一次構建過程中生成的hash都是一樣的,只要項目里有文件更改,整個項目構建的hash值都會更改。

如果出口是hash,那么一旦針對項目中任何一個文件的修改,都會構建整個項目,重新獲取hash值,緩存的目的將失效。

const path = require('path');
module.exports = {
    entry: {
        index: './src/index.js',
        main: './src/main.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[hash].js',
    }
}

 

可以從上圖清晰的看見每個壓縮后的文件的hash值是一樣的,所以對於沒有改變的模塊而言,這樣做顯然不恰當,因為緩存失效了嘛。此時,chunkhash的用途隨之而來。

 

二:為什么我們需要chunkhash?

chunkhash根據不同的入口文件(Entry)進行依賴文件解析、構建對應的chunk,生成對應的哈希值。在生產環境里把一些公共庫和程序入口文件區分開,單獨打包構建,接着我們采用chunkhash的方式生成哈希值,那么只要我們不改動公共庫的代碼,就可以保證其哈希值不會受影響。並且webpack4中支持了異步import功能,固,chunkhash也作用於此,如下:
const path = require('path');
module.exports = {
    entry: {
        index: './src/index.js',
        main: './src/main.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[chunkhash].js',
    }
}
 

我們可以清晰地看見每個chunk模塊的hash是不一樣的了。

但是這樣又有一個問題,因為我們是將樣式作為模塊import到JavaScript文件中的,所以它們的chunkhash是一致的,如index.js和index.css:

這樣就會有個問題,只要對應css或則js改變,與其關聯的文件hash值也會改變,但其內容並沒有改變呢,所以沒有達到緩存意義。固contenthash的用途隨之而來。

 

三:為什么我們需要contenthash?

contenthash是針對文件內容級別的,只有你自己模塊的內容變了,那么hash值才改變,所以我們可以通過contenthash解決上訴問題。如下:

const path = require('path');
module.exports = {
    entry: {
        index: './src/index.js',
        main: './src/main.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash].js',
    }
}

contenthash表示由文件內容產生的hash值,內容不同產生的contenthash值也不一樣。

在項目中,通常做法是把項目中css都抽離出對應的css文件來加以引用。

 注: 只要文件內容不一樣,產生的哈希值就不一樣

 

總結:測試用例

webpack.config.js 文件

let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let MiniCssExtractplugin = require('mini-css-extract-plugin')

const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
    devServer: {
        port: 3000,
        progress: true,
        contentBase: './dist',
        compress: true,
    },
    mode: 'development', // development 和 production
    entry: {
        index: './src/index.js',
        main: './src/main.js',
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash].js',
    },
    module: {
        rules: [
            // { test: /\.css$/, use: 'css-loader' },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractplugin.loader, //抽離css
                    {
                        loader: 'css-loader'
                    },
                ]
            },
        ]
    },
    plugins: [ // 插件
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html',
            minify: {
                collapseWhitespace: true, // 壓縮一行
            },
            contenthash: true,
        }),
        new MiniCssExtractplugin({  // 抽離css樣式插件
            filename: './css/[name].[contenthash].css', // 
        })
    ],
}
View Code

package.json 文件

{
  "name": "hash",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --webpack.config.js",
    "dev": "webpack-dev-server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "html-webpack-plugin": "^4.5.0",
    "mini-css-extract-plugin": "^1.3.1",
    "webpack": "^5.5.1",
    "webpack-cli": "^4.2.0",
    "webpack-dev-server": "^3.11.0"
  },
  "devDependencies": {
    "css-loader": "^5.0.1"
  }
}
View Code

src文件夾

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM