浅谈Vue灰度发布新功能的使用

目录
  • 概述
  • 组件级别
  • 页面级别
    • 方案一 新增入口页面分发
    • 方案二 高阶组件方案
    • 方案三 动态Router.js引入
  • 总结
  • 参考

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

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

从上可以看出,灰度发布的主要作用有以下几点:

  • 降低直接全量发布带来的影响,让少部分用户先使用新版本,如发现问题则及时做好修复,验证无重大问题则全量发布新功能
  • 通过新老版本的数据对比,决定新版本是否需要全量发布

概述

灰度发布的方式有很多,按端可以区分服务端,客户端,Web前端都可以做,没有最好,只有更适合自己的业务场景。

如上可以看到常见的几种灰度发布的方式,都有各自的优缺点,由于我们公司有完善的大数据AB test方案,所以前端只需关注接口返回的字段标识,来做具体的页面加载逻辑,今天重点讲述在前端中使用Vue框架中如何做灰度发布。在Vue中主要可以分为以下两种情况:

组件级别:

  • 组件级别动态控制只需后端回传对应方案标识即可。

页面级别:

  • 前端页面访问地址不变,同后端人员约定好AB test 标记字段,前端根据字段返回不同的内容加载对应的页面。
  • 新旧功能区分两个页面地址,跳转页面地址由后端控制,此方案前端不需要太多改动,此文就不多说明。

先来看看日常处理的方式,一个页面可能会存在多个地方判断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 的元素加一个特殊的 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根据后台数据加载不同的组件:https://www.cnblogs.com/zhea55/p/15115555.html

components-dynamic-async:https://cn.vuejs.org/v2/guide/components-dynamic-async.html

到此这篇关于浅谈Vue灰度发布新功能的使用的文章就介绍到这了,更多相关Vue灰度发布内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解决vue 打包发布去#和页面空白的问题

    1.vue项目中config文件下index.js中打包配置 build: { // Template for index.html index: path.resolve(__dirname, '../yiTownWebApp/index.html'), // Paths assetsRoot: path.resolve(__dirname, '../yiTownWebApp'), assetsSubDirectory: 'static', assetsPublicPath: '/yiTown

  • vue2.0+ 从插件开发到npm发布的示例代码

    vue: V2.5.11 此篇尽量详细,清楚的讲解vue插件的开发到npm的发布,想想将你自己做的东西展示给广大"网民",心里还是有点小激动的...-^_^ 先上一下插件效果图------github传送门 下面我们就来说说详细做法: 1. 初始化项目 vue init webpack-simple vue-pay-keyboard 使用vue创建一个简单的项目,删除src中除了main.js和app.vue外的文件,清空app.vue中无用内容 整理完后项目目录 2.编写插件 vue

  • Vue插件从封装到发布的完整步骤记录

    插件的分类 添加全局的方法或者属性 比如:vue-element 添加全局的资源 比如:指令 v-bind 通过mixin方法添加的一些混合 添加Vue实例方法 Vue.prototype上面 插件的使用 通过全局方法 Vue.use() 使用插件.它需要在你调用 new Vue() 启动应用之前完成: // 调用 `MyPlugin.install(Vue)` Vue.use(MyPlugin) new Vue({ //... options })``` 也可以传入一个选项对象: ``` ja

  • 详细讲解如何创建, 发布自己的 Vue UI 组件库

    前言 在使用 Vue 进行日常开发时, 我们经常会用到一些开源的 UI 库, 如: Element-UI_, _Vuetify 等. 只需一行命令, 即可方便的将这些库引入我们当前的项目: npm install vuetify // or yarn add vuetify 但是当我们自己开发了一个 _UI Component_, 需要在多个项目中使用的时候呢? 我们首先想到的可能是直接复制一份过去对吗? 这样做是很方便, 但是有两个问题: 当该 component 需要更新时, 我们需要手动维

  • 用vue封装插件并发布到npm的方法步骤

    一.基于vue的国家区号列表 vue-flag-list包含了大部分国家的区号,点击右边的三角形展开列表可以选择国家区号,若列表中没有区号,也可以自己输入区号. 全球区号列表 1.1 初始化组件 用的是vue-cli来初始化组件,虽然有很多东西不需要,因为对这个比较熟悉,所以还是按照这个步骤来. vue init webpack vue-flag-list cd vue-flag-list cnpm install npm run dev 1.2 根据自己的需求,实现具体功能,我的主要功能写在v

  • Vue2.0如何发布项目实战

    大家好,这节我们主要讲解项目的发布,其实很简单,没有大家想的那么复杂,具体如下操作. 一.创建VUE项目 首先我们需要创建VUE项目,创建项目的代码如下: # 全局安装 vue-cli $ npm install --global vue-cli # 创建一个基于 webpack 模板的新项目 $ vue init webpack my-project # 安装依赖,走你 $ cd my-project $ npm install $ npm run dev 项目截图如下: 项目截图 二.项目打

  • 关于vue.js发布后路径引用的问题解决

    本文主要给大家介绍了关于vue.js发布后路径引用问题的解决方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 在发布到iis目录下时候,如果放在网站的根目录下的时候,是不会有什么问题的 但是一旦放在了非根目录的其他文件夹里面,这时候index.html里引用的js和css文件路径都会找不到 错误如下 打开index.html文件发现里面引用的文件路径不对 这里只需要更改config/index.js配置就可以了 更改后的配置 这里也视当前环境的具体环境而定. 如果你也遇到这样

  • Vue cli3 库模式搭建组件库并发布到 npm的流程

    市面上目前已有各种各样的UI组件库,比如 Element 和 iView ,他们的强大毋庸置疑.但是我们面临的情况是需求越来越复杂,当它们不能再满足我们需求的时候,这个时候就有必要开发一套属于自己团队的组件库了. 所以本文的目的就是让读者能通过此文,小能做一个简单的插件供人使用,大能架构和维护一个组件库不在话下. 以下一个简单的颜色选择器插件 vColorPicker 讲述从开发到上线到npm的流程. vColorPicker 插件 DEMO 一.技术栈 如何通过新版脚手架创建项目,这里就不提了

  • vue+canvas实现炫酷时钟效果的倒计时插件(已发布到npm的vue2插件,开箱即用)

    前言: 此事例是在vue组件中,使用canvas实现倒计时动画的效果.其实,实现效果的逻辑跟vue没有关系,只要读懂canvas如何实现效果的这部分逻辑就可以了 canvas动画的原理:利用定时器,给定合理的帧数,不断的清除画布,再重绘图形,即呈现出动画效果. 让我们先看下效果 说明:此gif清晰度很低,因为转成gif图的时候,质量受损,帧数减少,所以倒计时转到红色时候看起来变的很模糊.但是实际在浏览器上效果全程都是很清晰和连贯的 使用 npm npm install vue-canvas-co

  • vue.js评论发布信息可插入QQ表情功能

    本文实例为大家分享了vue.js评论发布信息可插入QQ表情,供大家参考,具体内容如下 demo例子: HTML文本内容: <template> <div id="publish"> <!-- 发布内容输入框,利用Html5的新属性contenteditable,实现可编辑文本 ,会自动将插入的IMG标签解析--> <div class="publish_container"> <p contenteditable

随机推荐