我们公司前端采用的是覆盖式发布,过程就是:每次上线时构建好前端项目,将构建产物丢给运维,运维直接用新构建直接替换掉线上的版本(一般小作坊应该都是这么搞的...为啥这么搞?我想理由应该是想同的,在此我就不过多解读了)简单粗暴的背后隐患是很大的:假设这么个场景,有用户a和用户b有在使用我们的平台,有一天某时某刻,a正在使用我们的平台,成功登陆后,开始操作balabala,然后a没有关浏览器窗口,也没有关电脑,然后出去嗨了...在a嗨的同时,我们公司可爱的前端同学修复了一个bug,测试好了之后上线了一版,恰巧上线完成之后,b用户也来访问我们的平台,跟a一样的操作,没有出什么问题,但是a这时候继续使用我们平台的时候,问题就来了,发现点击好多页面没有反应,万幸的是a会武术,a打开f12后发现好多js文件404了?什么 ,我嗨之前不是好好的吗?怎么嗨完回来就gg了...
分析
仔细详细详细,这种场景下,用户a的问题是不是偶发还是必然?当然是必然了。。。不要给方案上的缺陷找借口了。。。现在前端开发一般是webpack构建项目,在html只会写一个入口的js文件,多个页面的js文件都会被webapck切分代码在配置中映射起来,通过webpack.require来进行懒加载。比方说用户页面和设置页面,用户访问用户页面(没有打开设置页面),这个时候我们修改设置页面并更新一个新版本,用户在打开设置页面的时候就会出现js404:入口js文件记录的设置页面还是修改前的js哈希文件,我们上线后会覆盖掉之前的文件,因此用户就会报js404错误。。。
解决
发布方案估计在很长一段时间没得改了。。。那就只能在现有基础上改了。。。在网上查找了解到有人使用 addEventListener 这种方法,第三个参数必须为true,使用捕获传播(因为是监听资源的错误),如下
window.addEventListener("error", handler, true)
思路就是,如果监听到错误,判断是否为js错误,然后获取js的src值,进行一次HEAD请求,确认是否http返回状态码为404,如果是404的话提示用户更新版本(刷新页面)后再使用:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
/**
* 判断js资源是否返回404状态码
* @param url
* @return {Promise<any>}
*/
function isScript404(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.open('HEAD', url, false)
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 404) {
resolve(true)
return
}
resolve(false)
}
xhr.send()
})
}
/**
* 处理错误函数
* @param e
*/
async function handleError(e) {
console.log('script resource load error....')
let script = e.target
let SCRIPT = 'SCRIPT'
let tagName = script.tagName
let src = script.src
// js资源网络请求失败
if (SCRIPT === tagName) {
let bool = await isScript404(src)
if (!bool) {
return
}
console.log('更新版本,请刷新页面')
}
}
// 绑定事件
window.addEventListener('error', handleError, true)
</script>
<script src="b.js"></script>
</body>
</html>
来源:https://www.cnblogs.com/hanshuai/p/12213356.html