日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁(yè) > 科技  > 軟件

我們一起聊聊審核平臺(tái)前端新老倉(cāng)庫(kù)遷移

來(lái)源: 責(zé)編: 時(shí)間:2024-07-06 07:42:38 896觀看
導(dǎo)讀背景審核平臺(tái)接入50+業(yè)務(wù),提供在線審核及離線質(zhì)檢、新人培訓(xùn)等核心能力,同時(shí)提供數(shù)據(jù)報(bào)表、資源追蹤、知識(shí)庫(kù)等工具。隨著平臺(tái)的飛速發(fā)展,越來(lái)越多的新業(yè)務(wù)正在或即將接入審核平臺(tái),日均頁(yè)面瀏覽量為百萬(wàn)級(jí)別。如今審核平

背景

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

審核平臺(tái)接入50+業(yè)務(wù),提供在線審核及離線質(zhì)檢、新人培訓(xùn)等核心能力,同時(shí)提供數(shù)據(jù)報(bào)表、資源追蹤、知識(shí)庫(kù)等工具。隨著平臺(tái)的飛速發(fā)展,越來(lái)越多的新業(yè)務(wù)正在或即將接入審核平臺(tái),日均頁(yè)面瀏覽量為百萬(wàn)級(jí)別。如今審核平臺(tái)已是公司內(nèi)容生產(chǎn)鏈路上的關(guān)鍵一環(huán),是保障內(nèi)容安全的重要防線,因此穩(wěn)定性至關(guān)重要。kZ828資訊網(wǎng)——每日最新資訊28at.com

過(guò)去一年我們?cè)鴮?duì)前端項(xiàng)目進(jìn)行框架升級(jí),考慮風(fēng)險(xiǎn)與成本最小化,選擇了漸進(jìn)式升級(jí),利用微前端實(shí)現(xiàn)Vue2和Vue3共存,新接業(yè)務(wù)在Vue3倉(cāng)庫(kù)中開(kāi)發(fā)。經(jīng)過(guò)一年的迭代,Vue3項(xiàng)目趨于穩(wěn)定,沉淀了大部分通用能力。為了降低多倉(cāng)庫(kù)維護(hù)心智,同時(shí)解決核心模塊的技術(shù)債務(wù),考慮將剩余活躍代碼進(jìn)行重構(gòu)并遷移至新倉(cāng)庫(kù)。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

面向遷移的重構(gòu) - 整潔架構(gòu)在前端的應(yīng)用

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

案例選擇

kZ828資訊網(wǎng)——每日最新資訊28at.com

參考前端埋點(diǎn)報(bào)表,選擇老倉(cāng)庫(kù)中頁(yè)面維度訪問(wèn)量最高的路由,對(duì)線上使用情況進(jìn)行摸排。日常業(yè)務(wù)現(xiàn)狀是點(diǎn)直融合,直播業(yè)務(wù)配置化接入需求較多,因?yàn)闃I(yè)務(wù)形態(tài)的差異,定制需求多,現(xiàn)有配置能力無(wú)法滿足,需擴(kuò)充。開(kāi)發(fā)現(xiàn)狀是通用配置化代碼改動(dòng)頻繁,邏輯復(fù)雜,開(kāi)發(fā)門(mén)檻較高,影響范圍大,牽一發(fā)而動(dòng)全身。因此選擇配置化詳情頁(yè)作為優(yōu)先重構(gòu)并遷移的對(duì)象。kZ828資訊網(wǎng)——每日最新資訊28at.com

配置化詳情頁(yè)采用的是業(yè)務(wù)定制化的低代碼方案,包含schema渲染器和任務(wù)流兩部分。當(dāng)前已沉淀近百份json schema,托管在內(nèi)部其他低代碼平臺(tái)上。頁(yè)面覆蓋40多個(gè)業(yè)務(wù),占據(jù)平臺(tái)約20%訪問(wèn)量和35%獨(dú)立訪客。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

如果將頁(yè)面看做一個(gè)黑盒子,依據(jù)唯一標(biāo)識(shí)(路由path和query等)從node服務(wù)、平臺(tái)服務(wù)以及外部業(yè)務(wù)方服務(wù)獲取數(shù)據(jù),基于頁(yè)面內(nèi)部規(guī)則渲染頁(yè)面。審核員瀏覽并進(jìn)行通過(guò)、駁回等操作,提交后將對(duì)視頻、彈幕等業(yè)務(wù)資源產(chǎn)生影響。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

schema渲染器基于json schema和接口數(shù)據(jù),在平臺(tái)內(nèi)生成路由信息與頁(yè)面內(nèi)容,負(fù)責(zé)各種模式的頁(yè)面分發(fā)、物料分發(fā),并提供敏感詞、快照、洗數(shù)等通用平臺(tái)能力。kZ828資訊網(wǎng)——每日最新資訊28at.com

代碼現(xiàn)狀是數(shù)據(jù)獲取、提交操作和頁(yè)面復(fù)雜邏輯分散在vue文件和store中,業(yè)務(wù)邏輯和UI框架耦合嚴(yán)重,不利于集成自動(dòng)化測(cè)試和框架升級(jí)。待辦、任務(wù)、資源等邊界劃分不清晰,平鋪在“巨石store“中,維護(hù)成本極高且代碼改動(dòng)風(fēng)險(xiǎn)大。渲染器和任務(wù)流邏輯不夠內(nèi)聚,耦合嚴(yán)重,無(wú)法做到關(guān)注點(diǎn)分離。因此需要尋找一種合適的架構(gòu)進(jìn)行重構(gòu),減弱業(yè)務(wù)邏輯對(duì)UI框架的依賴,增強(qiáng)可測(cè)試性。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

整潔架構(gòu)

kZ828資訊網(wǎng)——每日最新資訊28at.com

整潔架構(gòu)由Robert C. Martin在2012年提出,核心思想是將軟件系統(tǒng)拆分為獨(dú)立的層次,以實(shí)現(xiàn)高內(nèi)聚、低耦合、可測(cè)試和可維護(hù)。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

一共分為四個(gè)層級(jí),環(huán)與環(huán)之間,存在一個(gè)依賴關(guān)系原則:源代碼中的依賴關(guān)系,必須只指向同心圓的內(nèi)層,即由低層機(jī)制指向高級(jí)策略。kZ828資訊網(wǎng)——每日最新資訊28at.com

  • 實(shí)體層:包含業(yè)務(wù)領(lǐng)域的核心概念和業(yè)務(wù)邏輯。
  • 用例層:實(shí)現(xiàn)特定的業(yè)務(wù)用例,將實(shí)體層的業(yè)務(wù)邏輯與具體的應(yīng)用場(chǎng)景結(jié)合起來(lái)。
  • 接口適配器層:負(fù)責(zé)處理與外部系統(tǒng)的交互比如用戶界面、數(shù)據(jù)庫(kù)、web服務(wù)等。將外部系統(tǒng)的請(qǐng)求和數(shù)據(jù)格式轉(zhuǎn)化為用例層和實(shí)體層能夠理解和處理的對(duì)象。
  • 框架和驅(qū)動(dòng)層:包含具體的框架和工具,比如web框架、數(shù)據(jù)庫(kù)驅(qū)動(dòng)等。

優(yōu)點(diǎn)是可以在沒(méi)有UI、數(shù)據(jù)庫(kù)、web服務(wù)器或其他外部基礎(chǔ)設(shè)施的情況下測(cè)試業(yè)務(wù)邏輯;降低對(duì)UI框架的依賴,比如跨端開(kāi)發(fā)時(shí),業(yè)務(wù)邏輯可以復(fù)用,只需要做UI層的適配。相應(yīng)的,缺點(diǎn)也很明顯,過(guò)于復(fù)雜,數(shù)據(jù)需要經(jīng)過(guò)多層處理。學(xué)習(xí)成本較高,容易過(guò)度設(shè)計(jì),增加復(fù)雜性,靈活性較低。適用于大型復(fù)雜項(xiàng)目,對(duì)于需要長(zhǎng)期維護(hù)和持續(xù)開(kāi)發(fā)的項(xiàng)目,清晰層次結(jié)構(gòu)和明確依賴關(guān)系有助于減少代碼腐化,更容易適應(yīng)需求變化。針對(duì)我們選擇的模塊,審核前端配置化頁(yè)面,比較適合。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

重構(gòu)

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

實(shí)體層

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

主要可拆分成待辦、任務(wù)、資源等實(shí)體。待辦實(shí)體,主要提供待辦的基礎(chǔ)信息、獲取配置等屬性和方法。任務(wù)實(shí)體提供任務(wù)的狀態(tài)、任務(wù)耗時(shí)、調(diào)度配置、任務(wù)數(shù)據(jù),計(jì)時(shí)和拉取任務(wù)流程等。資源實(shí)體提供資源的詳情數(shù)據(jù)、獲取詳情及數(shù)據(jù)清洗方法等。待辦實(shí)體包含了配置詳情頁(yè)所需的核心數(shù)據(jù),任務(wù)實(shí)體高度抽象了核心任務(wù)流。在新業(yè)務(wù)接入過(guò)程中,實(shí)體層一般不變動(dòng),通過(guò)依賴倒置劃分架構(gòu)邊界。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

// entities/todo.jsexport default class Todo {    todoId    businessId    todoConfig    ...    constructor() {}    async getTodoConfig() {        // 獲取配置    }}// entities/task.jsexport default class Task {  dispatch_conf  listData  timeCount  ...  constructor() {}  async getTaskDetail({ getTask, taskFormat, afterGetTask}) {    // 抽象封裝核心任務(wù)流程  }  // 計(jì)時(shí)邏輯  startTimer() {}  clearTimers() {}}// entities/resource.jsexport default class Resource {    detail    dataReady    constructor() {}    async getResourceDetail({ getResource, resourceFormat, afterGetResource }) {        // 抽象封裝資源模式核心流程    }}

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

用例層

kZ828資訊網(wǎng)——每日最新資訊28at.com

用例層針對(duì)洗數(shù)、提交等復(fù)雜場(chǎng)景,通過(guò)調(diào)用實(shí)體層來(lái)實(shí)現(xiàn)特定的業(yè)務(wù)邏輯,是適配器層與實(shí)體層的中介。例如封裝了基于配置的洗數(shù)中間件,列表模式的單個(gè)和批量提交,卡片模式的單個(gè)和批量提交,快照上報(bào)、自動(dòng)化質(zhì)檢的復(fù)雜邏輯。用例層包含了系統(tǒng)的復(fù)雜業(yè)務(wù)邏輯,為單元測(cè)試提供了便利,可以獨(dú)立于UI和外部系統(tǒng)進(jìn)行測(cè)試。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

// usecase/use-single-submitimport { get } from 'lodash-es' // 三方工具庫(kù)import { ANNOTATION_SINGLE_OPER_PASS_NAME } from '@/constants' // 常量import { workbenchApi } from '@/api'import { setLogData } from '@/utils/xx' // 工具函數(shù)export function getSingleSubmitParams({ data, state.xxx }) {  //... 邏輯處理  return params}export function submitAuditSingle({ data, afterTaskSubmit }) {  const params = ...  workbenchApi.submit(params).then((res) => {    if(res.code = xxx){      afterTaskSubmit() // 調(diào)用鉤子函數(shù)    }  })}

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

適配器層

kZ828資訊網(wǎng)——每日最新資訊28at.com

適配器層包含store和UI,調(diào)用用例層的代碼,主要負(fù)責(zé)將依賴UI、外部服務(wù)、設(shè)備等的數(shù)據(jù)處理為用例層可以使用的“干凈數(shù)據(jù)”。適配器層一般不包括復(fù)雜的業(yè)務(wù)邏輯,因此在框架遷移時(shí)僅需關(guān)注基本的框架差異,適合自動(dòng)化代碼轉(zhuǎn)換。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

// store/todoConfigDetailimport { getTodoInfo } from '@/struct/TodoConfigDetailStruct/usecase/use-todo'import { getTaskInfo, getTask, taskDispatchListFormat } from '@/struct/TodoConfigDetailStruct/usecase/use-task'import { getSingleSubmitParams, submitAuditSingle } from '@/struct/TodoConfigDetailStruct/usecase/use-single-submit'const todo = ref({})async function init({ $route }) {  const query = $route.query  const todoId = +query.todo_id  ...  set(todo, getTodoInfo({ todoId, ... }))  await get(todo).getTodoConfig()  ...}function getTaskDetail() {  get(task).getTaskDetail({    getTask: async ({ noSeize, drillTaskIds }) => await getTask({ todo: get(todo), noSeize, drillTaskIds }),    taskFormat: async (data) => await taskDispatchListFormat({ data, schema: get(todo).schema })    afterGetTask: (res) => { ... }  })}async function submit(data) {  if (single) {    const params = getSingleSubmitParams({ data, todo: get(todo) })    submitAuditSingle({ params, afterTaskSubmit: () => { ... } })  } else {    ...  }}
// Audit.vueconst todoConfigDetailStore = useTodoConfigDetailStore()const { todo, task, multipleSelection } = storeToRefs(todoConfigDetailStore)const { getTaskDetail, submit } = todoConfigDetailStore

kZ828資訊網(wǎng)——每日最新資訊28at.com

新業(yè)務(wù)接入一般對(duì)實(shí)體層和用例層無(wú)改動(dòng),僅需適配器層增加相應(yīng)的展示物料,盡可能避免“牽一發(fā)動(dòng)全身”。新架構(gòu)會(huì)有一定的初學(xué)成本,但結(jié)合審核平臺(tái)復(fù)雜的項(xiàng)目現(xiàn)狀和持續(xù)接入新業(yè)務(wù)的節(jié)奏,長(zhǎng)遠(yuǎn)來(lái)看對(duì)于系統(tǒng)穩(wěn)定性、可測(cè)試性有一定幫助,同時(shí)降低UI框架依賴性。kZ828資訊網(wǎng)——每日最新資訊28at.com

基于新的架構(gòu),可分層進(jìn)行自動(dòng)化測(cè)試和自動(dòng)代碼轉(zhuǎn)換。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

完善用例層的單元測(cè)試

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

用例層為純函數(shù),不依賴框架、設(shè)備、三方服務(wù)等。單元測(cè)試的技術(shù)棧為jest和vue-test-utils,從審核員的基本工作模式入手,針對(duì)任務(wù)領(lǐng)取、數(shù)據(jù)清洗與展示、稿件處理三個(gè)環(huán)節(jié)完善測(cè)試用例。因?yàn)槭切吕蟼}(cāng)庫(kù)遷移,所以可以將線上環(huán)境視為基準(zhǔn)進(jìn)行用例采集。根據(jù)業(yè)務(wù)重要性、線上訪問(wèn)情況,按優(yōu)先級(jí)執(zhí)行測(cè)試。單測(cè)能有效降低回歸成本,在新業(yè)務(wù)持續(xù)接入的背景下,保障系統(tǒng)穩(wěn)定性。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

適配器層的自動(dòng)代碼轉(zhuǎn)換 - 基于gogocode將vue2升級(jí)為vue3 setup語(yǔ)法

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

調(diào)研與分析

kZ828資訊網(wǎng)——每日最新資訊28at.com

在尋求升級(jí)方案的過(guò)程中,我們對(duì)比了兩款工具:Gogocode 和 vue2-to-composition-api。以下是它們的簡(jiǎn)要對(duì)比:kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

功能kZ828資訊網(wǎng)——每日最新資訊28at.com

GogocodekZ828資訊網(wǎng)——每日最新資訊28at.com

vue2-to-composition-apikZ828資訊網(wǎng)——每日最新資訊28at.com

缺點(diǎn)kZ828資訊網(wǎng)——每日最新資訊28at.com

默認(rèn)不支持轉(zhuǎn)換成 Vue3 setup 語(yǔ)法kZ828資訊網(wǎng)——每日最新資訊28at.com

不支持 template 轉(zhuǎn)換kZ828資訊網(wǎng)——每日最新資訊28at.com

轉(zhuǎn)換規(guī)則覆蓋kZ828資訊網(wǎng)——每日最新資訊28at.com

轉(zhuǎn)換規(guī)則列表kZ828資訊網(wǎng)——每日最新資訊28at.com

轉(zhuǎn)換效果kZ828資訊網(wǎng)——每日最新資訊28at.com

特性kZ828資訊網(wǎng)——每日最新資訊28at.com

像 jQuery 一樣修改ASTkZ828資訊網(wǎng)——每日最新資訊28at.com

將 Vue2 代碼轉(zhuǎn)換為 Vue 3 的 Composition API 格式kZ828資訊網(wǎng)——每日最新資訊28at.com


kZ828資訊網(wǎng)——每日最新資訊28at.com

2. jQuery-like API 簡(jiǎn)化了 AST 修改成本kZ828資訊網(wǎng)——每日最新資訊28at.com

2. 支持在線轉(zhuǎn)換kZ828資訊網(wǎng)——每日最新資訊28at.com

優(yōu)點(diǎn)kZ828資訊網(wǎng)——每日最新資訊28at.com

1. 支持自定義插件kZ828資訊網(wǎng)——每日最新資訊28at.com

1. 支持轉(zhuǎn)換成 Vue3 setup 語(yǔ)法kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

經(jīng)過(guò)調(diào)研,gogocode 是基于 AST 封裝的庫(kù)可擴(kuò)展空間大,但是默認(rèn) gogocode-plugin-vue 不支持轉(zhuǎn)換成 Composition APIkZ828資訊網(wǎng)——每日最新資訊28at.com

vue2-to-composition-api 倒是支持 Composition API,但是不支持 template 部分的轉(zhuǎn)換。kZ828資訊網(wǎng)——每日最新資訊28at.com

考慮到我們的項(xiàng)目中有許多自定義的轉(zhuǎn)換邏輯,如 UI 庫(kù)替換、store 替換等,我們最終決定使用 gogocode 作為主要工具,并結(jié)合其他手段來(lái)實(shí)現(xiàn) vue2 到 vue3 的全面升級(jí)。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

實(shí)施與探索

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

基礎(chǔ):升級(jí)語(yǔ)法

kZ828資訊網(wǎng)——每日最新資訊28at.com

升級(jí)語(yǔ)法是借助 gogocode 的 replace 方法實(shí)現(xiàn)的,通過(guò) $$$ 匹配符保留所需要的代碼塊,將 Vue2 的語(yǔ)法快速替換成 Vue3 的語(yǔ)法。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

// 替換datascriptAst.replace("data() {return {$$$};}", `const $data = reactive({$$$})`);
// 替換propsscriptAst.replace("props:{$$$}", "const props = defineProps({$$$})");
// 替換生命周期scriptAst.replace("created(){$$$}", "onBeforeMount(()=>{$$$})")  .replace("mounted(){$$$}", "onMounted(()=>{$$$})")  .replace("async mounted(){$$$}", "onMounted(async ()=>{$$$})")  .replace("beforeUnmount(){$$$}", "onBeforeUnmount(()=>{$$$})")  .replace("unmounted(){$$$}", "onUnmounted(()=>{$$$})")  .replace("beforeDestroy(){$$$}", "onBeforeUnmount(()=>{$$$})")  .replace("destoryed(){$$$}", "onUnmounted(()=>{$$$})");

kZ828資訊網(wǎng)——每日最新資訊28at.com

效果如下,通過(guò) replace 替換的方式適合大部分場(chǎng)景,比如 methods、filters、watch 等kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

進(jìn)階:處理模板中的變量、函數(shù)中的this變量kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

template綁定的變量可能是data,可能是props,還可能是 methodskZ828資訊網(wǎng)——每日最新資訊28at.com

想要替換 template 中的變量,需要先收集 data、props、methods 中的 keyskZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

getDataKeys() {  const keys = new Set();  // 只需要第一層的key,所以deep設(shè)為1  this.scriptAst.find('data() {$$$}').find('$_$:$_$', { deep: 1 }).each(node => {    if (node.match[0] && node.match[0][0].node.type === 'Identifier') {      keys.add(node.match[0][0].value);    }  });  return Array.from(keys)}getPropsKeys() {  const keys = new Set();  this.scriptAst.find('props: {$$$1}', { deep: 1 }).each((node) => {    if (node.match['$$$1']) {      node.match['$$$1'].forEach((item) => {        if (item.key && item.key.type === 'Identifier') {          keys.add(item.key.name)        }      })    }  });  return Array.from(keys)}// methods 有點(diǎn)小復(fù)雜,需要考慮異步函數(shù),普通函數(shù)和鍵值對(duì)的寫(xiě)法getMethodsKeys() {  const methodsAst = this.scriptAst.find('methods:{$$$}');  const methods = methodsAst.find('$_$() {$$$1}');  const asyncmMethods = methodsAst.find('async $_$(){$$$1}');  const mapKeys = methodsAst.find('$_$:$$$1', { deep: 1 });  const methodNames = [];  methods.each(node => {    if (node.match[0] && node.match[0][0]) {      methodNames.push(node.match[0][0].value);    }  });  asyncmMethods.each(node => {    if (node.match[0] && node.match[0][0]) {      methodNames.push(node.match[0][0].value);    }  });  mapKeys.each(node => {    if (node.match[0] && node.match[0][0]) {      methodNames.push(node.match[0][0].value);    }  });  return methodNames;}

kZ828資訊網(wǎng)——每日最新資訊28at.com

收集完成后可以開(kāi)始遍歷 template 中的 attr,并替換所綁定的變量了。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

handlTemplate() {    // 替換attr, 例如 <div :value="value"></div>    this.ast.find("<template></template>").find(`<$_$ ="$$$0" >$$$1</$_$>`).each((node) => {      node.match['$$$0'].forEach(attr => {        if (attr && attr.value) {          this.dataKeys.some(keyName => {            const reg = new RegExp(`${keyName}//b`, 'g')            const macth = reg.test(attr.value.content);            attr.value.content = attr.value.content.replace(reg, `$data.${keyName}`)            if (macth) {              return true;            }          })          this.methodsKeys.some(keyName => {            const reg = new RegExp(`//b${keyName}//b`, 'g')            const macth = reg.test(attr.value.content);            attr.value.content = attr.value.content.replace(reg, `methods.${keyName}`)            if (macth) {              return true;            }          })          this.propsKeys.some(keyName => {            const reg = new RegExp(`//b${keyName}//b`, 'g')            const macth = reg.test(attr.value.content);            attr.value.content = attr.value.content.replace(reg, `props.${keyName}`)            if (macth) {              return true;            }          })        }      })      // 替換content,例如:<div>{{value}}<div>      node.match['$$$1'].forEach(node => {        if (node.content && node.content.value) {          // 省略:與上面類(lèi)似        }      })    })  }

kZ828資訊網(wǎng)——每日最新資訊28at.com

說(shuō)到 this 替換也是一個(gè)繁瑣的問(wèn)題,this.xx, xx 可以是 data,可以是props,可以是 function,還可以是私有屬性等。kZ828資訊網(wǎng)——每日最新資訊28at.com

所以我們需要先把組件中的 data、props、methods、mapGetter 中的 keys 都收集一遍,然后再替換 script 中的 this 變量。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

// 正則替換更方便,所以需要放在最后一步替換handlThis(code) {  code = code.replace(/this/.([_$0-9a-zA-Z]+)/g, (match, $1) => {    // 替換function body 中的 data引用    if (this.dataKeys.includes($1)) {      return `$data.${$1}`;    }    // 替換function body 中的 methods調(diào)用    else if (this.methodsKeys.includes($1)) {      return `methods.${$1}`;    }    // 替換 vm 私有屬性    else if ($1 && $1[0] === '$') {      return `$vm.${$1}`;    } else if (this.computedKeys.includes($1)) {      return $1    } else if (this.propsKeys.includes($1)) {      return `props.${$1}`    }    return `$vm.${$1}`  })  // 替換function body 中的 動(dòng)態(tài)methods調(diào)用  code = code.replace(/this/[(.+)/]/g, (match, $1) => {    return `methods[${$1}]`;  })  return code}

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

進(jìn)階:動(dòng)態(tài)調(diào)用this.xxx該如何解決

kZ828資訊網(wǎng)——每日最新資訊28at.com

async parseOpenDialog(payload) {  const { schema, data } = payload  await this[schema.method](    parseSchema,    data,    dialogParams,    dialogType  )}

按 vue3 新的寫(xiě)法,一般是展開(kāi)的kZ828資訊網(wǎng)——每日最新資訊28at.com

const parseOpenDialog = async (payload) => {}

但是按這個(gè)習(xí)慣來(lái)轉(zhuǎn)換,就無(wú)法做到動(dòng)態(tài)調(diào)用this.xxx,我們可以嘗試把方法都放在methods對(duì)象中,有點(diǎn)類(lèi)似 vue2kZ828資訊網(wǎng)——每日最新資訊28at.com

const methods = {  parseOpenDialog: async (payload) => {  },  xxx: async() => {  }}

在替換 this 時(shí),將 this 替換成 methods 變成 methods[schema.method]()。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

其他技巧

kZ828資訊網(wǎng)——每日最新資訊28at.com

1 . 原來(lái) vue2 中肯很多屬性掛在組件實(shí)例上,比如 $route, $router, $emit 甚至自定義的屬性等等。下面是 vue3 中獲取組件實(shí)例的方法。kZ828資訊網(wǎng)——每日最新資訊28at.com

import { getCurrentInstance } from 'vue'const { proxy: $vm } = getCurrentInstance()$vm.xxx = '自定義屬性'

2 . 原來(lái)使用的 vuex,現(xiàn)在使用的是 pinia。我們需要先收集 ...mapState($_$, [$$$1]),然后使用 storeToRefs 代替kZ828資訊網(wǎng)——每日最新資訊28at.com

// 獲取store 使用storeToRefsif (this.storeType === 'pinia') {  this.scriptAst  .find("computed:{}")  .before(`const {${stateNames.join(',')}} = storeToRefs(${this.getPiniaStoreName(key)})`)  .replace("computed:{$$$}", "$$$")}

最終將上述轉(zhuǎn)換能力封裝成一個(gè)庫(kù),通過(guò) npm 安裝來(lái)實(shí)現(xiàn)組件批量升級(jí)。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

遷移前后的E2E測(cè)試 - 視覺(jué)輔助UI自動(dòng)化測(cè)試kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

端到端測(cè)試是確保新舊系統(tǒng)平穩(wěn)過(guò)渡的關(guān)鍵步驟。本次遷移依舊遵循漸進(jìn)式升級(jí)的原則,新增v3路由,線上新老路由共存。共分為功能測(cè)試、UI測(cè)試、性能測(cè)試三個(gè)部分。功能測(cè)試為單元測(cè)試的補(bǔ)充,主要驗(yàn)證新老路由下核心操作路徑及提交參數(shù)的一致性,攔截請(qǐng)求避免對(duì)線上造成影響。性能由通用監(jiān)控大盤(pán)進(jìn)行保障。UI對(duì)比測(cè)試是本次的重點(diǎn)。kZ828資訊網(wǎng)——每日最新資訊28at.com

新老倉(cāng)庫(kù)分別基于Element UI和Element Plus,Element Plus重新設(shè)計(jì)了組件以適應(yīng)Vue3,組件尺寸體系調(diào)整為更自然的大中小選項(xiàng)。間距優(yōu)化為更通用的4px體系,主要涉及 padding 和 margin 屬性修改、 font-size 等字體和圖標(biāo)大小修改等。因此,雖然大部分組件在外觀上保持相似,視覺(jué)和布局上可能有一些差異。由于業(yè)務(wù)組件具備一定復(fù)雜性,手寫(xiě)測(cè)試用例工作量繁瑣,新舊頁(yè)面組件可能存在差異無(wú)法完全復(fù)用,方案也不具備通用性。因此考慮使用計(jì)算機(jī)視覺(jué)技術(shù)來(lái)識(shí)別和驗(yàn)證用戶界面的元素。kZ828資訊網(wǎng)——每日最新資訊28at.com

基于公司內(nèi)部的自動(dòng)化測(cè)試平臺(tái),測(cè)試框架為Playwright,測(cè)試語(yǔ)言選擇Python以更好的利用豐富的圖像處理庫(kù)。指定CSS選擇器,隨機(jī)選擇頁(yè)面上的元素進(jìn)行截圖和對(duì)比,設(shè)定閾值進(jìn)行判斷。圖像相似度對(duì)比可分為傳統(tǒng)的基于像素差的方法和基于圖像特征的方法。圖像特征有SIFT、ORB等特征提取方法和深度學(xué)習(xí)方法。分別選擇一種代表性的算法進(jìn)行對(duì)比和測(cè)試。kZ828資訊網(wǎng)——每日最新資訊28at.com

  • SSIM(結(jié)構(gòu)相似性指數(shù)),同時(shí)考慮圖片亮度、對(duì)比度與結(jié)構(gòu)信息。用于檢測(cè)兩張相同尺寸的圖像的相似性。對(duì)于圖像的亮度和對(duì)比度變化具有較好的魯棒性。
  • SIFT(尺度不變特征變換),用于在圖像中檢測(cè)和描述局部特征,這些特征對(duì)圖像的縮放、旋轉(zhuǎn)和部分亮度變化具有不變性。能夠檢測(cè)和匹配不同尺寸下的特征,對(duì)圖像的仿射變換、噪聲和部分遮擋具有較好的魯棒性。
  • LPIPS是一種深度學(xué)習(xí)特征,用于量化圖像之間的感知相似性,通過(guò)比較圖像在深度神經(jīng)網(wǎng)絡(luò)中的特征表示來(lái)工作,這些特征能夠捕捉到人類(lèi)視覺(jué)所關(guān)注的圖像細(xì)節(jié)。基于一個(gè)大規(guī)模的人類(lèi)感知相似性判斷數(shù)據(jù)集,包含484K個(gè)人類(lèi)的判斷,涵蓋了多種圖像變換和失真類(lèi)型。使用深度特征(例如VGG網(wǎng)絡(luò)中的特征)來(lái)衡量圖像相似性,比傳統(tǒng)的度量方法更有效。

kZ828資訊網(wǎng)——每日最新資訊28at.com

v2kZ828資訊網(wǎng)——每日最新資訊28at.com

v3kZ828資訊網(wǎng)——每日最新資訊28at.com

SSIMkZ828資訊網(wǎng)——每日最新資訊28at.com

SIFTkZ828資訊網(wǎng)——每日最新資訊28at.com

LPIPSkZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

0.656kZ828資訊網(wǎng)——每日最新資訊28at.com

0.855kZ828資訊網(wǎng)——每日最新資訊28at.com

0.909kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

0.916kZ828資訊網(wǎng)——每日最新資訊28at.com

0.874kZ828資訊網(wǎng)——每日最新資訊28at.com

0.961kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

0.658kZ828資訊網(wǎng)——每日最新資訊28at.com

0.857kZ828資訊網(wǎng)——每日最新資訊28at.com

0.881kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

0.877kZ828資訊網(wǎng)——每日最新資訊28at.com

0.855kZ828資訊網(wǎng)——每日最新資訊28at.com

0.926kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

0.551kZ828資訊網(wǎng)——每日最新資訊28at.com

0.836kZ828資訊網(wǎng)——每日最新資訊28at.com

0.947kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

0.929kZ828資訊網(wǎng)——每日最新資訊28at.com

0.884kZ828資訊網(wǎng)——每日最新資訊28at.com

0.942kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

實(shí)驗(yàn)表明,基于深度學(xué)習(xí)特征的相似度對(duì)比結(jié)果更接近用戶感知,針對(duì)Vue2升級(jí)Vue3 UI組件庫(kù)導(dǎo)致的間距、字體、尺寸等細(xì)微差異判斷更準(zhǔn)確。因此采用LPIPS作為對(duì)比算法。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

def compare_images(url1, url2):  loss_fn = lpips.LPIPS(net = 'alex')  img1 = cv2.imread(url1)  img2 = cv2.imread(url2)  if img1 is not None and img2 is not None and img1.size > 0 and img2.size > 0:      img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))      cv2.imwrite(url2, img2)      combined_image = cv2.hconcat([img1, img2])      ex_img1 = lpips.im2tensor(lpips.load_image(url1))      ex_img2 = lpips.im2tensor(lpips.load_image(url2))      d = loss_fn.forward(ex_img1, ex_img2)      if d is not None:          cv2.putText(combined_image,'score: %.3f'%(1 - d.mean()), (20, 20), cv2.FONT_ITALIC, 0.4, (255, 0, 255))      return d, combined_image  else:      return None

kZ828資訊網(wǎng)——每日最新資訊28at.com

依據(jù)業(yè)務(wù)流程,分別訪問(wèn)新老路由,對(duì)頁(yè)面指定元素進(jìn)行截圖、對(duì)比和拼接,輸出測(cè)試截圖和完整的測(cè)試報(bào)告。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

采用視覺(jué)輔助UI自動(dòng)化測(cè)試,更接近用戶真實(shí)感知,大大降低測(cè)試用例復(fù)雜度,提升測(cè)試效率,無(wú)需關(guān)注繁雜的DOM元素層級(jí)。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

上線

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

以頁(yè)面配置的形式按待辦進(jìn)行灰度,跳轉(zhuǎn)至新路由。單元測(cè)試已集成至項(xiàng)目流水線中,MR和發(fā)布前觸發(fā)。灰度過(guò)程中手動(dòng)執(zhí)行E2E用例,以自定義環(huán)境變量的形式指定頁(yè)面路徑、元素選擇器、相似度閾值等。測(cè)試通過(guò)后修改頁(yè)面配置,引流至新路由。通過(guò)用戶故障群和頁(yè)面反饋入口響應(yīng)用戶反饋,結(jié)合前端埋點(diǎn)報(bào)表觀察線上使用情況和確定灰度策略。通過(guò)完善單元測(cè)試、E2E測(cè)試和制定合理的灰度策略,針對(duì)特定模板的遷移已順利完成,期間未收到線上故障反饋。kZ828資訊網(wǎng)——每日最新資訊28at.com

后續(xù)遷移策略將以老倉(cāng)庫(kù)中改動(dòng)較頻繁文件優(yōu)先入手,測(cè)試用例先行,借助自動(dòng)代碼轉(zhuǎn)換工具快速平穩(wěn)遷移,線上埋點(diǎn)數(shù)據(jù)做輔助。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

收益

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

活躍代碼陸續(xù)遷移,結(jié)束多倉(cāng)庫(kù)并行,減少維護(hù)心智。之前我們的常態(tài)是新老倉(cāng)庫(kù)并行,開(kāi)發(fā)一個(gè)完整的業(yè)務(wù)功能時(shí)要在ts和js,選項(xiàng)式API和setup語(yǔ)法之間頻繁切換,心智負(fù)擔(dān)較重。活躍代碼陸續(xù)遷移至vue3新倉(cāng)庫(kù),結(jié)合新的框架特性和實(shí)用工具,能夠更專注于業(yè)務(wù)邏輯本身。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

核心模塊重構(gòu),“巨石store”輕量化,提高可維護(hù)性和可演進(jìn)性,分層結(jié)構(gòu)保障核心邏輯穩(wěn)定性。原本配置能力擴(kuò)充時(shí)需要在復(fù)雜的數(shù)據(jù)流中“走迷宮”,耦合嚴(yán)重,通用代碼影響范圍大,常常出現(xiàn)A業(yè)務(wù)需求上線導(dǎo)致B業(yè)務(wù)不可用的情況。利用整潔架構(gòu)進(jìn)行分層設(shè)計(jì)后,新增一種審核模式僅需在適配器層新增對(duì)應(yīng)物料和action,用例層新增用例。無(wú)需修改實(shí)體層和其他業(yè)務(wù)相關(guān)的用例、通用頁(yè)面、物料等。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

業(yè)務(wù)邏輯的重新梳理,彌補(bǔ)測(cè)試用例空缺。領(lǐng)域提取是對(duì)業(yè)務(wù)邏輯的重新梳理,前端能加深業(yè)務(wù)理解。穩(wěn)定性至上的模塊很長(zhǎng)時(shí)間缺少測(cè)試用例,造成對(duì)開(kāi)發(fā)人員的經(jīng)驗(yàn)、能力依賴極大。完善核心鏈路的測(cè)試用例能有效降低回歸成本,保障系統(tǒng)穩(wěn)定性。kZ828資訊網(wǎng)——每日最新資訊28at.com

工具沉淀,組內(nèi)復(fù)用。自動(dòng)代碼轉(zhuǎn)換工具和基于AI能力的前端E2E測(cè)試方案為后續(xù)組內(nèi)其他項(xiàng)目的框架升級(jí)和遷移提供了便利。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

總結(jié)與展望

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

在2023年開(kāi)始漸進(jìn)式升級(jí)Vue3后,我們經(jīng)歷了很長(zhǎng)一段時(shí)間的多倉(cāng)庫(kù)并行。在新業(yè)務(wù)不斷接入、開(kāi)發(fā)新成員加入的背景下,這樣的模式無(wú)疑提升了開(kāi)發(fā)門(mén)檻和維護(hù)心智。本次活躍代碼的陸續(xù)遷移結(jié)束了多倉(cāng)庫(kù)并行的現(xiàn)狀,同時(shí)在整個(gè)實(shí)踐過(guò)程中我們?yōu)閷徍似脚_(tái)這個(gè)大型復(fù)雜項(xiàng)目前端引入了整潔架構(gòu)的思想,為后續(xù)的開(kāi)發(fā)維護(hù)提供了一種新的思路。沉淀了一套自動(dòng)化vue2代碼轉(zhuǎn)vue3 setup的工具,可為后臺(tái)項(xiàng)目的框架升級(jí)提供便利。同時(shí)借助AI能力提升前端E2E測(cè)試的效率,利用計(jì)算機(jī)視覺(jué)輔助前端UI自動(dòng)化測(cè)試。有幾點(diǎn)心得:kZ828資訊網(wǎng)——每日最新資訊28at.com

完美重構(gòu)、敏捷重構(gòu)、系統(tǒng)穩(wěn)定性難以平衡。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

既然下定決心對(duì)年久失修的代碼進(jìn)行重構(gòu),我們一定是追求極致優(yōu)化和整潔的。但是需求現(xiàn)狀是不斷有新特性進(jìn)來(lái),戰(zhàn)線拉的太長(zhǎng)必將導(dǎo)致抹平差異的成本增加,因此敏捷性也很重要。同時(shí)底線是關(guān)注系統(tǒng)的可靠性和穩(wěn)定性。這三者一定程度上存在矛盾,需平衡:kZ828資訊網(wǎng)——每日最新資訊28at.com

  • 任務(wù)拆分,基于埋點(diǎn)數(shù)據(jù)選擇最重要或最緊急的鏈路進(jìn)行重構(gòu),而非追求大而全,先落地架構(gòu),后擴(kuò)充功能
  • 測(cè)試用例先行,重構(gòu)必將引入風(fēng)險(xiǎn),用例先行能最大程度保障核心功能的穩(wěn)定遷移
  • 制定合理的灰度策略,新增路由,以頁(yè)面配置形式進(jìn)行灰度,優(yōu)先uv較低的頁(yè)面驗(yàn)證,并保證及時(shí)的反饋渠道
  • 持續(xù)優(yōu)化,重構(gòu)應(yīng)成為一種思想,在迭代中持續(xù)優(yōu)化

整潔架構(gòu)非銀彈,容易過(guò)度設(shè)計(jì),學(xué)習(xí)門(mén)檻較高。kZ828資訊網(wǎng)——每日最新資訊28at.com

  • 按模塊重構(gòu),而非項(xiàng)目
  • 針對(duì)新架構(gòu),制定長(zhǎng)期維護(hù)計(jì)劃,組織團(tuán)隊(duì)培訓(xùn),降低學(xué)習(xí)成本

kZ828資訊網(wǎng)——每日最新資訊28at.com

多倉(cāng)庫(kù)遷移路線:數(shù)據(jù)為支撐,測(cè)試用例先行,借助自動(dòng)代碼轉(zhuǎn)換工具和視覺(jué)輔助UI自動(dòng)化測(cè)試,制定合理的灰度策略并建立及時(shí)的故障反饋和響應(yīng)渠道。對(duì)于大型復(fù)雜項(xiàng)目或模塊,先進(jìn)行面向遷移的重構(gòu),也能起到事半功倍的作用。kZ828資訊網(wǎng)——每日最新資訊28at.com

kZ828資訊網(wǎng)——每日最新資訊28at.com

對(duì)我們而言,遷移的結(jié)束只是起點(diǎn),基于更整潔的架構(gòu)和更先進(jìn)的前端框架,未來(lái)仍有很多發(fā)力點(diǎn):kZ828資訊網(wǎng)——每日最新資訊28at.com

  • 對(duì)于遷移過(guò)程中沉淀下來(lái)的新架構(gòu),需不斷優(yōu)化和改進(jìn),以適應(yīng)復(fù)雜的業(yè)務(wù)場(chǎng)景。
  • 在更多的業(yè)務(wù)場(chǎng)景下評(píng)估遷移后的性能改進(jìn),確保用戶體驗(yàn)得到提升。
  • 持續(xù)審查并解決在遷移過(guò)程中發(fā)現(xiàn)的技術(shù)債務(wù)。
  • 持續(xù)建設(shè)自動(dòng)代碼轉(zhuǎn)換工具,賦能團(tuán)隊(duì)內(nèi)其他項(xiàng)目。
  • 視覺(jué)輔助UI自動(dòng)化測(cè)試的方案,進(jìn)一步抽象,給到不熟悉自動(dòng)化測(cè)試的團(tuán)隊(duì)成員“開(kāi)箱即用”。
  • ...

本文鏈接:http://www.www897cc.com/showinfo-26-99167-0.html我們一起聊聊審核平臺(tái)前端新老倉(cāng)庫(kù)遷移

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: AI 引領(lǐng)佛山智造 數(shù)聚禪城開(kāi)拓創(chuàng)新 2024 華為開(kāi)發(fā)者大會(huì)佛山分會(huì)場(chǎng)圓滿落幕

下一篇: Go語(yǔ)言助力安全測(cè)試:24小時(shí)內(nèi)發(fā)送5億次HTTP/1.1請(qǐng)求

標(biāo)簽:
  • 熱門(mén)焦點(diǎn)
Top 主站蜘蛛池模板: 湾仔区| 江山市| 井冈山市| 瑞金市| 祁连县| 铜山县| 嘉兴市| 丹凤县| 清涧县| 华亭县| 临汾市| 金塔县| 襄城县| 凌源市| 新源县| 紫金县| 阜宁县| 若尔盖县| 宁城县| 水城县| 通江县| 乌拉特后旗| 兴安县| 张北县| 中山市| 平罗县| 长丰县| 安陆市| 都匀市| 靖州| 阳曲县| 周至县| 临潭县| 肇州县| 苏尼特左旗| 集安市| 崇礼县| 习水县| 郑州市| 滁州市| 温宿县|