webpack缓存优化

1,266 阅读3分钟

babel缓存

babel解析js是非常耗时的,想象一下,假如我们有100个js文件,某一时刻只修改了其中一个,构建的时候还是会对这100个文件进行解析,这显然是不够高效的。这时候我们可以给babel加一个缓存,再次构建时,对那些没有发生修改的js文件,直接从缓存中读取解析结果而不需要重新解析。

好了,我们在babel-loader中添加一个cacheDirectory参数配置

//.babelrc
{
  "presets": [
    "@babel/env",
    "@babel/react"
  ],
  "cacheDirectory": true,
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3
      }
    ]
  ]
}

文件资源缓存

webpack提供了hash,chunkhash,contenthash实现文件资源缓存,我们就这三种缓存机制和使用场景说一下。

当我们在浏览器中对一个文件资源发起请求后,服务端返回资源文件,如果响应头中包含了对资源的缓存信息时,浏览器会对该资源进行缓存,当我们再次请求相同文件资源时,浏览器不会向服务器发起请求,而是直接返回缓存中的资源

hash

那么有人就会说了,改变资源名称或者版本不就可以重新请求了。是的,webpack 的 hash 就可以为我们做到每次打包生成不同的hash值。如:

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[hash:6].js',  //给文件名添加hash值
    path: path.resolve(__dirname, 'dist'),
    chunkFilename: '[name].[hash:6].js'
  }
}

这样 yarn build 打包后文件名都会形如 **.36361b.js,包含一个hash值。当浏览器再次请求资源时,发现资源名字变了,于是重新向服务器请求。

但是,这样也有一个问题,webpack hash 每次打包,所有资源文件的hash值都是一样的,也就是说所有文件资源的缓存都失效了,都要再次向服务器请求。这显然是不合理的,我们只想向服务器请求那些修改了的文件资源

chunkhash

那我们是不是可以用chunkhash来解决这个问题呢?首先我们要明白webpack中chunk的概念——有依赖关系的文件资源都视为一个chunk。对于spa来说,只有一个入口,所有文件资源都直接或间接和入口文件有依赖关系,也就是说在webpack看来,一个spa就是一个chunk,所有的文件资源公用一个hash值,还是没能解决上面的问题

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[chunkhash:6].js',  //给文件名添加chunkhash值
    path: path.resolve(__dirname, 'dist'),
    chunkFilename: '[name].[chunkhash:6].js'
  }
}

但chunkhash也不是完全无用武之地,多页面打包的时候,不同的入口属于不同的chunk,还是可以使用chunkhash的

contenthash

webpack打包时,根据不同的文件生成不同的contenthash值,哎,这好像恰好可以解决上面公用hash值的问题

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[contenthash:6].js',  //给文件名添加chunkhash值
    path: path.resolve(__dirname, 'dist'),
    chunkFilename: '[name].[contenthash:6].js'
  }
}

这样两次打包前后,只有发生修改的文件资源hash值会发生改变,没有修改的文件资源hash值不会变,浏览器依然可以从缓存中拿未发生改变的资源,只需要向服务器请求内容发生改变的资源

总结

  • babel缓存时从构建的角度去提升开发效率;
  • webpack hash是从前端页面性能角度去提升用户体验;