vue项目打包后,在非首次线上更新项目时,某些老用户浏览器/微信浏览器在项目更新后首次打开页面,由于用户缓存了之前的文件,导致出现白屏情况。多次刷新或者退出微信可以解决,但是不可能知道和联系到每一个存在缓存的用户去刷新或者退出微信。
原因分析
在使用vue-cli脚手架构建完项目,项目完成后,需打包上线。默认打包方式则是npm build
,项目根目录会生成 dist 文件夹。服务端将该文件夹替换线上即可。但是当第n(n>1)次上线后,由于在用户端会默认缓存index.html入口文件,而由于vue打包生成的css/js都是哈希值,跟上次的文件名都不同,因此会出现找不到css/js的情况,导致白屏的产生。
经常使用vue作为开发框架的开发者都知道,build打包后,所生成的css/js的文件名中间会夹杂哈希值,以此来避免缓存问题。但是由于入口文件index.html的名字每次打包后不改变,并且也不能乱变,就导致了index.html在用户端仍然会被缓存下来。那么在服务端更新包之后,由于旧的文件被删除,而index.html所链接的路径依然是旧文件路径,因此会找不到文件,从而白屏。解决方案一般是强制刷新页面或者清除缓存重新加载。当然,网上也给出不少的“缓解方案”。为什么称之为缓解方案而不是解决方案呢?因为前端缓存问题是一个具有行业性的难题,在没有根治之前,只能尽全力优化。使用以下优化步骤后未听到用户再反馈白屏问题。
方案1、 meta标签
<!-- 在入口文件index.html中,头部添加meta标签 -->
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">
方案2、时间戳区分
//vue.config.js
configureWebpack: config => {
const timeStamp = new Date().getTime();
if (process.env.NODE_ENV === 'production') {
config.output.filename = `[name].${process.env.VUE_APP_VERSION}.${timeStamp}.js`;
config.output.chunkFilename = `[name].${process.env.VUE_APP_VERSION}.${timeStamp}.js`;
}
},
方案3、服务端配置
// nginx端配置
location / {
root /www/dm;
index index.html index.htm;
try_files $uri $uri/ /index.html;
add_header Cache-Control no-store; //添加header cache no store配置
}
相对来说这3个方案前端都可以自行解决,比较简单。在微信浏览器里,我们现有的项目综合使用这几步后基本解决了这个问题,如果是在某些特定情况下(如混合开发App,原生嵌入webview还在h5),可在原生端的加载模式方面尝试解决:
加载webview前清除缓存再加载;
销毁webview前清除缓存;