前段时间在工作中会设计到项目上线方案,也踩了一些坑,写个博客记下来她们。
前提
项目是 SPA 单页面应用( Vue 项目),首次会加载 manifest ,这个文件会记录当前项目中所需要的 JS 的版本映射,由于是 SPA ,在点击其他页面时只会加载对应版本的 JS
静态文件和 HTML 文件在同一域名中,HTML 页面使用预渲染 prerender-spa-plugin 完成,比如:/ - HTML 文件,真实文件为 /index.html
/login/ - HTML 文件,真实文件为 /login/index.html
/static/js/*.js - JS 文件
/static/img/*.png -图片文件
...
第一代上线方案 - ln 软链接
本身运维线上部署使用的软链接,大概的脚本如:
#!/bin/bash
# 基础路径
base="/usr/webapp"
# 项目名
repo="www.demo.com"
# 前端项目产出 dist 包
dist_tar="${base}/tar/${repo}.tar.gz"
# 网站根目录
wwwroot="${base}/wwwroot/${repo}"
# 网站源文件
wwwsource="${base}/wwwsource/${repo}/$(date '+%Y-%m-%d@%s')"
# 创建目录
mkdir -p "$wwwsource/tar" "$wwwsource/data"
# 解压
tar xzvf $dist_tar -C "$wwwsource/data"
# 保留一份数据
cp -r $dist_tar "$wwwsource/tar"
# 创建根目录软链接到解压的数据目录
mkdir -p `dirname $wwwroot`
ln -F -s "$wwwsource/data" "$wwwroot"
注意:脚本只是一个栗子,认真你就输了。
遵循:
/usr/webapp/tar/${项目名}.tar.gz - 最新前端编译产出的文件包,就是 dist/ 目录下的文件
/usr/webapp/wwwroot/${项目名} - 项目的根目录,但不是真实文件,是通过软链接创建的
/usr/webapp/wwwsource/${项目名}/${年-月-日}@${时间缀} - 项目的真实源文件./data - 项目数据源文件
./tar - 项目的文件包
由于使用软链接,回滚非常的高效(只需要重新创建指定我要上班的软链接就可以),但由于 SPA 单页面应用发现每次上线后会出现大量的 404 状态,由于是各种查,没想到最终的原因竟然是:
SPA 在首次加载时会记录当前版本的文件名映射,在用户打开网站后如果用户没有刷新,在这个期间项目上线了,用户再点击首次访问新的页面时,加载对应的静态文件会是 404 ,因为新的版本对应新的文件(在有变更的前提下)。
第二代上线方案 - 增量
增量顾名思义是每次上线时在线上都是新增、覆盖,而不会删除老文件,大概脚本如:
#!/bin/bash
# 基础路径
base="/usr/webapp"
# 项目名
repo="www.demo.com"
# 前端项目产出 dist 包
dist_tar="${base}/tar/${repo}.tar.gz"
# 网站根目录
wwwroot="${base}/wwwroot/${repo}"
# 网站备份
wwwback="${base}/wwwback/${repo}"
# 解压,增量
tar xzvf $dist_tar -C $wwwroot
# 保留一份数据
mkdir -p $wwwback
cp -r $dist_tar "${repo}`date '+%Y-%m-%d@%s'`.tar.gz"
注意:脚本只是一个栗子,认真你就输了。
遵循:
线上代码不删除
/usr/webapp/tar/${项目名}.tar.gz - 最新前端编译产出的文件包,就是 dist/ 目录下的文件
/usr/webapp/wwwroot/${项目名} - 项目根目录
/usr/webapp/wwwback/${项目名}/${项目名}@${年-月-日}@${时间缀} - 备份文件
解决了线上 404 静态的问题,但发现:
@PM:上线个xx活动页吧。
@FE:收到!
@PM:我擦,活动页临时不做了,赶快把活动页给删除吧,快点上线。
@FE:emmmm...
由于我复制了个 404.html 覆盖了活动页,这TM叫什么鬼啊。。。
第三代上线方案 - 按需增量
结合上面的教训:静态文件 404 + HTML 文件删不掉的问题,我们约定个规则:
前端打包会把静态文件和 HTML 文件区分,如:dist/html/ - HTML 产出文件
dist/static/ - 静态文件产出文件
制定新规则:HTML 软链接上线
静态文件增量上线
脚本如:
#!/bin/bash
# 基础路径
base="/usr/webapp"
# 项目名
repo="www.demo.com"
# 前端项目产出 dist 包
dist_tar="${base}/tar/${repo}.tar.gz"
# 网站目录,里面会有 html 和 static
wwwroot="${base}/wwwroot/${repo}"
# 网站源文件
wwwsource="${base}/wwwsource/${repo}/$(date '+%Y-%m-%d@%s')"
# 创建目录
mkdir -p "$wwwsource/tar" "$wwwsource/data"
# 解压
tar xzvf $dist_tar -C "$wwwsource/data"
# 保留一份数据
cp -r $dist_tar "$wwwsource/tar"
# 创建根目录
mkdir -p $wwwroot
# 增量上线静态文件
cp -r "$wwwsource/data/static/*" "$wwwroot/static/"
# 软链接 HTML 文件
ln -F -s "$wwwsource/data/html" "$wwwroot/html"
注意:脚本只是一个栗子,认真你就输了。
遵循:
/usr/webapp/tar/${项目名}.tar.gz - 最新前端编译产出的文件包,就是 dist/ 目录下的文件
/usr/webapp/wwwroot/${项目名} - 项目的目录./html/ - HTML 根目录,软链接到 /usr/webapp/wwwsource/${项目名}/${年-月-日}@${时间缀}/data/html
./static/ - 静态文件根目录
/usr/webapp/wwwsource/${项目名}/${年-月-日}@${时间缀} - 项目的真实源文件./data - 项目解析的文件
./tar - 项目的文件包
回滚的时候只需要回滚 HTML 文件即可,对了,还需要修改 Nginx 配置目录,如:
server {
root /usr/webapp/wwwroot/${项目名}/html/;
location /static/ {
alias `/usr/webapp/wwwroot/${项目名}/static/;
}
}
这就一定解决问题了?其实并不是。。。因为打开 SPA ,只要不刷新,其实你后面删除的 HTML 文件就会存在的。。。正所谓成也 SPA 败也 SPA 。。。
那么如何处理:我们正在尝试使用定时请求线上版本号,如果发现有更新则说明有上线,那么在路由里就切换为 location.href 跳转。当然这个方案我们还在尝试中,期待新一代的上线方案诞生。
CDN 缓存策略
前端项目往往离不开 CDN ,我们这样配置的:
规则
缓存时间
说明
HTML 文件
不缓存
由于需要上线即生效,HTML 又是所有功能的入口,所以不缓存
其实可以缓存1分钟的,更合理的利用 CDN ,具体需要和需求方沟通
静态文件
最大缓存
静态文件有 Content Hash 做为文件名
API 接口
不缓存
-
非 2xx 的响应
不缓存
被坑过,一个静态文件 404 被 CDN 缓存,怎么都不生效。。。
如果你有好的策略或者上线方案,请联系我。。。