本文首發於 vivo互聯網技術 微信公衆號
連接: https://mp.weixin.qq.com/s/Ka1pjJKuFwuVL8B-t7CwuA
做者:悟空中臺研發團隊
vivo大廈(南京)前端
隨着 vivo 互聯網用戶量級不斷增長,應用商店、官網商場、 遊戲中心和瀏覽器等 vivo 官方產品相繼進入存量用戶運營時代。在這種大背景下,營銷活動日益增多,傳統活動開發模式已經不能知足井噴式且多樣化的需求,項目開發和產品運營過程當中遇到種種困難:vue
1. 瀏覽器團隊開發的活動組件, 商城活動項目可否拿來複用?webpack
2. 遊戲中心團隊開發的 H5 頁面,會員活動項目可否拿來複用?git
3. H5 項目發佈週期較長,修改文案須要從新上線,可否把活動運營效率最大化?github
4. 輕 H5 業務可否節省相應配比的服務端和測試人力?web
5.各 BU 業務不一樣,活動後臺系統過多,研發效率和運營效率低下,致使數據孤島現象嚴重。vue-cli
6.研發輪子過多,問題場景沒有標準的解決方案,營銷活動常見問題沒有官方團隊進行統一收集沉澱。json
7.非業務 H5 需求,如招聘、節日、活動報名等,需使用外部的建站產品且數據安全風險高。api
8.……跨域
「悟空」,是咱們在攻克上述問題場景過程當中誕生的 「插拔化、可視化、一站式」的綜合活動中臺,目前已經是 vivo 活動項目首選的在線開發平臺、運營平臺。
取名爲 「悟空」,是承載了咱們的願景,在技術領域持續探索,修煉「七十二變」,不斷攻克企業活動項目運做過程當中的「九九八十一難」,取得「真經」。
截止目前,悟空接入 BU30+ 、上線 H5 頁面 7000+ 、營銷組件 20+ 、各品類模版 50+ 和營銷任務 60+ 。
如下是 vivo 各 BU 互聯網團隊在悟空上進行開發提交、上線運營的經典活動。
圖1 - 經典營銷活動截圖
舉個栗子:
vivo 商城團隊針對國慶節促銷活動開發了一款爆款 H5 ,其中【集卡】組件效果出衆。vivo 會員團隊但願雙十一也上線一款相似的 H5 活動頁,也指望具有【集卡】組件能力。
傳統方案:
會員團隊線下 clone 一份商城 H5 活動代碼,根據業務進行定製修改後上線。因【集卡】涉及運營策略線上配置,須要從新開發相應的活動配置功能。
痛點:
1. H5 代碼耦合業務嚴重,可維護性、可擴展性降低。
2. 單次開發的後臺功能,可能僅服務於本次活動,投入產出比低。
3. 針對活動上線後的效果,相關埋點須要從新設計。
4.若須要風控、數據分析、微信二次分享等活動配套能力,須要從新開發。
如何解決:
而悟空從組件/模版市場、任務中心、實時配置、活動配套,四個維度解決上述的痛點。
目前會員的運營同窗只須要在悟空模版市場中挑選本身須要的 H5 活動,進行業務化調整配置,發佈上線便可。如有定製需求,悟空提供在線開發能力,幫助研發快速產出業務組件。
下面是各功能維度的詳細介紹。
悟空活動中臺提供通用的營銷組件(抽獎、表單、答題、投票等),內容組件(文本、圖片、樓層、熱區、導航、輪播)等。
在此基礎上悟空提出組件市場概念:
各 BU 團隊在線提交定製的活動組件,悟空活動設計器提供實時拉取並渲染組件能力。同時支持版本切換、環境切換等能力。
此外組件可視化拼接成的 H5 活動頁後,可再次轉換成活動模版,供下次或其餘團隊使用。經過悟空提供的市場, H5 模版或組件很方便的在內部團隊中流轉,從而達到高複用、高保障的目的。
大多數的 H5 營銷組件或活動場景都會配套複雜的營銷任務和配置需求,也是衆多活動系統誕生的緣由。悟空爲了解決不一樣活動的配置後臺個性化問題,提出了任務中心的概念。
任務中心:悟空支持各 BU 團隊線下提交「管理後臺頁面」,無需發版便可線上自動拉取,用戶提交的頁面並渲染至頁面。經過該機制,悟空就具有了收容不一樣活動管理後臺的能力。
與傳統 iframe 嵌入子系統方案不一樣,悟空裝載的是離線代碼,符合悟空標準提交的製品,可「嚴絲合縫」熱加載至平臺框架。提供給用戶一致的交互體驗和使用習慣。
與組件概念相似,悟空提供通用任務中心(獎品配置中心、答題題目配置中心等)和私有任務中心概念。私有任務中心是各 BU 線下提交開發的活動配置頁面。
圖2 - 任務中心示例圖
如上圖,具有系統標籤的任務,是由悟空平臺分配給該 BU 的系統級任務。而非系統標籤,如:預定、直播等,則是當前登陸的 BU 業務方,自行開發上傳至平臺使用。(系統具有維護擴展自身的能力)
營銷活動支持配置實時生效,是精準營銷的基礎。悟空平臺提供的可視化活動設計器,機制上會將配置數據(頁面配置、組件配置、任務配置)與 H5 頁面分離。
用戶終端訪問 H5 活動時,會從雲端自動拉取在平臺配置的活動數據,渲染至頁面或活動組件中,達到代碼與數據動靜分離,且實時生效的能力。
圖3 - H5代碼與數據存取示意圖
流程如上圖,咱們發佈活動上線後,活動配置數據存儲在雲端, H5 代碼上線在 CDN ,經過該機制成功避免修改配置,須要再次上線發版的尷尬。
H5 核心設計器功能概覽
圖4 - 悟空H5設計器功能概覽圖
H5 活動可複用性高,定製化門檻低,線上時效性高是悟空活動中臺最基本的能力。在複雜的線上營銷場景下,做爲專業的活動中臺,只具有這些能力每每是不夠的。悟空針對營銷活動前中後時期,提供了常見的活動配套能力。例如:
素材庫:對接專業的素材網站,同時悟空提供在線壓縮,剪裁等圖片處理能力。
自動化埋點:組件加載器會自然包裝 H5 組件,頁面和組件默認具有點擊、曝光、操做時長等埋點能力。
微信分享:無需重複申請微信開放平臺,默認具有二次分享能力。
數據線索:悟空支持在線實時數據可視化分析(計算指標、指標分檔、多維度、數據透視圖表等能力)。
同時悟空中臺還集成藉助了公司內部其餘中臺能力(反垃圾、實驗、監控、風控等),多維度助力線上活動營銷。
悟空中臺產品架構圖
圖5 - 悟空中臺產品架構圖
開篇咱們提出了研發的痛點
研發輪子過多,問題場景沒有標準的解決方案,營銷活動常見問題沒有官方團隊進行統一收集沉澱。
悟空中臺如何服務於開發者?
悟空提供了 PaaS 平臺從開發環境、開發管理兩個維度,提高研發效率、研發體驗,幫助研發快速交付,作活動開發者最強大的後盾。
系統默認提供的組件和任務若不能知足各 BU 的業務需求, BU 就須要根據自身的業務場景去開發相應的套件(組件+任務)。這些套件可能只是業務場景不同,可是底層能力都是一致的。例如:
H5 投放場景多種多樣,相同交互觸發的方法各不相同,爲了針對對不一樣客戶端環境的適配, 悟空封裝了 @vivo/wukong-api 工具類庫。其中包含了強業務性的能力封裝,如:環境判斷、用戶信息獲取、不一樣環境的分享或下載能力喚起等等。
在此基礎上,悟空還提供了經常使用的研發級的能力封裝,例如 cookie 操做, fetch 能力, webp ,埋點操做等工具方法。幫助前端開發者精力聚焦在業務開發,提高活動組件開發效率。同時 wukong-api 也是一個內部開源的解決方案,支持按需加載,持續跟進最新最優的解決方案。
目前已提供 10+ 強業務能力封裝。15+ 基礎能力封裝。
示例代碼以下:
<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+ ,經過多個維度幫助開發便捷使用平臺能力,提高活動配置側開發效率。
圖6 - vscode插件截圖
同時悟空 vscode 插件集成了本地開發工做臺,支持跨設備配置同步,本地存儲組件組合關係等功能,開發者所見即所得。
下圖演示了本地開發配置發生變動,多端設備實時同步的效果。
圖7 - 本地開發平臺實時預覽演示
圖8 - 開發者手冊截圖
悟空提供了 PaaS 開發平臺,幫助研發管理開發產物,流程閉環,能力沉澱。
功能顯而易見,此處就不展開敘述了。
經過運營、研發兩個角度咱們敘述了悟空中臺能力。
那悟空 H5 設計器是如何作到平臺無需版本升級, H5 活動製品(組件、任務)線上自動裝載並直接使用?
其實這就是悟空研發團隊一直在探索的 workless 的工做流中的微前端架構方案的應用。
該方案主要特色以下:
經過上述的特色進行放大和縮小,就是悟空的任務中心、活動設計器 。
workless 是悟空目前致力打造的高效能綜合研發體系,目標是追求極致效果,解放生產力。目前 workless 在持續演進中,咱們相信這將是 vivo 前端最早進生產力的表明。後續將會有專題文章進行介紹,此處就不展開了。
workless ≈ 終端即開(展示層)+雲端一站式開發(研發層)+ 微前端架構(架構層)+ 數據心臟(數據驅動層)
本節將爲你們揭祕 vivo 微前端架構中的核心實現原理。
千里之行,始於足下。迴歸最原始的開發功能來敘述其原理:即前端組件不與平臺系統耦合,平臺具有從服務端拉取組件能力,並提供組件熱插拔式渲染接口。
從服務端拉取並渲染至頁面的組件,咱們稱之爲微組件,即 RSC(Remote Service Component)遠程服務組件。
圖9 - 個性化組件流轉示意圖
爲了知足線上運營策略能夠實時調整,悟空制定了 RSC 活動組件是由( UI + 配置)兩個子組件構成的規範。
├── code.vue # 編輯器中渲染的UI組件 ├── prop.vue # 屬性面板中渲染的配置組件 ├── setting.json # 存儲初始化基礎配置和業務配置 └── package.json # 依賴信息
同時設計器將會提供 UI 與配置組件間的數據共享機制,開發同窗能夠經過 setting.json 提早預設基礎設置或業務配置。機制上節省大量運營重複配置工做和學習組件使用的成本。
經過微組件的抽象和設計極大的縮短了活動頁的開發週期,運營同窗能夠從海量的組件和模板中選擇活動所需,經過可視化的系統配置,作到所見即所得,一鍵實時發佈活動頁觸達用戶。
同時微組件創建在不改變開發習慣基礎上,減小彼此之間的依賴,下降了開發和維護成本。基於 RSC 的理念開發出的微組件具備下列特性:
演示場景
圖10 - RSC組件機制加載演示圖
當用戶點擊或拖拽編輯器左側區域的組件到設計區域使用,設計器將根據組件的屬性(名稱、版本)發起 HTTP 組件請求(代碼、預設配置)。以後組件會熱加載到設計器中,預設配置也會隨之生效。
針對不一樣的環境系統,不斷的迭代升級認知和理念,咱們通過實踐發現 RSC 機制很好解決了組件和環境系統之間的協同和共享,達成了期待的結果:
運營:無需關心技術細節,可視化組合和配置,一鍵發佈直達用戶,線上實時調整運營策略,帶來更多商業價值。
產品:更快的上線速度,提高了服務質量和穩定性,承載更多商業價值。
開發:提高了迭代速度,提高了代碼質量,對新人友好,減小學習成本。
測試:經過可靠穩定的方案,減小重複測試工做量。
下面說明如何實現動態加載遠程組件。
示例:
<template> <div @click="test">click me | {{item}}</div> </template> <script> export default { data () { return { item: 1 } }, methods: { test () { this.item++ } } } </script>
注意:該SFC文件僅是組件入口,可正常引入其餘第三方組件或子組件。
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 的 <component> 組件的 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 組件加載機制實現的微前端架構,使前端業務系統與平臺分離。爲系統可第三方定製的能力,奠基了強大的基礎,也是一切可能的開始。
悟空微前端方案中的子系統若須要業務數據服務,此時誰來提供?
悟空默認不提供數據 API 服務,不一樣業務的數據服務由業務方的服務端提供。對應系統配置容許悟空跨域調用便可。
可是長久協做下來,慢慢暴露了開篇裏的問題。
輕 H5 業務可否節省相應配比的服務端和測試人力?
舉個栗子:
咱們須要開發一個投票組件,只有兩個選項 0 、 1 。經過該組件,咱們能適配不一樣的投票場景。該組件只需一個數據接口,例如:
http://api.vivo.com.cn/.../save.do?action=
投票組件示例圖
圖12 - 投票組件示例圖
傳統來講,前臺的項目或組件,須要相應後臺提供數據接口,才能完成功能閉環。
若是隻需提供一個接口,便要新建後臺工程、申請庫表和部署服務等工做,相對來講會形成不小的人力成本和資源浪費。
悟空爲了解決這個問題,提出悟空微前端的下一步的演進方向:
支持用戶在線可視化建立數據源,動態建立指標、維度等操做。實時動態生成數據源的 CRUD 接口。
該功能再結合悟空的數據平臺能力,真實的作到了無服務介入自助生產的場景。爲輕 H5 業務開發,解放了服務端、測試同窗人力成本。
後續也會有詳細的專題文章爲你們敘述該能力的探索與實現。
經過對悟空活動中臺的介紹和 RSC 技術方案的講解實現,你們應該對悟空活動中臺爲什麼具有高度定製的能力有了初步的瞭解。
當咱們把 H5 活動製品(組件、任務)和平臺框架分離,那麼意味着開發者也正式成爲咱們中臺的客戶。咱們爲開發者準備了線下開發環境,線上開發管理。經過研發基建、流程統1、產品化服務總體爲活動開發提效,加速公司營銷內容生態的成長。
前端在活動中臺的探索的征程並未結束,更多的挑戰等着咱們,微組件的使用和場景還有不少難點,後面咱們會圍繞 RSC 組件機制帶來如下的專題文章,爲你們進行詳盡解析。
此外 vivo悟空中臺研發團隊也會持續產出一系列圍繞活動產生中臺解決方案系列專題,敬請期待。
更多內容敬請關注 vivo 互聯網技術 微信公衆號
注:轉載文章請先與微信號:labs2020 聯繫。