0%

覆盖更新与增量更新

覆盖更新

实现方案是在引用资源的URL后添加请求参数,比如添加时间戳参数,

浏览器会将参数不同的URL视为全新的URL,所以浏览器向服务器请求并下载最新资源,我们只更新修改了的资源,为了避免手动改参数,将hash指纹(通过mds算法得到)作为URL的v参数

1
2
3
4
5
<head>
<link rel='stylesheet' href="main.home.css?v=858d5483">
<script type="text/javascript" src="main.home.js?v=bbcadaf73"></script>

</head>

缺点:

  • 必须保证html文件与改动的静态文件同步更新,否则会出现资源不同步的情况。如果是无服务端渲染的项目,html文件被视为金泰之源,并且与其他今天资源(js/css/图片等)部署到同一台服务器,在这种情况下,我们可以保证资源的同步更新,不会受到覆盖更新的影响。但是对于依赖服务端渲染的项目,大多数的部署方式是将网站的入口HTML和静态资源分开部署,比如,HTML与服务器代码一同部署到域名为ww.app.com对应的服务器,把JS/CSS等静态资源部署到static.app.com对应的服务器,两种资源分开部署必然有先后顺序,这就意味着两种资源的上线存在时间差,不论先部署哪种资源无法保证所有用户访问页面的正确性,即使时间差小,对于淘宝这种访问量庞大的网站来说也会影响用户群,这就是为什么很多团队总是选择在半夜或者凌晨这种访问量较小的时间段发布新版本的原因之一
  • 不利于版本回滚。由于覆盖更新每次迭代之后的资源都会覆盖服务器上原有的旧版本文件,这对于版本回滚操作很不友好,运维人员吗要么借助于服务器本身的缓存机制要么拿到旧版本文件再次覆盖

增量更新

将原本作为参数值的hash指纹作为资源文件名的一部分并且删除用于更新的url参数

1
2
3
4
5
<head>
<link rel='stylesheet' href="main.home.858d5483.css">
<script type="text/javascript" src="main.home.bbcadaf73.js"></script>

</head>

在静态资源使用增量更新前提下可以将静态资源先于动态HTML部署,此时静态资源没有引用入口,不会对线上环境产生影响;动态HTML部署后即可在第一时间访问已存的最新静态资源。解决覆盖更新部署同步问题

增量更新修改了资源文件名,不会覆盖已存的旧版本文件,运维人员进行回滚操作只需回滚HTML即可,优化了版本控制,支持多版本共存

按需加载与多模块架构场景的增量更新

假设一个页面有主模块main.app.js,同步模块module.sync.js,构建后与主模块合并为主文件的main.app.[hash].js,同步加载,异步模块module.async.js,构建后为异步文件app.async.[hash].js

缺陷:当更新异步文件的hash指纹,主文件的hash没有同步修改,不能获取到最新资源

解决:

webpack中的chunkhash:

hash与chunkhash:

hash:the hash of compilation,webpack的compilation对象代表某个版本资源对应的编译进程,当使用webpack的development中间件,每次检测到项目文件有改动就会创建一个compilation,进而能够针对改动生产全新的编译文件。compilation对象不是针对单个文件,是针对项目中所有参与构建的文件,只要任何一个文件改动,compilation对象就改变,作为compilation的hash值就相应改变,因此不论同步文件还是异步文件构建输出后均有相同hash,显然不合理

chunk在webpack中含义可以理解为散列模块经合并后的“块”,比如同步模块module.sync.js和主模块main.app.js合并为一个“块”,异步模块module.async.js是另一个块,chunkhash就是一个个块依据自身代码内容计算所得的hash值。

1
2
3
4
output:{
filename:'[name].[chunkhahs:8].js'

}
主文件 异步文件
原始状态 main.app.8d136fcd.js app.async.67fa68a0.js
修改主模块main.app.js hash改变 hash不变
修改同步模块modue.sync.js hash改变 hash不变
修改异步模块module.async.js hash改变 hash改变

contenthash

webpack默认将CSS代码合并到js文件,要把CSS文件抽离处理独立维护,既有利于浏览器的渲染优化,又能够更好利用客户端缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
test:/\.css$/,
use:ExtractTextPlugin.extract({
filename:'./dest/[name].[contenthash:8].css'
use:[{
loader:'css-loader',
options::{
importLoaders:2
}

}],
publishPath:'/'
})

}

contenthash就是解耦js与css文件hash指纹的关键,contenthash是由ExtractTextPlugin插件提供,代表被导出内容计算后的hash值,如果不用contenthash,main.app.css不会参与chunk的chunkhash计算,但也不会作为一个独立的Chunk进行单独计算,编译后的css文件取值与主文件相同

使用contenthash:

主文件hash 异步文件hash CSS文件hash
修改主模块 不变 不变
修改同步模块 不变 不变
修改异步模块 不变 不变
修改CSS 不变 不变