Categories
程式開發

消費者端微組件的實現


一、背景

在消費者端,為了方便各條業務線接入,我們通常以組件的方式提供功能,但是組件的發布必須依賴於頁面的發布,頁面發布又通常需要業務方統一操作,比較影響組件的迭代速度。

經過一段時間的探索和開發,我們實現了一種可以讓組件獨立發布的異步方案,具備以下特點:

  • 組件級別解耦,獨立版本控制
  • 組件單獨發布,支持灰度、秒級回滾以及平滑升降級
  • 不影響現有的開發測試流程

下面我介紹一下我們的方案。

二、概述

一句話概括:將組件獨立打包成UMD 格式的js 文件,頁面加載時通過動態生成script 插入該js,插入完成後渲染組件。

組件單獨打包是異步組件實現的基礎,動態獲取js 能實時地獲取最新版本,再結合組件動態切換可以實現組件的升降級。

異步組件方案核心功能通過消費者端組件、Node 端插件和打包服務三部分來實現:

  • 組件Vue-Components-Injector —— 負責h5端異步組件的注入,動態渲染和降級,提高異步組件的穩定性。
  • Node端插件Apollo-Dynamic-Components —— 使用分佈式配置中心Apollo 處理配置的分發,實現實時組件灰度切流和版本迭代。
  • 打包中心—— 負責將組件源碼打包成瀏覽器可立即執行的UMD 代碼,保障代碼的兼容性。

使用異步組件的流程:

  1. 使用打包工具將組件源代碼獨立打包成UMD 代碼並上傳到CDN
  2. 修改組件配置,包含代碼地址、版本、灰度比例以及降級版本等信息
  3. 頁面請求Node 時,Apollo-Dynamic-Components 插件會根據配置,返回頁面需要的異步組件信息並放入全局變量內
  4. 頁面加載時,從全局變量獲取異步組件信息,並告訴Vue-Components-Injector要使用哪個異步組件以及異步組件的變量名
  5. Vue-Components-Injector 構建script 標籤,加載js 掛載組件並渲染

具體思路如下圖所示:

消費者端微組件的實現 1

三,具體分析

3.1 組件代碼獨立打包

首先我們需要將原本ESM 或者CJS 的組件打包成UMD 規範或者IIFE 的形式。

打包配置可以根據每個組件的內容和使用方法單獨配置,不需要修改代碼,所以組件依然可以通過NPM 的方式引入。

打包完成後,為了加快文件的下載速度,通過腳本將文件上傳到cdn 服務器,然後將返回的cdn 地址同步到配置中心。 這樣我們就完成了組件打包層面的解耦,將組件打包流程從項目打包中獨立出來。

這裡有一個優化點,可以把一些公共的依賴排除在外,使用時在項目中配置組件的外部依賴,不過需要注意該組件依賴的版本和項目中依賴的版本是否兼容。

消費者端微組件的實現 2

3.2 Node 端獲取組件配置

Node 端收到頁面請求後,獲取當前組件在配置中心包含灰度切流比例和A/B版本信息的配置內容,A/B版本的使用會在組件動態切換中詳細介紹。

每次請求都會獲取最新的異步組件配置,所以配置更新時能夠第一時間在線上生效,異步組件的發布和秒級回滾都依賴這個特性。 這個功能我們通過插件的方式來實現,保證業務代碼的足夠精簡、穩定,使用也方便。

Apollo 使用分佈式部署,可用性高且能實時更新配置,同時也可以在開發、測試、生產等環境分別部署運行,對開發很友好。

3.3 加載異步組件

為了進一步提高異步組件的加載速度、減少請求次數和耗時,我們將異步組件配置在node層返回html 模版的時候注入。 整個流程分為4 步:

  • vue-components-injector 獲取配置
  • 生成script 標籤並插入到頁面中,加載腳本
  • 監聽js onload 事件,加載成功後調用回調函數
  • 執行組件掛載

消費者端微組件的實現 3

3.4 組件動態切換

線上的穩定性非常重要,當異步組件地址獲取異常、加載異常、沒有命中切流或其他異常情況發生時,vue-components-injector 會立刻根據配置策略動態切換到其他版本或使用NPM 引入的原組件,保證異步組件在極端情況下的可用性。

組件升級也是經常出現問題的地方,我們可以通過配置A/B版本信息並結合百分比切流來實現組件版本穩定升級。

例如我們將A 版本設置為當前版本的js 地址,B版本配置為將要發布的新版本,將流量通過修改灰度比例逐步切換到B版本,如果遇到異常情況,可以通過修改組件配置立刻切回A版本。

四、效果

最近我們陸續將交易下單頁中的儲值卡和收銀台的引入方式替換為異步組件加載,得益於我們比較充分的準備,替換過程比較順利,上線之後也比較穩定,達到了預期的目標。

後續我們會簡化異步組件的接入流程,擴大接入範圍,優化有贊消費者端用戶體驗。

本文轉載自公眾號有贊coder(ID:youzan_coder)。

原文鏈接

消費者端微組件的實現