最快实现的前端灰度方案

小白最快学会的前端灰度方案

首次访问效果如下,点击立即更新会访问灰度版本。本地cookie存在version字段后,后续访问都是指定版本代码,也不会出现弹窗提示

一、引言:为什么需要灰度发布?

1.1 血泪教训:全量发布的风险

因为一次上线,导致登录异常,用户无法使用。复盘时候,测试反馈预发环境不能完全模拟出生成环境。要不做一个灰度发布,实现代码最小化影响。

1.2 技术思考:面试的需要

多了解点技术方案,总没有坏事

二、前端灰度方案

  • 在网上搜索前端灰度方案,整体看来就目前这个比较简单,上手快,易实现
  • nginx + 服务端 + 前端 js(可以考虑封装成一个通用工具 js)
大致思路
复制代码
> 前端通过获取版本规则,服务端计算规则
> 命中规则,重新访问页面,nginx 通过版本信息,返回指定版本
> 未命中规则,继续访问当前稳定版本页面

ps: 额外探讨,如果希望服务端接口也能有灰度版本,是不是只需要通过 nginx 配置就能实现?

【顺便吆喝一句,技术大厂跳板,前后端测试捞人,待遇还可以,感兴趣的兄弟一试。】

三、实现细节

1. 版本规则接口

这个规则是可以自己定制的;这里我简单以 userId 进行匹配

  • 案例服务端框架:koa2 + mongoose

    /**

    • 获取当前用户的版本

    • @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);
      }
      };

  • userId 匹配那块,可以引入 redis 做缓存处理,避免直接查询用户表进行比对

2. 前端触发获取版本
  1. 交互方式,目前我能想到
  2. 第一种,接口请求完,才开始渲染页面,自动执行指定版本
  3. 第二种,接口请求、页面渲染同步进行,指定版本由用户触发
复制代码
// 我把请求版本放到入口首页界面里
// 首次需要登录之后才会执行
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();
      });
    }
  });
  // 页面其他初始化逻辑
});
前端打包控制
  1. 项目里使用的是 vite 打包工具
  2. 通过增加两个配置,两者区别在于输入输出不同。当然如果嫌维护两个配置麻烦,可以把公共相同配置抽离出来或者通过环境变量区分维护一个配置
  3. 新增一个入口 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;

3. nginx 配置

这里我尝试很久,最终以下配置可以实现

通过 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...

------转载自:东坡白菜

相关推荐
java1234_小锋5 小时前
【技术专题】HTML5 网页技术 - HTML5 Canvas 基础以及动画入门
前端·html·html5
知了学历孙老师8 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
ShineWinsu10 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说11 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
程序员老赵13 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot13 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot13 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
狒狒AI13 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc
修炼的dance13 小时前
浏览器里导出H.265,8.5秒和55.5秒差在硬件
前端
补码缩写13 小时前
WebCodecs选编码器,探测之后还要验解码和播放
前端