Li Mei

个人技术博客

嗨,我是李梅,一名前端开发者。


主要是记录个人对技术的理解和开发过程中遇到的问题,欢迎了解更多。

webpack:如何解决浏览器缓存问题

在这篇文章里会介绍怎么在webpack中解决浏览器缓存问题。

这篇文章是基于 webpack3.10.0

默认打包的时候是直接把CSS inline到bundle文件里面

缓存

webpack打包以后的文件一般都是:app.bundle.js、vendor.bundle.js,每次发布以后,如果用户浏览器缓存没有过期,加上文件名字相同,浏览器不会从服务器下载最新文件,导致用户不能看到新发布的功能。

这就是我们所说的浏览器缓存问题。

解决方案就是,每次如果文件有改动,那么在发布的时候,就让对应bundle文件名不一样。这样,不管浏览器缓存过没过期,都会强制浏览器从服务器拿最新代码。

按照这个思路,一旦有文件改动,不管是ts,js,img还是css文件有改动,打包的时候,对应的bundle文件名也要有变化。才能强制浏览器去服务器拿最新文件,从而解决缓存问题。

chunkhash

在webpack中,build生成bundle文件的时候,在bundle文件名中加上hashcode,一旦有改动,那么bundle文件名中的hashcode也不一样,这样就保证了每次发布,bundle文件名不一样。

加上hashcode以后的bundle文件如下:

app.f68357fc8e99ece57afe.bundle.js

vendor.0d5cad4949ab26faaa39.bundle.js

具体用法是在webpack配置文件的output filename中加上 [chunkhash]

  //webpack.prod.js
  output: {
    path: path.join(process.cwd(), 'dist'),
    publicPath: "/dist/",
    filename: 'js/[name].[chunkhash].bundle.js',
  }

完整代码可参考:angular-seed-project

在terminal 跑命令行npm run build:prod之后生成文件如下:

webpack-caching-chunkhash

里面有如下三个文件,是因为用到angular lazy loading所产生的chunk文件:

0.068716ea07094f619891.bundle.js

1.3392ab62515e716550b2.bundle.js

2.f69ff655a0890c6a5b91.bundle.js

除了用chunkhash之外,还可以用hash

hash

把output filename中的chunkhash改为hash

  //webpack.prod.js
  output: {
    path: path.join(process.cwd(), 'dist'),
    publicPath: "/dist/",
    filename: 'js/[name].[hash].bundle.js',
  }

在terminal跑命令行npm run build:prod之后生成文件如下:

webpack-caching-hash

从最终bundle文件名可以看出,所有bundle文件hashcode都是一样的。

我们来测试下:改动app.component.html文件,使用hash的方式,重新build以后,bundle文件如下:

0.64de26c53b0cd5ce3331.bundle.js

1.64de26c53b0cd5ce3331.bundle.js

2.64de26c53b0cd5ce3331.bundle.js

vendor.64de26c53b0cd5ce3331.bundle.js

app.64de26c53b0cd5ce3331.bundle.js

polyfills.64de26c53b0cd5ce3331.bundle.js

所有的bundle文件名都改了,但hashcode都一样。

使用chunkhash方式,重新build以后,bundle文件如下:

0.068716ea07094f619891.bundle.js

1.3392ab62515e716550b2.bundle.js

2.f69ff655a0890c6a5b91.bundle.js

vendor.0d5cad4949ab26faaa39.bundle.js

app.c33736260b829570e8ba.bundle.js

polyfills.9d98b7f13680b7f15ee4.bundle.js

从最终bundle文件名可以看出,只有app.bundle文件的hashcode有改动,其他的都跟上一次contenthash方式编译结果一致。

hash与chunkhash的区别:

  1. hash 是用来给本次build计算hashcode,所有的编译结果文件中的hashcode都会一样。

  2. chunkhash 是用来给每个entry file计算hashcode,每个编译结果文件中的hashcode都是独一无二的。而且entry file任一文件改动,对应的bundle文件hashcode也会改动,否则就保持不变。

需要注意的是:hash 或 chunkhash最好只用在生产环境下,如果在开发环境下用,会导致编译变慢。

总结

这篇文章主要是介绍了,hash 和 chunkhash的基本用法,默认打包的时候是直接把CSS inline到bundle文件里面。

我们知道CSS在项目里面改动的次数不多,每次都inline到bundle文件里,会有以下问题:

  1. 如果本身CSS文件就很大,会导致bundle文件过大

  2. 任何一次非CSS代码改动,发布以后客户端会重新下载文件,虽然CSS没有变化,但是需要每次跟budnle文件一起下载

那么如何解决这个问题呢?

在【webpack:优化打包CSS文件】文章中会结合ExtractTextPlugin和CSS介绍更全面的解决缓存问题方案。