本文首發于 vivo網際網路技術 微信公衆号
連結:
https://mp.weixin.qq.com/s/Ka1pjJKuFwuVL8B-t7CwuA 作者:悟空中台研發團隊
一、緣起 - 什麼是悟空活動中台?
随着 vivo 網際網路使用者量級不斷增加,應用商店、官網商城、 遊戲中心和浏覽器等 vivo 官方産品相繼進入存量使用者營運時代。在這種大背景下,營銷活動日益增多,傳統活動開發模式已經不能滿足井噴式且多樣化的需求,項目開發和産品營運過程中遇到種種困難:
1. 浏覽器團隊開發的活動元件, 商城活動項目能否拿來複用?
2. 遊戲中心團隊開發的 H5 頁面,會員活動項目能否拿來複用?
3. H5 項目釋出周期較長,修改文案需要重新上線,能否把活動營運效率最大化?
4. 輕 H5 業務能否節省相應配比的服務端和測試人力?
5.各 BU 業務不同,活動背景系統過多,研發效率和營運效率低下,導緻資料孤島現象嚴重。
6.研發輪子過多,問題場景沒有标準的解決方案,營銷活動常見問題沒有官方團隊進行統一收集沉澱。
7.非業務 H5 需求,如招聘、節日、活動報名等,需使用外部的建站産品且資料安全風險高。
8.……
「悟空」,是我們在攻克上述問題場景過程中誕生的 「插拔化、可視化、一站式」的綜合活動中台,目前已是 vivo 活動項目首選的線上開發平台、營運平台。
取名為 「悟空」,是承載了我們的願景,在技術領域持續探索,修煉“七十二變”,不斷攻克企業活動項目運作過程中的“九九八十一難”,取得“真經”。
截止目前,悟空接入 BU30+ 、上線 H5 頁面 7000+ 、營銷元件 20+ 、各品類模版 50+ 和營銷任務 60+ 。
以下是 vivo 各 BU 網際網路團隊在悟空上進行開發送出、上線營運的經典活動。

圖1 - 經典營銷活動截圖
二、活動營運為什麼選擇悟空?
舉個栗子:
vivo 商城團隊針對國慶節促銷活動開發了一款爆款 H5 ,其中【集卡】元件效果出衆。vivo 會員團隊希望雙十一也上線一款類似的 H5 活動頁,也期望具備【集卡】元件能力。
傳統方案:
會員團隊線下 clone 一份商城 H5 活動代碼,根據業務進行定制修改後上線。因【集卡】涉及營運政策線上配置,需要重新開發相應的活動配置功能。
痛點:
1. H5 代碼耦合業務嚴重,可維護性、可擴充性下降。
2. 單次開發的背景功能,可能僅服務于本次活動,投入産出比低。
3. 針對活動上線後的效果,相關埋點需要重新設計。
4.若需要風控、資料分析、微信二次分享等活動配套能力,需要重新開發。
如何解決:
而悟空從元件/模版市場、任務中心、實時配置、活動配套,四個次元解決上述的痛點。
目前會員的營運同學隻需要在悟空模版市場中挑選自己需要的 H5 活動,進行業務化調整配置,釋出上線即可。若有定制需求,悟空提供線上開發能力,幫助研發快速産出業務元件。
下面是各功能次元的詳細介紹。
1、元件/模版市場
悟空活動中台提供通用的營銷元件(抽獎、表單、答題、投票等),内容元件(文本、圖檔、樓層、熱區、導航、輪播)等。
在此基礎上悟空提出元件市場概念:
各 BU 團隊線上送出定制的活動元件,悟空活動設計器提供實時拉取并渲染元件能力。同時支援版本切換、環境切換等能力。
此外元件可視化拼接成的 H5 活動頁後,可再次轉換成活動模版,供下次或其他團隊使用。通過悟空提供的市場, H5 模版或元件很友善的在内部團隊中流轉,進而達到高複用、高保障的目的。
2、任務中心
大多數的 H5 營銷元件或活動場景都會配套複雜的營銷任務和配置需求,也是衆多活動系統誕生的原因。悟空為了解決不同活動的配置背景個性化問題,提出了任務中心的概念。
任務中心:悟空支援各 BU 團隊線下送出「管理背景頁面」,無需發版即可線上自動拉取,使用者送出的頁面并渲染至頁面。通過該機制,悟空就具備了收容不同活動管理背景的能力。
與傳統 iframe 嵌入子系統方案不同,悟空裝載的是離線代碼,符合悟空标準送出的制品,可“嚴絲合縫”熱加載至平台架構。提供給使用者一緻的互動體驗和使用習慣。
與元件概念類似,悟空提供通用任務中心(獎品配置中心、答題題目配置中心等)和私有任務中心概念。私有任務中心是各 BU 線下送出開發的活動配置頁面。
圖2 - 任務中心示例圖
如上圖,具備系統标簽的任務,是由悟空平台配置設定給該 BU 的系統級任務。而非系統标簽,如:預約、直播等,則是目前登入的 BU 業務方,自行開發上傳至平台使用。(系統具備維護擴充自身的能力)
3、實時配置
營銷活動支援配置實時生效,是精準營銷的基礎。悟空平台提供的可視化活動設計器,機制上會将配置資料(頁面配置、元件配置、任務配置)與 H5 頁面分離。
使用者終端通路 H5 活動時,會從雲端自動拉取在平台配置的活動資料,渲染至頁面或活動元件中,達到代碼與資料動靜分離,且實時生效的能力。
圖3 - H5代碼與資料存取示意圖
流程如上圖,我們釋出活動上線後,活動配置資料存儲在雲端, H5 代碼上線在 CDN ,通過該機制成功避免修改配置,需要再次上線發版的尴尬。
H5 核心設計器功能概覽
圖4 - 悟空H5設計器功能概覽圖
4、活動配套
H5 活動可複用性高,定制化門檻低,線上時效性高是悟空活動中台最基本的能力。在複雜的線上營銷場景下,作為專業的活動中台,隻具備這些能力往往是不夠的。悟空針對營銷活動前中後時期,提供了常見的活動配套能力。例如:
素材庫:對接專業的素材網站,同時悟空提供線上壓縮,剪裁等圖檔處理能力。
自動化埋點:元件加載器會天然包裝 H5 元件,頁面群組件預設具備點選、曝光、操作時長等埋點能力。
微信分享:無需重複申請微信開放平台,預設具備二次分享能力。
資料線索:悟空支援線上實時資料可視化分析(計算名額、名額分檔、多元度、資料透視圖表等能力)。
同時悟空中台還內建借助了公司内部其他中台能力(反垃圾、實驗、監控、風控等),多元度助力線上活動營銷。
悟空中台産品架構圖
圖5 - 悟空中台産品架構圖
三、活動開發為什麼選擇悟空?
開篇我們提出了研發的痛點
研發輪子過多,問題場景沒有标準的解決方案,營銷活動常見問題沒有官方團隊進行統一收集沉澱。
悟空中台如何服務于開發者?
悟空提供了 PaaS 平台從開發環境、開發管理兩個次元,提升研發效率、研發體驗,幫助研發快速傳遞,做活動開發者最強大的後盾。
1、開發環境
系統預設提供的元件和任務若不能滿足各 BU 的業務需求, BU 就需要根據自身的業務場景去開發相應的套件(元件+任務)。這些套件可能隻是業務場景不一樣,但是底層能力都是一緻的。例如:
- 工具類庫
H5 投放場景多種多樣,相同互動觸發的方法各不相同,為了針對對不同用戶端環境的适配, 悟空封裝了 @vivo/wukong-api 工具類庫。其中包含了強業務性的能力封裝,如:環境判斷、使用者資訊擷取、不同環境的分享或下載下傳能力喚起等等。 在此基礎上,悟空還提供了常用的研發級的能力封裝,例如 cookie 操作, fetch 能力, webp ,埋點操作等工具方法。幫助前端開發者精力聚焦在業務開發,提升活動元件開發效率。同時 wukong-api 也是一個内部開源的解決方案,支援按需加載,持續跟進最新最優的解決方案。 目前已提供 10+ 強業務能力封裝。15+ 基礎能力封裝。
- 内置元件
内置元件是悟空提供給開發者快捷場景的能力封裝,差別于 @vivo/wukong-api ,它可以提供給開發者使用平台的能力,如媒體選擇器、圖層選擇器、活動選擇器、富文本、遮罩彈框等等。 舉個栗子:媒體選擇器,使用者需要在配置面闆直接上傳媒體或選擇已上傳的媒體。該選擇器會出現在不同的業務元件場景,而且強依賴平台提供能力。
示例代碼如下:
<template>
<media-picker
selectType="image"
:defaultImgs="url"
:uploadDialogVisible.sync="visible"
v-on:select-end-call="func">
</media-picker>
</template>
<script>
export default {
data() {
return {
visible: false
}
},
methods: {
func() { }
}
}
</script>
目前平台已提供内置元件 8+ ,通過多個次元幫助開發便捷使用平台能力,提升活動配置側開發效率。
- vscode 插件
為統一開發環境,不改變開發習慣,提供高效的開發工具,悟空開發了一款 vscode 插件,該插件內建了初始化制品,代碼遠端托管、NPM私服存取、活動元件管理、開發素材存儲等能力。 從元件初始化代碼生成,本地開發環境調試預覽到代碼自動托管。一站式開發體驗,幫助研發快速傳遞。  圖6 - vscode插件截圖 同時悟空 vscode 插件內建了本地開發工作台,支援跨裝置配置同步,本地存儲元件組合關系等功能,開發者所見即所得。 下圖示範了本地開發配置發生變更,多端裝置實時同步的效果。  圖7 - 本地開發平台實時預覽示範
- 開發者手冊
文檔即服務,上述的所有能力包括插件安裝、工具使用方法、案例示範等,悟空為開發者建立了線上開發者手冊,幫助開發者快速上手,友善查閱。
圖8 - 開發者手冊截圖
2、開發管理
悟空提供了 PaaS 開發平台,幫助研發管理開發産物,流程閉環,能力沉澱。
- 開發素材管理(元件、靜态資源檔案)
- 權限管理(多人協作,多項目維護)
- 元件管理(版本上下線,權限內建)
- 開發社群(問題收集、回報、沉澱)
功能顯而易見,此處就不展開叙述了。
四、揭秘悟空微前端方案
通過營運、研發兩個角度我們叙述了悟空中台能力。
那悟空 H5 設計器是如何做到平台無需版本更新, H5 活動制品(元件、任務)線上自動裝載并直接使用?
其實這就是悟空研發團隊一直在探索的 workless 的工作流中的微前端架構方案的應用。
該方案主要特點如下:
- 不同子系統可獨立部署,也可內建通路。(可聚可散)
- 主系統提供熱插拔能力,狀态同步通道。(子系統間也可互相協作)
通過上述的特點進行放大和縮小,就是悟空的任務中心、活動設計器 。
workless 是悟空目前緻力打造的高效能綜合研發體系,目标是追求極緻效果,解放生産力。目前 workless 在持續演進中,我們相信這将是 vivo 前端最先進生産力的代表。後續将會有專題文章進行介紹,此處就不展開了。
workless ≈ 終端即開(展現層)+雲端一站式開發(研發層)+ 微前端架構(架構層)+ 資料心髒(資料驅動層)
本節将為大家揭秘 vivo 微前端架構中的核心實作原理。
1、設計思路
千裡之行,始于足下。回歸最原始的開發功能來叙述其原理:即前端元件不與平台系統耦合,平台具備從服務端拉取元件能力,并提供元件熱插拔式渲染接口。
從服務端拉取并渲染至頁面的元件,我們稱之為微元件,即 RSC(Remote Service Component)遠端服務元件。
圖9 - 個性化元件流轉示意圖
為了滿足線上營運政策可以實時調整,悟空制定了 RSC 活動元件是由( UI + 配置)兩個子元件構成的規範。
├── code.vue # 編輯器中渲染的UI元件
├── prop.vue # 屬性面闆中渲染的配置元件
├── setting.json # 存儲初始化基礎配置和業務配置
└── package.json # 依賴資訊
同時設計器将會提供 UI 與配置元件間的資料共享機制,開發同學可以通過 setting.json 提前預設基礎設定或業務配置。機制上節省大量營運重複配置工作和學習元件使用的成本。
通過微元件的抽象和設計極大的縮短了活動頁的開發周期,營運同學可以從海量的元件和模闆中選擇活動所需,通過可視化的系統配置,做到所見即所得,一鍵實時釋出活動頁觸達使用者。
同時微元件建立在不改變開發習慣基礎上,減少彼此之間的依賴,降低了開發和維護成本。基于 RSC 的理念開發出的微元件具有下列特性:
- 高内聚
- 弱耦合
- 職責單一
- 可組合
- 可配置
示範場景
圖10 - RSC元件機制加載示範圖
當使用者點選或拖拽編輯器左側區域的元件到設計區域使用,設計器将根據元件的屬性(名稱、版本)發起 HTTP 元件請求(代碼、預設配置)。之後元件會熱加載到設計器中,預設配置也會随之生效。
針對不同的環境系統,不斷的疊代更新認知和理念,我們經過實踐發現 RSC 機制很好解決了元件和環境系統之間的協同和共享,達成了期待的結果:
營運:無需關心技術細節,可視化組合和配置,一鍵釋出直達使用者,線上實時調整營運政策,帶來更多商業價值。
産品:更快的上線速度,提升了服務品質和穩定性,承載更多商業價值。
開發:提升了疊代速度,提升了代碼品質,對新人友好,減少學習成本。
測試:通過可靠穩定的方案,減少重複測試工作量。
2、實作步驟
下面說明如何實作動态加載遠端元件。
步驟一:本地 SFC 元件
示例:
<template>
<div @click="test">click me | {{item}}</div>
</template>
<script>
export default {
data () {
return {
item: 1
}
},
methods: {
test () {
this.item++
}
}
}
</script>
注意:該SFC檔案僅是元件入口,可正常引入其他第三方元件或子元件。
步驟二:編譯 umd.js
vue 檔案轉換成 js 檔案,有以下兩種方案可選:
(1)webpack 配置
通過簡單的 webpack 導出配置,即導出我們的目标 js 檔案。
webpack 配置檔案參考如下:
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const path = require("path");
module.exports = {
entry: "./code.vue", // 需要轉換的vue檔案路徑
plugins: [new VueLoaderPlugin()],
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
externals: {
vue: "vue"
},
output: {
filename: "myLib.umd.min.js",
path: path.resolve(__dirname, "dist"),
library: "myLib",
libraryTarget: "umd",
libraryExport: "default",
globalObject: "typeof self !== 'undefined' ? self : this"
}
};
output 關鍵字段說明
library //導出js對象的名稱。
libraryTarget //導出對象的規範。
globalObject //umd對象挂載目标對象。
(2)@vue/cli
通過 @vue/cli 指令,我們可以将 vue 單檔案元件導出一個 myLib.umd.min.js(命名自定義) 。
指令如下:
vue-cli-service build --target lib --name myLib ./myLib.vue --formats umd-min
若有額外的 webpack 配置,可在 vue 檔案目錄下建立 vue.config.js 進行配置。
擴充
@vue/cli 的内置 build 建構導出指令底層同樣是使用了 webpack 的能力。
建構配置在
@vue/cli-service/lib/commands/build/resolveLibConfig.js //114行
截取如下
rawConfig.output = Object.assign(
{
library: libName,
libraryExport: isVueEntry ? "default" : undefined,
libraryTarget: format,
// preserve UDM header from webpack 3 until webpack provides either
// libraryTarget: 'esm' or target: 'universal'
// https://github.com/webpack/webpack/issues/6522
// https://github.com/webpack/webpack/issues/6525
globalObject: `(typeof self !== 'undefined' ? self : this)`
},
rawConfig.output,
{
filename: `${entryName}.js`,
chunkFilename: `${entryName}.[name].js`,
// use dynamic publicPath so this can be deployed anywhere
// the actual path will be determined at runtime by checking
// document.currentScript.src.
publicPath: ""
}
);
步驟三:線上渲染
如何将動态元件的 umd.js 中的元件對象導出并在 web 端使用呢?下面将揭開線上渲染的奧秘。
通過上述方法導出檔案後,我們将 umd.js 打開檢視一下,如下所示:
(function (e, t) {
'object' === typeof exports && 'object' === typeof module ? module.exports = t() : 'function' === typeof define && define.amd ? define([], t) : 'object' === typeof exports ? exports['myLib'] = t() : e['myLib'] = t()
})('undefined' !== typeof self ? self : this, function () {
return function (e) {
var t = {};
...
...
})["default"]
})
// # sourceMappingURL=myLib.umd.min.js.map
找到關鍵代碼
"undefined" !== typeof self ? self : this;
該代碼正是我們将 vue 代碼編譯成 js 檔案時的配置 globalObject 變量。
我們利用 new Function 建構一個函數的執行環境,然後把 self 對象進行篡改導出。再通過 vue 的 元件的 is 屬性,将遠端 vue 元件渲染至網頁。
完整代碼如下:
<template>
<div>
<component :is="mode" v-if="mode"></component>
<div @click="load">遠端加載元件</div>
</div>
</template>
<script>
export default {
data() {
return {
mode: null
};
},
methods: {
async load() {
let data = await fetch("http://localhost:8080/myLib.umd.min.js");
let mode = {};
//此時内部的self變量,被外部變量mode代替,成功将元件對象導出
new Function("self", `return ${await data.text()}`)(mode);
this.mode = mode.myLib;
}
}
};
</script>
代碼示範效果
圖11 - 線上案例示範圖
如圖11效果,元件代碼是通過 fetch 動态加載,點選元件數字可正常自增。
通過 RSC 元件加載機制實作的微前端架構,使前端業務系統與平台分離。為系統可第三方定制的能力,奠定了強大的基礎,也是一切可能的開始。
3、關于資料服務
悟空微前端方案中的子系統若需要業務資料服務,此時誰來提供?
悟空預設不提供資料 API 服務,不同業務的資料服務由業務方的服務端提供。對應系統配置允許悟空跨域調用即可。
但是長久協作下來,慢慢暴露了開篇裡的問題。
輕 H5 業務能否節省相應配比的服務端和測試人力?
我們需要開發一個投票元件,隻有兩個選項 0 、 1 。通過該元件,我們能适配不同的投票場景。該元件隻需一個資料接口,例如:
http://api.vivo.com.cn/.../save.do?action=
投票元件示例圖
圖12 - 投票元件示例圖
傳統來說,前台的項目或元件,需要相應背景提供資料接口,才能完成功能閉環。
如果隻需提供一個接口,便要建立背景工程、申請庫表和部署服務等工作,相對來說會造成不小的人力成本和資源浪費。
悟空為了解決這個問題,提出悟空微前端的下一步的演進方向:
支援使用者線上可視化建立資料源,動态建立名額、次元等操作。實時動态生成資料源的 CRUD 接口。
該功能再結合悟空的資料平台能力,真實的做到了無服務介入自助生産的場景。為輕 H5 業務開發,解放了服務端、測試同學人力成本。
後續也會有詳細的專題文章為大家叙述該能力的探索與實作。
五、寫在最後
通過對悟空活動中台的介紹和 RSC 技術方案的講解實作,大家應該對悟空活動中台為何具備高度定制的能力有了初步的了解。
當我們把 H5 活動制品(元件、任務)和平台架構分離,那麼意味着開發者也正式成為我們中台的客戶。我們為開發者準備了線下開發環境,線上開發管理。通過研發基建、流程統一、産品化服務整體為活動開發提效,加速公司營銷内容生态的成長。
前端在活動中台的探索的征程并未結束,更多的挑戰等着我們,微元件的使用和場景還有很多難點,後面我們會圍繞 RSC 元件機制帶來以下的專題文章,為大家進行詳盡解析。
- 《悟空活動中台|微元件狀态管理(上)》
- 《悟空活動中台|微元件狀态管理(下)》
- 《悟空活動中台|微元件滿屏适配方案》
- 《悟空活動中台|微元件與uni-app的多端探索》
- ……
此外 vivo悟空中台研發團隊也會持續産出一系列圍繞活動産生中台解決方案系列專題,敬請期待。