01月13, 2019

记一次 Vue 单页面上线方案的优化

前段时间在工作中会设计到项目上线方案,也踩了一些坑,写个博客记下来她们。

前提

  • 项目是 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 缓存,怎么都不生效。。。

如果你有好的策略或者上线方案,请联系我。。。

本文链接:https://xuexb.com/post/vue-online-cdn.html

-- EOF --

发表于 2019年01月13日 12:50:08 ,添加在分类 前端技术 下 ,并被添加「 cdn 」标签 ,最后修改于 2019年01月18日 07:52:23

提醒: 本文最后更新于 2547 天前,文中所描述的信息可能已发生改变,请谨慎使用。

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。

AltStyle によって変換されたページ (->オリジナル) /