前端SPA应用发版后用户白屏的解决方案
接手了一个前端老项目,使用React开发的SPA,最近几次短周期发版之后,收到了用户大量的体验反馈,其中比较多的就是白屏。
问题回放
问题出现集中出现在发版之后的短时间内,从用户反馈来看,页面大约长这样:
在这个页面里无论等待多久就是加载不出来。
问题原因
找这个问题还是花了一点时间来复现,后面专门找了一次发版的契机,才把这个问题抓到。查看控制台,大约报错如下:
xxxxxx.js 404
问题比较明显,就是这个页面的js从服务器取不到了。为什么会有这个问题?这与我们发版机制有关,目前的前端发版是直接把前端工程打包成一个dist
文件夹,然后把它打到docker的镜像里,最后直接将这个docker镜像部署。
有没有什么问题?这种部署方式直接替换掉原来的镜像,而现代化的前端工程打包出来的js文件名一般会带一个hash值,所以导致如果用户缓存了老版本的js文件请求的话,直接替换就会出现这种404的白屏问题。
可为什么会缓存js文件?我们再看看我们的Dockfile
,如下:
FROM xxxxx.xxxxx.xxx/nginx:latest
ADD ./dist /usr/share/nginx/html
注意:数据脱敏隐藏了内部的docker地址。
但我们可以发现这里使用的比较粗暴,直接用的Nginx的默认配置,我们在本地启动一个Nginx的docker测试一下,发现默认情况下,Nginx会缓存html文件。
解决方案
明白了问题,解决方案也比较简单了,有两种可行方案。
- 让用户刷新一下(不要笑,B端的系统有的真就是可以这样,但我觉得不好)
- 改一下Nginx,默认不缓存HTML文件
我采用的方案二,添加了一个自定义的nginx.conf
配置文件,替换掉原来的默认配置,这样就不会缓存html文件了。
nginx.conf
文件内容如下
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
if ($request_filename ~* ^.*?.(html|htm)$) {
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
再修改下Dockfile
, 用这个新的配置替换掉默认配置。
FROM xxxx.xxxxxxxx/nginx:latest
#上面修改成你的docker镜像地址
ADD ./dist /usr/share/nginx/html
ADD ./conf/nginx.conf /etc/nginx/conf.d/default.conf
真的解决了吗?
考虑一种极端情况,如果用户一直开着页面不关呢?这个时候,当前的解决方案就无法满足要求了。
那这种情况有没有方案呢?
我能想到的几种方法:
- 前端工程部署到CDN
- 定时刷新(比如1个小时)
- 打包的时候可以集成上一个版本
更多的方案暂时也没想到,有更好解决方案的小伙伴欢迎交流。