活動(dòng)運(yùn)營(yíng)自動(dòng)化平臺(tái)實(shí)踐

人人貸活動(dòng)運(yùn)營(yíng)平臺(tái),是一個(gè)由人人貸大前端團(tuán)隊(duì)進(jìn)行開發(fā)和維護(hù),并用于自動(dòng)化、可視化構(gòu)建人人貸常規(guī)活動(dòng)的系統(tǒng)。本文將會(huì)分享"人人貸活動(dòng)運(yùn)營(yíng)平臺(tái)"的設(shè)計(jì)思想和部分技術(shù)實(shí)現(xiàn),希望對(duì)大家有所幫助。

一、背景

人人貸前端團(tuán)隊(duì)在過去的幾年里,接到了很多來自市場(chǎng)部門的活動(dòng)開發(fā)需求,這些活動(dòng)主要分為4大類:

  • LP活動(dòng)(Landing Page,引導(dǎo)頁(yè)),用于新人注冊(cè)的活動(dòng)頁(yè)面,基本都是一個(gè)注冊(cè)框 + 若干產(chǎn)品卡

  • MGM活動(dòng)(Members get member),用于好友間邀請(qǐng)拉新的活動(dòng)頁(yè)面,一般包括邀請(qǐng)記錄,邀請(qǐng)排行,分享等功能

  • 常規(guī)活動(dòng),一般包括抽獎(jiǎng)、產(chǎn)品卡、排行榜、分享等功能,用于促進(jìn)銷量

  • 特殊活動(dòng),一般是游戲頁(yè)面,相同的形式基本只會(huì)使用一次

1.1 活動(dòng)開發(fā)人力瓶頸和上線周期長(zhǎng)

一個(gè)普通的活動(dòng)(包括上述的LP活動(dòng)、MGM活動(dòng)、常規(guī)活動(dòng))開發(fā)時(shí)間得多久?

正常情況下,一個(gè)涉及到H5和PC兩端的簡(jiǎn)單活動(dòng),從產(chǎn)品提出需求開始,設(shè)計(jì)師需要2人*2天來完成設(shè)計(jì)工作,開發(fā)需要3人*2天(包括H5、PC端頁(yè)面、后端接口開發(fā)、接口聯(lián)調(diào)),測(cè)試需要2人*2天投入。

就這樣,從需求提出到頁(yè)面上線,需要一共投入14人*天的人力資源,得 7個(gè)工作日 才能完成。

而遇到比較緊急的活動(dòng)開發(fā)需求,上線周期需要壓縮,大家都得加班來完成。

另外,由于公司財(cái)務(wù)結(jié)算的特殊性,很多活動(dòng)的開始時(shí)間一般都是凌晨,開發(fā)、測(cè)試人員需要確認(rèn)活動(dòng)在線上運(yùn)行正常,才能下班。

1.2 活動(dòng)功能重復(fù)和反復(fù)修改

隨著公司業(yè)務(wù)的發(fā)展,活動(dòng)的開發(fā)需求越來越多。前端團(tuán)隊(duì)有三分之一的人力,長(zhǎng)期投入在活動(dòng)頁(yè)面的開發(fā)中。

事實(shí)上,咱們大部分的普通活動(dòng),功能并不復(fù)雜,而且大部分的功能比較重復(fù)。

這種功能重復(fù)性的頁(yè)面開發(fā),對(duì)于個(gè)人和團(tuán)隊(duì)的成長(zhǎng)來說,并沒有太多的價(jià)值。而且活動(dòng)上線后,經(jīng)常因?yàn)闃邮胶臀陌傅年P(guān)系,需要修改代碼,重新上線,導(dǎo)致團(tuán)隊(duì)成員普遍比較反感這種普通活動(dòng)的開發(fā)。

期間,團(tuán)隊(duì)也提出過組件化開發(fā)的方式,試圖將不同的功能模塊抽取出來,在不同的活動(dòng)頁(yè)面上進(jìn)行引用,以便節(jié)省開發(fā)時(shí)間。但由于設(shè)計(jì)方案的不確定性,以及不同開發(fā)人員參與,這種抽取的功能模塊復(fù)用性不太高,效果不是特別理想。并且不能解決樣式和文案修改,需要重新上線的問題。

總之,普通活動(dòng)的特點(diǎn)是:頁(yè)面功能大同小異、開發(fā)時(shí)間緊、下線快、技術(shù)成長(zhǎng)低。

隨著團(tuán)隊(duì)的技術(shù)體系日益成熟,我們終于騰出精力,試圖解決普通活動(dòng)開發(fā)中各項(xiàng)痛點(diǎn)。

二、人人貸活動(dòng)運(yùn)營(yíng)平臺(tái)

早在十幾年前,使用Dreamweaver就能可視化地搭建出前端靜態(tài)頁(yè)面。雖然Dreamweaver已經(jīng)成為過去式,但是可視化搭建的思想,卻被廣泛使用。

我們?cè)谡{(diào)研業(yè)界常用解決方案中發(fā)現(xiàn),很多公司都有自己的活動(dòng)運(yùn)營(yíng)系統(tǒng),可用來高效、可視化地配置活動(dòng),以及監(jiān)控活動(dòng)運(yùn)營(yíng)數(shù)據(jù)。我們希望采用這種活動(dòng)頁(yè)面可視化搭建的思想,由運(yùn)營(yíng)人員根據(jù)實(shí)際的運(yùn)營(yíng)需求,自行添加活動(dòng),并配置對(duì)應(yīng)的活動(dòng)頁(yè)面。

運(yùn)營(yíng)平臺(tái).png

2.1 整體框架

首先,簡(jiǎn)單介紹下人人貸前端的開發(fā)模式。

隨著 Node.js 的興起,我們從2016年開始,將原有基于 JSP 的前端開發(fā)模式,改造成使用 Node.js 做中間層,進(jìn)行前后端分離的模式。

活動(dòng)平臺(tái)整體設(shè)計(jì).png

人人貸前端使用的就是圖中所示的前后端分離的開發(fā)模式(圖片來自Web 研發(fā)模式演變),這種開發(fā)模式下,前后端的職責(zé)清晰。對(duì)于前端來說,兩個(gè)UI層各司其職:Front-end UI layer 處理瀏覽器層的展現(xiàn)邏輯,Back-end UI layer 可以用來處理路由、模板、數(shù)據(jù)獲取、cookie、服務(wù)器端渲染等。

在這種前后端開發(fā)模式下,整個(gè)人人貸活動(dòng)運(yùn)營(yíng)平臺(tái)的架構(gòu)圖如下:

活動(dòng)平臺(tái)整體設(shè)計(jì).png

整個(gè)運(yùn)營(yíng)平臺(tái)系統(tǒng)分為四大塊。

1、組件庫(kù)。運(yùn)營(yíng)平臺(tái)采用了業(yè)界通用的 組件化 方案,并且選用 React.js 作為組件的開發(fā)庫(kù)。下面會(huì)詳細(xì)介紹組件庫(kù)的拆分和開發(fā)模式。

2、前端系統(tǒng)。整個(gè)運(yùn)營(yíng)平臺(tái)包括 積木系統(tǒng)rrd-h5 、rrd-pc 三個(gè)前端系統(tǒng)。其中 積木系統(tǒng) 是運(yùn)營(yíng)創(chuàng)建、編輯、發(fā)布活動(dòng)頁(yè)面的系統(tǒng),屬于內(nèi)部系統(tǒng)。而rrd-h5rrd-pc 屬于面向用戶的Back-end UI layer,它們是基于生成的活動(dòng)配置數(shù)據(jù),對(duì)活動(dòng)頁(yè)面進(jìn)行渲染及提供異步接口,以供用戶訪問。

3、后端接口。在后臺(tái)服務(wù)上,由于活動(dòng)并不是特別復(fù)雜,我們有較大一部分接口,比如抽獎(jiǎng)、記錄收獲地址,只是做一些簡(jiǎn)單的存儲(chǔ)或者計(jì)算,就直接使用了Node.js實(shí)現(xiàn),也就是上圖中的node-market-service服務(wù)。而部分與公司主營(yíng)業(yè)務(wù)相關(guān)的接口,比如投資返現(xiàn)這類,還是直接使用后端提供的Java接口。

4、數(shù)據(jù)層。用于存儲(chǔ)活動(dòng)配置相關(guān)的數(shù)據(jù)以及部分運(yùn)營(yíng)數(shù)據(jù)。

2.2 組件庫(kù)

我們按照功能模塊,將往期的活動(dòng)頁(yè)面拆分成了不同的組件。

移動(dòng)端的邀請(qǐng)好友頁(yè)面 為例,這個(gè)頁(yè)面就包括:圖片組件(banner圖)、活動(dòng)規(guī)則組件、邀請(qǐng)記錄組件、戰(zhàn)隊(duì)排行榜組件、平臺(tái)增信組件和邀請(qǐng)好友按鈕組件等。

組件拆分完成后,我們就得到了一個(gè)組件庫(kù)。

為了便于對(duì)組件庫(kù)進(jìn)行管理,我們按照所屬的平臺(tái),將組件庫(kù)拆分為 jm-common 、jm-mobilejm-pc 三類,分別對(duì)應(yīng)兩端公用組件、H5組件、PC端組件。

如上文所述,我們的積木系統(tǒng)定位為 可視化編輯平臺(tái),在對(duì)組件進(jìn)行配置后,需要在編輯頁(yè)面實(shí)時(shí)展示。rrd-h5rrd-pc服務(wù)也需要根據(jù)頁(yè)面的配置數(shù)據(jù),對(duì)組件進(jìn)行渲染。

這三個(gè)系統(tǒng)中都需要使用組件庫(kù),為了方便組件的開發(fā)以及預(yù)覽,我們將組件庫(kù)的源碼集成到了積木系統(tǒng)的代碼倉(cāng)庫(kù)中。

積木系統(tǒng)通過項(xiàng)目代碼中的組件庫(kù)源碼來加載組件庫(kù),當(dāng)組件的代碼有修改,積木系統(tǒng)能通過重新編譯,刷新頁(yè)面并預(yù)覽到新的組件樣式。

組件庫(kù)還會(huì)通過開發(fā)環(huán)境判斷,會(huì)自動(dòng)在編輯系統(tǒng)中使用模擬數(shù)據(jù),方便了組件開發(fā)時(shí)的測(cè)試。

為了方便進(jìn)行版本管理和組件庫(kù)接入,當(dāng)組件開發(fā)完成后,我們會(huì)將組件庫(kù)發(fā)布在私有的npm倉(cāng)庫(kù)中,同時(shí)在rrd-h5rrd-pc中,更新對(duì)應(yīng)的組件庫(kù)版本號(hào),就能加載到新的組件。

2.3 活動(dòng)配置與頁(yè)面配置

在積木系統(tǒng)中,需要先創(chuàng)建活動(dòng),然后才能創(chuàng)建該活動(dòng)對(duì)應(yīng)的移動(dòng)端、PC端頁(yè)面,而不是直接創(chuàng)建活動(dòng)頁(yè)面。

這是因?yàn)楦鶕?jù)以往的運(yùn)營(yíng)經(jīng)驗(yàn),一個(gè)活動(dòng),是可以對(duì)應(yīng)多個(gè)推廣頁(yè)面(至少是H5和PC端兩個(gè)頁(yè)面),而這些推廣頁(yè)面需要共享一些活動(dòng)配置。

數(shù)據(jù)存儲(chǔ)上看,我們新建了 activity 、 pagepage_record 三張表用于存儲(chǔ)活動(dòng)配置、頁(yè)面配置和組件配置相關(guān)的數(shù)據(jù)。

  • activity 是活動(dòng)配置表,負(fù)責(zé)記錄活動(dòng)名,活動(dòng)的上下線時(shí)間,業(yè)務(wù)相關(guān)的活動(dòng)配置以及公用活動(dòng)配置等。其中公用組件配置,是指該活動(dòng)下的頁(yè)面,需要公用的組件配置項(xiàng)。比如領(lǐng)取優(yōu)惠券組件,會(huì)將優(yōu)惠券的金額、類型、批次等,放到公用組件配置中,這樣能有效避免在多個(gè)頁(yè)面的組件中分開進(jìn)行配置時(shí),配置出錯(cuò)或者不統(tǒng)一的情況。
公共配置.png
  • page 是頁(yè)面表。新建頁(yè)面時(shí),就會(huì)往該表中插入數(shù)據(jù)。信息會(huì)記錄頁(yè)面名,頁(yè)面所屬的活動(dòng)id,頁(yè)面所屬的平臺(tái)(移動(dòng)端 or PC端),發(fā)布時(shí)間等。需要注意的是,該表不會(huì)記錄具體的組件配置數(shù)據(jù)。這是為了將頁(yè)面數(shù)據(jù)與組件配置數(shù)據(jù)分離。但是頁(yè)面表會(huì)記錄線上頁(yè)面使用的 online_record_id ,用來關(guān)聯(lián)查詢線上頁(yè)面使用的組件數(shù)據(jù)。每次發(fā)布頁(yè)面后,我們會(huì)將最新的 online_record_id 更新到對(duì)應(yīng)頁(yè)面數(shù)據(jù)中。

  • page_record 是組件配置記錄表,主要負(fù)責(zé)記錄所屬的頁(yè)面id,具體的組件數(shù)據(jù),編輯人,發(fā)布時(shí)間等。在積木系統(tǒng)的活動(dòng)頁(yè)面編輯中,每一次保存頁(yè)面,都會(huì)在這個(gè)表中插入一條數(shù)據(jù),這樣方便查找編輯記錄,同時(shí)也方便回滾。

編輯頁(yè)面.png

2.4 組件的配置與配置數(shù)據(jù)解析

按照我們規(guī)劃的操作流程,運(yùn)營(yíng)同學(xué)在 積木系統(tǒng) 中新增活動(dòng),創(chuàng)建頁(yè)面后,需要給頁(yè)面添加組件,修改組件配置,配置完成后,保存頁(yè)面中的組件配置,最后發(fā)布頁(yè)面。

不同的組件,需要用到不同的配置項(xiàng)。那么我們?cè)撛趺丛?code>積木系統(tǒng)中,給不同的組件提供不同的配置項(xiàng)呢?

首先得介紹一下組件的開發(fā)模式。

在開發(fā)組件前,我們會(huì)提前和產(chǎn)品同事確認(rèn)該組件所需要的配置,包括組件樣式配置、組件文案配置以及組件業(yè)務(wù)屬性配置等。

開發(fā)組件時(shí),我們一般會(huì)添加三個(gè)文件。以圖片組件為例,我們添加image.jsx、image.scss、spec.js,分別是組件的具體實(shí)現(xiàn)代碼、組件樣式文件、組件的配置文件數(shù)據(jù)。

在配置某個(gè)組件時(shí),積木系統(tǒng)通過讀取該組件下的spec.js文件,提供不同的配置彈窗。

以下是圖片組件的spec.js文件內(nèi)容:

import Image from './image.js';

export default {
    Component: Image,
    type: Image.type,
    _name: '圖片',    //組件列表使用的名稱
    _platform: 'common', //該組件屬于公共組件
    _acceptChild: false, //是否允許嵌套其他組件
    _dataSchema: {  //組件配置項(xiàng)需要的JSON Schema
        type: "object",
        required: ["src"],
        properties: {
            src: {
                type: "string",
                title: "請(qǐng)?zhí)顚憟D片地址",
            },
            alt: {
                type: "string",
                title: "圖片無法加載時(shí)的文案",
            },
            title: {
                type: "string",
                title: "鼠標(biāo)移到圖片上的提示文案",
            }
        }
    },
    data: {  //默認(rèn)數(shù)據(jù)
        src: 'https://www.we.com/cms/5864b0d6a24d131067ef7956/jimu/default-img.jpg',
        alt: '',
        title: ''
    },
    style: {  //樣式配置項(xiàng)
        width: '',
        height: '',
        position: 'static',
        display: 'block',
        margin: '',
        padding: ''
    },
    _defaultStyle: {  //默認(rèn)樣式
        mobile: {
            width: '100%'
        },
        pc: {
            maxWidth: '1080px',
            height: 'auto'
        }
    }
}

以上的配置文件中,有部分屬性是以下劃線_開頭,這部分屬性屬于積木系統(tǒng)專用的屬性,會(huì)在給前端頁(yè)面?zhèn)鬟f組件配置數(shù)據(jù)時(shí),過濾掉這些專屬屬性,避免配置數(shù)據(jù)過多,也避免部分內(nèi)部數(shù)據(jù)泄露。

一個(gè)活動(dòng)頁(yè)面,一般會(huì)添加多個(gè)組件,而且組件間還可能存在嵌套關(guān)系,頁(yè)面上的組件配置數(shù)據(jù)如何組織、解析,也是必須要解決的問題。

我們這樣定義頁(yè)面上的組件數(shù)據(jù):

{
    "dataMap":{
        "id1":{
            "cid":"id1", // 組件id
            "type":"pc_component_1", //組件類型
            "name":"組件一", //組件名
            "platform":"pc", //組件所屬的平臺(tái)
            "acceptChild":true, //是否能添加子組件
            "data":{},//組件數(shù)據(jù)
            "style":{},//組件樣式
            "childs":['id3'] //子組件id
        },
        "id2":{
            "cid":"id2", // 組件id
            "type":"pc_component_2", //組件類型
            "name":"組件二", //組件名
            "platform":"pc", //組件所屬的平臺(tái)
            "acceptChild":false, //是否能添加子組件
            "data":{},//組件數(shù)據(jù)
            "style":{},//組件樣式
            "childs":[] //子組件id
        },
        "id3":{
            "cid":"id3", // 組件id
            "type":"pc_component_3", //組件類型
            "name":"組件三", //組件名
            "platform":"pc", //組件所屬的平臺(tái)
            "acceptChild":false, //是否能添加子組件
            "data":{},//組件數(shù)據(jù)
            "style":{},//組件樣式
            "childs":[] //子組件id
        },
        ...
    },
    "main": ["id1","id2"] //第一層級(jí)的組件id
}

頁(yè)面的組件配置數(shù)據(jù)中有dataMapchilds兩個(gè)字段。

在需要通過這些配置的組件數(shù)據(jù)來渲染頁(yè)面時(shí),首先使用配置項(xiàng)中的 main 字段獲取所有第一層級(jí)子組件的id,然后在dataMap中,根據(jù)組件id來查找對(duì)應(yīng)的具體配置,進(jìn)行渲染。

如果某個(gè)組件配置數(shù)據(jù)中的 childs 字段不為空數(shù)組,就意味該組件中嵌套了其他組件,就繼續(xù)通過 childs 中的id值,在dataMap中查找對(duì)應(yīng)組件的配置數(shù)據(jù),并渲染子組件。

還有,我們之前提到過的公共組件配置數(shù)據(jù),在渲染組件前,也會(huì)和dataMap中的對(duì)應(yīng)組件配置進(jìn)行數(shù)據(jù)合并。

2.5 rrd-h5 & rrd-pc 中如何渲染?

那么積木系統(tǒng)中生成的頁(yè)面組件配置數(shù)據(jù),是如何在 rrd-h5 和 rrd-pc 中,進(jìn)行渲染的呢?

其實(shí),目前主流的組件渲染方式有三種:

  • 加載所有的組件定義,然后通過活動(dòng)id和頁(yè)面id獲取頁(yè)面的配置數(shù)據(jù),進(jìn)而動(dòng)態(tài)渲染出頁(yè)面

  • 先通過活動(dòng)id和頁(yè)面id獲取頁(yè)面的配置數(shù)據(jù),然后按需加載組件,渲染出頁(yè)面

  • 服務(wù)器通過頁(yè)面配置和組件定義,直接在發(fā)布時(shí)生成靜態(tài)頁(yè)面

不同的方案各有優(yōu)劣。rrd-h5 和 rrd-pc 系統(tǒng)中,我們使用了第一種方案來進(jìn)行渲染:我們的線上頁(yè)面模板,會(huì)默認(rèn)加載所有的組件。

rrd-h5為例,我們會(huì)在活動(dòng)頁(yè)面模板中引用所有的 jm-common(公共組件) 和jm-mobile組件庫(kù)代碼。然后使用活動(dòng)頁(yè)面URL中攜帶的活動(dòng)id和頁(yè)面id,通過 node-market-service 服務(wù)獲取活動(dòng)數(shù)據(jù)和頁(yè)面組件配置數(shù)據(jù)。之后就按上述 2.4 組件的配置與配置數(shù)據(jù)解析 中介紹的組件配置數(shù)據(jù)解析方式,渲染出整個(gè)活動(dòng)頁(yè)面。

就這樣,用戶就能看到配置的活動(dòng)頁(yè)面。

三、TODO

目前的運(yùn)營(yíng)平臺(tái),其實(shí)主要以編輯系統(tǒng)為主,并提供了少量的查詢功能。

我們未來會(huì)繼續(xù)迭代,將繼續(xù)集成運(yùn)營(yíng)監(jiān)控、報(bào)警,自動(dòng)生成活動(dòng)數(shù)據(jù)報(bào)表等功能。

同時(shí),為了提高頁(yè)面加載速度,考慮到活動(dòng)頁(yè)面上圖片較多、且切圖普遍較大的問題,我們即將在rrd-h5、rrd-pc中引入 webp 、http2、service-worker等。

四、總結(jié)

人人貸活動(dòng)運(yùn)營(yíng)平臺(tái)在2018年9月上線后,效果極其明顯:

  • 活動(dòng)運(yùn)營(yíng)平臺(tái),能夠自動(dòng)化、可視化地創(chuàng)建活動(dòng)及活動(dòng)頁(yè)面。

  • 活動(dòng)運(yùn)營(yíng)平臺(tái),讓活動(dòng)的上線周期,從以往的6天,降低到了2天。設(shè)計(jì)師切完圖,運(yùn)營(yíng)人員就能配置上線。

  • 活動(dòng)可配置上線和下線時(shí)間,開發(fā)人員基本不會(huì)因?yàn)榛顒?dòng)的開發(fā)而加班。

  • 運(yùn)營(yíng)平臺(tái)規(guī)范了活動(dòng)功能的形式,同時(shí),設(shè)計(jì)師也會(huì)在組件的可編輯范圍內(nèi)進(jìn)行設(shè)計(jì),組件可配置項(xiàng)豐富。

  • 活動(dòng)頁(yè)面的樣式和文案的修改,不再需要重新上線。

  • 釋放出的前、后端開發(fā)人員,能將更多的精力投入到對(duì)新技術(shù)的研究。

由于篇幅有限,活動(dòng)運(yùn)營(yíng)平臺(tái)的很多具體實(shí)現(xiàn)細(xì)節(jié)并沒有過多描述。如果大家有感興趣的問題,可以留言進(jìn)行交流。

最后,歡迎大家star我們的人人貸大前端團(tuán)隊(duì)博客,所有的文章還會(huì)同步更新到知乎專欄掘金賬號(hào),我們每周都會(huì)分享幾篇高質(zhì)量的大前端技術(shù)文章。

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容