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',
    }
}

webpack:hash、chunkhash、contenthash三者区别

 

可以从上图清晰的看见每个压缩后的文件的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',
    }
}
  webpack:hash、chunkhash、contenthash三者区别

我们可以清晰地看见每个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',
    }
}

webpack:hash、chunkhash、contenthash三者区别

contenthash表示由文件内容产生的hash值,内容不同产生的contenthash值也不一样。

在项目中,通常做法是把项目中css都抽离出对应的css文件来加以引用。

 注: 只要文件内容不一样,产生的哈希值就不一样

 

总结:测试用例

webpack.config.js 文件

webpack:hash、chunkhash、contenthash三者区别
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 文件

webpack:hash、chunkhash、contenthash三者区别
{
  "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文件夹

webpack:hash、chunkhash、contenthash三者区别

 

 

上一篇:webpack高级概念,webpack与浏览器的缓存(系列九)


下一篇:录入订单时出现错误信息“APP-ONT-250271:不允许联机折扣,价目表价格为零或没有价目表”