9

借助 wepack 的 hash 命名法,不仅可以提高我们项目的构建效率,在生产环境中,合理设置 hash 类型有助于我们对资源进行有效的缓存。

webpack hash 种类

当无情面试官问 webpack 有几种 hash 类型?
  1. hash - 工程级

    如果出口文件设置的类型是 hash 则每次修改任何文件,所有文件名的 hash 都会跟着改变。(不能有效利用缓存)

  2. chunkhash - 模块级

    根据不同的入口文件进行依赖文件解析、构建对应的 chunk,生成对应的 hash 值。

  3. contenthash - 文件内容级

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

如何设置 hash 达到项目优化的目的?

js 文件分类构建,设置 chunkhash

首先使用 CommonsChunkPlugin 插件提取第三方库和公众模块,进行单独打包构建:

plugins: [
  new webpack.optimize.CommonsChunkPlugin({ 
    name: 'vendor',
    minChunks (module) {
      return (
        module.resource &&
        /\.js$/.test(module.resource) &&
        module.resource.indexOf(
          path.join(__dirname, '../node_modules')
        ) === 0
      )
    }
  }),
]

接着我们在 outputfilenamechunkFilename 两个字段设置 chunkhash ,生成对应 hash 值:

output: {
  path: path.resolve(__dirname, './dist'),
  publicPath: '/dist/',
  filename: 'js/[name].[chunkhash].js', 
  chunkFilename: 'js/[id].[chunkhash].js' // chunkFilename 是处理异步模块的
},

通过设置 chunkhash 最后打包出来的 js 文件会生产三种 chunkhash

  1. 正常引入的 js 文件对应的 hash
  2. 异步加载的 js 文件(如果在项目中存在的话)对应的 hash
  3. 提取的三方库和公共模块对应的 hash

image.png

那么只要对应的 js 文件代码不改动,就可以保证其 chunkhash 值不会受影响,从而达到浏览器的持久缓存。

抽离 css,设置 contenthash

首先,使用 ExtractTextPlugin 插件将所有的入口 chunk 中引用的 *.css,抽离到独立的 css 文件夹中。

抽离之后的样式将不再内嵌到 JS bundle 中,而是会放到一个单独的 CSS 文件当中,如果样式文件大小较大,这会做更快提前加载,因为 CSS bundle 会跟 JS bundle 并行加载。
plugins: [
  new ExtractTextPlugin({
    filename: 'css/[name].css',
    allChunks: true
  }),
]

之后对 css 文件进行 contenthash 命名:

plugins: [
  new ExtractTextPlugin({
    filename: 'css/[name].[contenthash].css',
    allChunks: true
  }),
]

针对 css 文件会生产对应的 contenthash 值,只要 css 文件内容没有修改,那么 contenthash 值就一直保持不变,以有效的利用浏览器缓存。

image.png

css 文件可以设置成 chunkhash 吗?

答案是不要这么做,因为 chunkhash 是模块级,我们是将样式作为模块 importjs 文件中,所以它们的 chunkhash 是一致的。

js 和所引入的 css 共用同一个 chunkhash,只要 js 改变,与其关联的 css 文件对应的 chunkhash 值也会改变,但可能其内容并没有改变,所以达不到缓存的效果。

image.png

这是 「性能优化小册」 系列第二篇小记,欢迎关注。


破晓L
2.1k 声望3.6k 粉丝

智慧之子 总以智慧为是