前言

什么是灰度公布?百度百科的解释如下。

灰度公布是指在黑与白之间,可能平滑过渡的一种公布形式。AB test就是一种灰度公布形式,让一部分用户持续用A,一部分用户开始用B,如果用户对B没有什么拥护意见,那么逐渐扩大范围,把所有用户都迁徙到B下面来。灰度公布能够保障整体零碎的稳固,在初始灰度的时候就能够发现、调整问题,以保障其影响度。

从上能够看出,灰度公布的次要作用有以下几点:

  1. 升高间接全量公布带来的影响,让少部分用户先应用新版本,如发现问题则及时做好修复,验证无重大问题则全量公布新性能
  2. 通过新老版本的数据比照,决定新版本是否须要全量公布

概述

灰度公布的形式有很多,按端能够辨别服务端,客户端,Web前端都能够做,没有最好,只有更适宜本人的业务场景。

如上能够看到常见的几种灰度公布的形式,都有各自的优缺点,因为咱们公司有欠缺的大数据AB test计划,所以前端只需关注接口返回的字段标识,来做具体的页面加载逻辑,明天重点讲述在前端中应用Vue框架中如何做灰度公布。在Vue中次要能够分为以下两种状况:

组件级别:

  1. 组件级别动态控制只需后端回传对应计划标识即可。

页面级别:

  1. 前端页面拜访地址不变,同后端人员约定好AB test 标记字段,前端依据字段返回不同的内容加载对应的页面。
  2. 新旧性能辨别两个页面地址,跳转页面地址由后端管制,此计划前端不须要太多改变,此文就不多阐明。

先来看看日常解决的形式,一个页面可能会存在多个中央判断AB test 逻辑,或者是更多的AB test同时进行,这样的页面代码逻辑复杂度绝对比拟高,也不够整洁易懂,当有新的AB test退出或者有AB test须要决策的时候,批改代码的老本较高,升高了代码保护的效率。

<template>    ...    <test-a v-if="testA" />    <test-b v-else-if="testB" />    ...    <div v-if="testA">        ...    </div>    <div v-else-if="testB">        ...    </div>    ...</template><script>    ...    if (testA) {        ...    } else if (testB) {        ...    }</script>

接下来就开始咱们明天文章的正题,看看有哪些形式能够解决以上的问题。

组件级别

如只是简略的两个小组件性能的灰度则能够间接用 v-if 解决

<testA v-if="testA" /><testB v-else />

如有多个性能同时测试,能够通过 Vue 的<component>元素加一个非凡的 isattribute 来实现,currentTabComponent 可基于接口获取或其余前端计算得出。

<component :is="currentTabComponent"></component>

页面级别

计划一 新增入口页面散发

新增入口页面,将新旧版本页面降级为组件的形式引入,入口页面减少接口查问,通过 v-if 或通过 Vue 的<component> 元素加一个非凡的 is 属性来加载页面组件。如下是通过接口查问代码示例,通过接口前置查问会带来肯定的界面提早加载,取决于接口的响应速度,咱们也能够通过在URL减少参数获取,这时的URL由后端拼接好参数再返回,这样就能够防止一次接口查问。

<template>   <component :is="testId"></component></template><script>  import IndexA from './index-a'  import IndexB from './index-b'  import {    getTestID  } from '@/api/getTestID'  export default {    name: 'index',    components: {      'index-a': IndexA,      'index-b': IndexB    },    data() {      return {        testId: ''      }    },    created() {      this.getTestID()    },    methods: {      async getTestID() {        const { testId } = await getTestID({          xxx: xxx        })        this.testId = testId      }    }  }</script>

这里间接这样加载页面级组件会导致此文件体积加大,能够将页面组件的加载形式改为异步组件,晋升页面加载速度。

components: {    'index-a': () => import(/* webpackChunkName: "index-a" */ './index-a'),    'index-b': () => import(/* webpackChunkName: "index-b" */ './index-b')}

计划二 高阶组件计划

在路由配置中从接口获取灰度标识数据,进行路由散发。如果不想额定减少接口查问的开销,也能够将标识数据从URL参数返回,此形式须要提前拼接好参数。

高阶组件的益处是所有须要灰度的加载逻辑都在路由配置文件中,对立保护,组件也可复用,不须要每个须要灰度的页面都减少一个入口文件。

组件代码

<template>  <component :is="com" /></template><script>export default {  name: 'DynamicLoadComponent',  props: {    renderComponent: {      type: Promise    }  },  data() {    return {      com: () => this.renderComponent    }  }};</script>

router.js 配置

{  path: 'originPath',  component: () => import('@/views/components/DynamicLoadComponent'),  name: 'originPath',  props: (route) => ({    renderComponent: new Promise((resolve, reject) => {      // 依据 route 拼接参数获取加载页面      if (route.query.testA) {          resolve(import('@/views/testA'));      } else {          resolve(import('@/views/testB'));      }      // OR 依据接口返回标识动静加载页面      getAPIData()        .then((response) => {          if (response.testA) {            resolve(import('@/views/testA'));          } else {            resolve(import('@/views/testB'));          }        })        .catch(reject);    }),  })}

计划三 动静Router.js引入

如果是有大面积的页面替换,可采纳这种形式。例如,后端开发语言更换导致接口地址及返回的字段内容都发生变化,这样会有一段时间的过渡应用,开发完一个页面上线一个页面,就可能会有5个页面应用新的计划,5个页面还是保留原始计划的状况。

革新router.js,将原始路由配置抽离到default.js中,再新建java.js将新计划路由配置写入,基于前端计算或接口返回标识动静加载路由配置文件。

import Vue from 'vue'import Router from 'vue-router'import { isHitJavaAPI } from '@/config'Vue.use(Router)const router = new Router({  mode: 'history'})const computedRouterDirectory = (routeFile) => {   let routerConfig;   const requireRouter = require.context('.', false, /\.js$/);   routerConfig = requireRouter.keys().filter(file => file === `./${routeFile}.js`)[0];   if (routerConfig) {     routerConfig = requireRouter(routerConfig)     routerConfig.default && router.addRoutes(routerConfig.default);  }}if (isHitJavaAPI()) {   computedRouterDirectory('java') } else {   computedRouterDirectory('default')}

isHitJavaAPI办法中是命中灰度的逻辑,如果这里是前端做灰度,可基于deviceID或UA等计算。如果这里是调用接口获取计划则需改为同步调用。

总结

本文次要介绍了页面级别的几个灰度计划,每个计划的试用场景都有各自的优缺点,如新增入口文件,次要是针对页面变动较大且以后我的项目只会有一个在进行中的灰度测试;高阶组件实用于以后我的项目有多个进行中的灰度测试,则可复用组件;动静加载路由配置文件次要针对于以后我的项目有大规模的页面UI或逻辑更换灰度测试;通过以上几种计划都可极大的晋升代码的可维护性以及解耦灰度逻辑和业务代码逻辑,当灰度测试没有问题需全量上线时,咱们只需批改入口逻辑即可,无需在业务代码中去一一批改灰度逻辑。

除开本文所介绍的几种形式,也还有其余的加载形式,如路由钩子函数拦挡后做动静跳转,或者申请到后端,后端做重定向解决等。每个形式都有各自的优缺点,就看是不是你以后场景最合适的计划。如果你有其余的计划,欢送留言和咱们交换~

参考

Vue Router依据后盾数据加载不同的组件
components-dynamic-async