03.webpack中hash,chunkhash和contenthash 的区别

  • hash、contenthash 和 chunkhash 是通过散列函数处理之后,生成的一串字符,可用于区分文件。

    作用:善用文件的哈希值,解决浏览器缓存导致的资源未及时更新的问题

    1.文件名不带哈希值

javascript 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
    entry: {
        index: path.join(srcPath, 'index.js'),
        other: path.join(srcPath, 'other.js')
    },
    module: {
        rules: [
    
        ]
    },
    plugins: [
        // 多入口 - 生成 index.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'index.html'),
            filename: 'index.html',
            // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
            chunks: ['index']  // 只引用 index.js
        }),
        // 多入口 - 生成 other.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'other.html'),
            filename: 'other.html',
            chunks: ['other']  // 只引用 other.js
        })
    ]
}
  • 默认打包的情况下,打包出来的文件是不带哈希值的

2. 问题所在

每一次编译后,生成的文件名都一样,这样会存在一个问题,通过 webpack 编译生成的静态文件会被我们放置到服务器中,当编译后的文件更新时,由于浏览器或者服务器设置的缓存策略,同名文件可能不会立刻被更新,导致用户访问到的仍然是上一次的版本。

3.hash

为了解决这个问题,我们通常会在文件名上加一些哈希值,保证当更新文件时,浏览器会重新下载资源。这里使用 hash这个占位符

javascript 复制代码
const path = require('path')
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'production',
    output: {
        // filename: 'bundle.[contentHash:8].js',  // 打包代码时,加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口时 entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
    },
    module: {
        rules: [
            
        ]
    },
    plugins: [
        new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('production')
        })
    ]
})
  • 打包出来如下,带上hash值
  • 当项目里没有文件发生改变时,无论如何重新编译,文件哈希值都不会变。但此时,改变了 index.js文件,增加一句输出,所有文件的哈希值都会同时改变。
  • 所存在的问题: 所有文件的哈希值都发生了变化,导致即使只更新了一个文件都需要重新加载所有资源,还是有些浪费性能的

4.chunkhash

这里是多入口的项目,只改变了 index.js这个入口,不希望 other.js入口的文件也被修改,就可以使用占位符 chunkhash来解决,另外哈希值比较长,截取八位显示。

javascript 复制代码
module.exports = {
  // 部分配置省略
  output: {
        // filename: 'bundle.[contentHash:8].js',  // 打包代码时,加上 hash 戳
        filename: '[name].[chunkhash:8].js', // name 即多入口时 entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
    },
  plugins: [
    
  ],
};
  • 可以看到同一个 chunk 打包出来的哈希值是一样的,在同一个入口中的hash是一样的
  • 当修改了 css 文件时,只有同 chunk 的 main.js 和 main.css 文件的哈希值发生了改变,
  • css 文件是在 main.js这个 chunk 的,但 other.js本身没有发生任何修改,可以不用重新加载

5.contenthash

同一个 chunk 中,部分文件修改导致所有文件的哈希值发生变化的问题,可以使用 contenthash 来解决,contenthash 只和每一个文件的内容有关,内容发生变化,则重新生成哈希值

javascript 复制代码
module.exports = {
  // 部分配置省略
  output: {
    filename: '[name]_[contenthash:8].js',
    path: path.resolve(__dirname, "./dist"),
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: './[name]_[contenthash:8].css',
    }),
  ],
};
  • 每一个文件生成的哈希值都不一样
  • 在index.js中多新增一行代码在打包,可以看到maincsshash不会发生变化

总结

在 webpack 中有三种生成哈希值规则的方式,可以用来区分文件是否修改。

  • hash 与整个项目有关,项目里有文件修改,所有文件的哈希值都会变化。
  • chunkhash 与入口有关,同一入口的文件被视为一个整体,当其中一个文件修改时,同入口的所有文件哈希值发生改变。
  • contenthash 只与文件内容有关,文件内容发生改变,才会更改该文件的哈希值。
相关推荐
格子软件12 小时前
2026年GEO优化系统源码级状态机与多模型调度拆解
java·前端·vue.js·人工智能·vue·geo
HUMHSX13 小时前
Vue 项目启动全流程解析:从入口文件到全局指令注册与页面渲染
前端·javascript·vue.js
有颜有货13 小时前
PMC生产排产的4种算法,一次讲清
java·服务器·前端
小虎牙00713 小时前
Android kotlin图片库Coil源码详解
android·前端
随风一样自由13 小时前
【前端领域】前端开发核心应用场景与落地实践
前端·前端框架
an3174214 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
谢尔登14 小时前
【React】 状态管理方案
前端·react.js·前端框架
用户21366100357214 小时前
Vue商品详情与放大镜组件
前端·javascript
半个落月14 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript
李明卫杭州14 小时前
Vue2 中 v-model 处理不同数据结构的技巧
前端·javascript·vue.js