首次访问效果如下,点击立即更新会访问灰度版本。本地cookie存在version字段后,后续访问都是指定版本代码,也不会出现弹窗提示
因为一次上线,导致登录异常,用户无法使用。复盘时候,测试反馈预发环境不能完全模拟出生成环境。要不做一个灰度发布,实现代码最小化影响。
多了解点技术方案,总没有坏事
> 前端通过获取版本规则,服务端计算规则
> 命中规则,重新访问页面,nginx 通过版本信息,返回指定版本
> 未命中规则,继续访问当前稳定版本页面
ps: 额外探讨,如果希望服务端接口也能有灰度版本,是不是只需要通过 nginx 配置就能实现?
【顺便吆喝一句,技术大厂跳板,前后端测试捞人,待遇还可以,感兴趣的兄弟一试。】
这个规则是可以自己定制的;这里我简单以 userId 进行匹配
/** * 获取当前用户的版本 * @param {*} ctx */ exports.getVersion = async (ctx) => { try { const version = ctx.cookies.get("version"); const userId = ctx.query.userId; // 这里直接写死,也可以放到redis里,做成可以动态配置也行 const inTestList = ["68075c202bbd354b0fcb7a4c"]; const data = inTestList.includes(userId) ? "gray" : "stable"; if (version) { return ctx.success( { version: data, cache: true, }, "缓存" ); } else { ctx.cookies.set("version", data, { maxAge: 1000 * 60 * 60 * 24 * 7 }); return ctx.success( { version: data, cache: false, }, "重新计算" ); } } catch (error) { ctx.fail("获取页面记录失败"); console.error("获取页面记录失败:", error); } };
- 交互方式,目前我能想到
- 第一种,接口请求完,才开始渲染页面,自动执行指定版本
- 第二种,接口请求、页面渲染同步进行,指定版本由用户触发
// 我把请求版本放到入口首页界面里 // 首次需要登录之后才会执行 onMounted(() => { const userInfo = store.getters["login/getUserInfo"]; getVesion({ userId: userInfo.id }).then((res) => { if (!res.cache && res.version === "gray") { // 这里我增加一个弹窗提示,让用户选择 ElMessageBox.confirm("存在新的灰度版本,是否要体验最新版本?", "新版本", { confirmButtonText: "立即更新", cancelButtonText: "不更新", type: "warning", }).then(() => { window.location.reload(); }); } }); // 页面其他初始化逻辑 });
- 项目里使用的是vite打包工具
- 通过增加两个配置,两者区别在于输入输出不同。当然如果嫌维护两个配置麻烦,可以把公共相同配置抽离出来或者通过环境变量区分维护一个配置
- 新增一个入口 html 文件,并修改打包输出名称
# vite.gray.config.js // 修改打包输出名称方便部署 const renameHtmlPlugin = () => { return { name: 'html-transform', enforce: 'post', generateBundle(options, bundle) { bundle['gray.html'].fileName = 'index.html' } } } export default defineConfig({ // ... 其他配置 plugins: [vue(), renameHtmlPlugin()], build: { outDir: 'gray', rollupOptions: { input: { main: resolve(__dirname, 'gray.html') } } } // ... })
"build": "vite build", "build:gray": "vite build --config vite.gray.config.js",
// 灰度版本 -gray - assests - index.html - // 稳定版本 dist - assests - index.html;
这里我尝试很久,最终以下配置可以实现
通过 cookie 中版本标识,返回不同版本内容
http { map $http_cookie $target_dir { # 精确匹配version值,避免捕获额外内容 "~*version=gray(;|$)" "/gray"; "~*version=stable(;|$)" "/stable"; default "/stable"; } server { ...已存在... location / { root html$target_dir; try_files $uri $uri/ /index.html; } ...已存在... } }
自此一个简单前端灰度效果就实现了。当然这里还有许多的场景没有考虑到,欢迎大家提问探讨。
案例代码:gitee.com/banmaxiaoba… 代码包含一个简易的前端监控方案实现,有空下篇文章分享讨论