美文网首页
webpack 持久化缓存

webpack 持久化缓存

作者: DC_er | 来源:发表于2019-05-14 15:16 被阅读0次

前言

  1. 什么是持久化缓存,为什么做持久化缓存?
  2. webpack 如何做持久化缓存?

持久化缓存

首先我们需要去解释一下,什么是持久化缓存,在现在前后端分离的应用大行其道的背景下,前端 html,css,js 往往是以一种静态资源文件的形式存在于服务器,通过接口来获取数据来展示动态内容。这就涉及到公司如何去部署前端代码的问题,所以就涉及到一个更新部署的问题,是先部署页面,还是先部署资源?

  • 先部署页面,再部署资源:在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本资源当做新版本缓存起来,其结果就是:用户访问到一个样式错乱的页面,除非手动去刷新,否则在资源缓存过期之前,页面会一直处于错乱的状态。
  • 先部署资源,再部署页面:在部署时间间隔内,有旧版本的资源本地缓存的用户访问网站,由于请求的页面是旧版本,资源引用没有改变,浏览器将直接使用本地缓存,这样属于正常情况,但没有本地缓存或者缓存过期的用户在访问网站的时候,就会出现旧版本页面加载新版本资源的情况,导致页面执行错误。

所以我们需要一种部署策略来保证在更新我们线上的代码的时候,线上用户也能平滑地过渡并且正确打开我们的网站。

推荐先看这个回答:大公司里怎样开发和部署前端代码?

当你读完上面的回答,大致就会明白,现在比较成熟的持久化缓存方案就是在静态资源的名字后面加 hash 值,因为每次修改文件生成的 hash 值不一样,这样做的好处在于增量式发布文件,避免覆盖掉之前文件从而导致线上的用户访问失效。

因为只要做到每次发布的静态资源(css, js, img)的名称都是独一无二的,那么我就可以:

  • 针对** html 文件:不开启缓存,把 html 放到自己的服务器上,关闭服务器的缓存**,自己的服务器只提供 html 文件和数据接口
  • 针对静态的 js,css,图片等文件:开启 cdn 和缓存,将静态资源上传到 cdn 服务商,我们可以对资源开启长期缓存,因为每个资源的路径都是独一无二的,所以不会导致资源被覆盖,保证线上用户访问的稳定性。静态资源放置于独立域名之下的好处
  • 每次发布更新的时候,先将静态资源(js, css, img) 传到 cdn 服务上,然后再上传 html 文件,这样既保证了老用户能否正常访问,又能让新用户看到新的页面。

上面大致介绍了下主流的前端持久化缓存方案,那么我们为什么需要做持久化缓存呢?

  • 用户使用浏览器第一次访问我们的站点时,该页面引入了各式各样的静态资源,如果我们能做到持久化缓存的话,可以在 http 响应头加上 Cache-control 或 Expires 字段来设置缓存,浏览器可以将这些资源一一缓存到本地。
  • 用户在后续访问的时候,如果需要再次请求同样的静态资源,且静态资源没有过期,那么浏览器可以直接走本地缓存而不用再通过网络请求资源。

webpack 如何做持久化缓存

上面简单介绍完持久化缓存,下面这个才是重点,那么我们应该如何在 webpack 中进行持久化缓存的呢,我们需要做到以下两点:

  • 保证 hash 值的唯一性,即为每个打包后的资源生成一个独一无二的 hash 值,只要打包内容不一致,那么 hash 值就不一致。
  • 保证 hash 值的稳定性,我们需要做到修改某个模块的时候,只有受影响的打包后文件 hash 值改变,与该模块无关的打包文件 hash 值不变。

hash 文件名是实现持久化缓存的第一步,目前 webpack 有两种计算 hash 的方式([hash] 和 [chunkhash])

  • hash 代表每次 webpack 在编译的过程中会生成唯一的 hash 值,在项目中任何一个文件改动后就会被重新创建,然后 webpack 计算新的 hash 值
  • chunkhash 是根据模块计算出来的 hash 值,所以某个文件的改动只会影响它本身的 hash 值不会影响其他文件。

所以如果你只是单纯地将所有内容打包成同一个文件,那么 hash 就能够满足你了,如果你的项目涉及到拆包,分模块进行加载等等,那么你需要用 chunkhash,来保证每次更新之后只有相关的文件 hash 值发生改变。

所以我们在一份具有持久化缓存的 webpack 配置应该长这样:

module.exports = {
 entry: __dirname + '/src/index.js',
 output: {
 path: __dirname + '/dist',
 filename: '[name].[chunkhash:8].js',
 }
}

上面代码的含义就是:以 index.js 为入口,将所有的代码全部打包成一个文件取名为 index.xxxx.js 并放到 dist 目录下,现在我们可以在每次更新项目的时候做到生成新命名的文件了。

如果是应付简单的场景,这样做就够了,但是在大型多页面应用中,我们往往需要对页面进行性能优化:

  • 分离业务代码和第三方的代码:之所以将业务代码和第三方代码分离出来,是因为业务代码更新频率高,而第三方代码更新迭代速度慢,所以我们将第三方代码(库,框架)进行抽离,这样可以充分利用浏览器的缓存来加载第三方库。
  • 按需加载:比如在使用 React-Router 的时候,当用户需要访问到某个路由的时候再去加载对应的组件,那么用户没有必要在一开始的时候就将所有的路由组件下载到本地。
  • 在多页面应用中,我们往往可以将公共模块进行抽离,比如 header, footer 等等,这样页面在进行跳转的时候这些公共模块因为存在于缓存里,就可以直接进行加载了,而不是再进行网络请求了。

那么如何进行分隔打包,分模块进行加载。在webpack4之前,借助 webpack 内置插件:CommonsChunkPlugin可以实现分隔打包,深入理解 webpack 文件打包机制。在webpack4之后,借助内置SplitChunks即可轻松实现。webpack4 SplitChunks实现代码分隔详解

相关文章

  • webpack 持久化缓存

    前言 什么是持久化缓存,为什么做持久化缓存? webpack 如何做持久化缓存? 持久化缓存 首先我们需要去解释一...

  • webpack5新特性

    1 持久化缓存 缓存在webpack5中默认开启,缓存默认是在内存里,但可以对cache进行设置cache: { ...

  • webpack持久化实践

    webpack持久化实践

  • Webpack实现持久缓存

    持久缓存 使用webpack构建工程的时候,我们往常会把功能不同的代码打包到不同的包里(如lib,vendor,业...

  • 分布式-缓存

    缓存 Memcached 不可持久化Redis 可持久化 Memcached Memcached数据访问模型添加新...

  • hiberante3-day2

    一、hibernate持久化对象状态(一级缓存)持久化对象 Persistent Object = POJO +...

  • 数据持久化

    数据持久化及数据更新缓存 常用的8种缓存机制:HTTP缓存, locationStorage, Session S...

  • Hibernate学习(二)

    目录 Hibernate的持久化类介绍Hibernate持久化对象的状态Hibernate的一级缓存Hiberna...

  • RDD持久化

    为什么需要持久化 所谓的持久化,就是将数据进行保存,避免数据丢失。RDD持久化并非将数据落盘保存,而是用作缓存。了...

  • 2 kafka的特性

    消息持久化和缓存Kafka高度依赖文件系统来存储和缓存消息。一般的人都认为“磁盘是缓慢的”,这使得人们对“持久化结...

网友评论

      本文标题:webpack 持久化缓存

      本文链接:https://www.haomeiwen.com/subject/jawsaqtx.html