日本电影一区二区_日本va欧美va精品发布_日本黄h兄妹h动漫一区二区三区_日本欧美黄色

微前端在美團外賣的實踐(美團微前端架構)

微前端是微服務理念在前端的應用。之前給大家介紹過微前端在美團HR系統(tǒng)和美團閃購的實踐文章。今天的文章來自美團外賣廣告團隊,他們參考業(yè)界優(yōu)秀方案,同時也深度結合了廣告端實際業(yè)務的情況,提出了基于React的中心路由基座式微前端方案。

微前端在美團外賣的實踐(美團微前端架構)

背景

微前端是一種利用微件拆分來達到工程拆分治理的方案,可以解決工程膨脹、開發(fā)維護困難等問題。隨著前端業(yè)務場景越來越復雜,微前端這個概念最近被提起得越來越多,業(yè)界也有很多團隊開始探索實踐并在業(yè)務中進行了落地。可以看到,很多團隊也遇到了各種各樣的問題,但各自也都有著不同的處理方案。誠然,任何技術的實現(xiàn)都要依托業(yè)務場景才會變得有意義,所以在闡述美團外賣廣告團隊的微前端實踐之前,我們先來簡單介紹一下外賣商家廣告端的業(yè)務形態(tài)。目前,我們開發(fā)和維護的系統(tǒng)主要包括三端:

  • PC系統(tǒng):單門店投放系統(tǒng)PC端
  • H5系統(tǒng):單門店投放系統(tǒng)H5端
  • KA系統(tǒng):多門店投放系統(tǒng)PC端

微前端在美團外賣的實踐(美團微前端架構)

如上圖所示,原始解決方案的三端由各自獨立開發(fā)和維護,各自包含所有的業(yè)務線,而我們的業(yè)務開發(fā)情況是:

  • PC端和H5端相同業(yè)務線的基本業(yè)務邏輯一致,UI差異大。
  • PC端和KA端相同業(yè)務線的部分業(yè)務邏輯一致,UI差異小。

在這種特殊的業(yè)務場景下,就會出現(xiàn)一個有關開發(fā)效率的抉擇問題。即我們希望能復用的部分只開發(fā)一次,而不是三次。那么接下來,就有兩個問題擺在我們面前:

  • 如何進行物理層面的復用(不同端的代碼在不同地址的Git倉庫)。
  • 如何進行邏輯層面的復用(不同端的相同邏輯如何使用一份代碼進行抽象)。

我們這里重點看一下物理層面的復用,即:如何在物理空間上使得各自獨立的三端系統(tǒng)(不同倉庫)引入我們的復用層?我們嘗試了NPM包、Git subtree等類“共享文件”的方式后發(fā)現(xiàn),最有效率的復用方式是把三個系統(tǒng)放在一個倉庫里,去消除物理空間上的隔離,而不是去連接不同的物理空間。當然,我們?nèi)讼到y(tǒng)的技術棧是一致的,所以就進行了如下圖的改造:

微前端在美團外賣的實踐(美團微前端架構)

可以看到,當我們把三端系統(tǒng)放在一個倉庫中時,通過common文件夾提供了物理層面可復用的土壤,不再需要“共享文件”式地進行頻繁地拉取操作,直接引用復用即可。不過,在帶來物理層面復用效率提升的同時,也加速了整個工程出現(xiàn)了爆炸式發(fā)展的問題,隨著產(chǎn)品線從最初的幾個發(fā)展到現(xiàn)在的幾十個之多,工程管理成本也在迅速增長。具體來說,包括如下四個方面:

  • 新業(yè)務線產(chǎn)品急速增加,同時為了保證三端系統(tǒng)復用效率的最大化,把文件放入同一倉庫管理,導致文件數(shù)量增長極快,管理及協(xié)同開發(fā)難度也在不斷加大。
  • 文件越來越多,文件結構越不受控制,業(yè)務開發(fā)尋址變得越來越困難。
  • 文件越來越多,開發(fā)、構建、部署速度變得越來越慢,開發(fā)體驗在持續(xù)下降。
  • 不同業(yè)務線間沒有物理隔離,出現(xiàn)了跨業(yè)務線互相引用混亂,例如A業(yè)務線出現(xiàn)了B業(yè)務線名字的組件。

如下圖所示,具體地說明了原有架構存在的問題。為了要解決這些問題,我們意識到需要拆分這些應用,即進行工程優(yōu)化的常規(guī)手段進行“分治”。那么要怎么拆呢?自然而然地我們就想到了微前端的概念。也從這個概念出發(fā),我們參考業(yè)界優(yōu)秀方案,同時也深度結合了廣告端實際業(yè)務的開發(fā)情況,對現(xiàn)有工程進行了微前端的實踐與落地。

微前端在美團外賣的實踐(美團微前端架構)

需求分析

結合現(xiàn)有工程的狀況,我們進行了深度的分析。不過,在進行微前端方案確定前,我們先確定了需求點及期望收益,如下表所示:

微前端在美團外賣的實踐(美團微前端架構)

方案選擇

經(jīng)過以上的需求分析,我們調研了業(yè)界及公司周邊的微前端方案,并總結了以下幾種方案以及它們各自主要的特點:

  • NPM式:子工程以NPM包的形式發(fā)布源碼;打包構建發(fā)布還是由基座工程管理,打包時集成。
  • iframe式:子工程可以使用不同技術棧;子工程之間完全獨立,無任何依賴;基座工程和子工程需要建立通信機制;無單頁應用體驗;路由地址管理困難。
  • 通用中心路由基座式:子工程可以使用不同技術棧;子工程之間完全獨立,無任何依賴;統(tǒng)一由基座工程進行管理,按照DOM節(jié)點的注冊、掛載、卸載來完成。
  • 特定中心路由基座式:子業(yè)務線之間使用相同技術棧;基座工程和子工程可以單獨開發(fā)單獨部署;子工程有能力復用基座工程的公共基建。

通過對各個方案特點進行分析,我們將重點關注項進行了對比,如下表所示:

微前端在美團外賣的實踐(美團微前端架構)

經(jīng)過上面的調研對比之后,我們確定采用了特定中心路由基座式的開發(fā)方案,并命名為:基于React的中心路由基座式微前端。這種方案的優(yōu)點包括以下幾個方面:

  • 保證技術棧統(tǒng)一在React。
  • 子工程之間開發(fā)互相獨立,互不影響。
  • 子工程可單獨打包、單獨部署上線。
  • 子工程有能力復用基座工程的公共基建。
  • 保持單頁應用的體驗,子工程之間切換不刷新。
  • 改造成本低,對現(xiàn)有工程侵入度較低,業(yè)務線遷移成本也較低。
  • 開發(fā)子工程和原有開發(fā)模式基本沒有不同,開發(fā)人員學習成本較低。

微前端實踐概覽

通過對方案的分析及技術方向上的梳理,我們確定了微前端的整體方案,如下圖所示:

微前端在美團外賣的實踐(美團微前端架構)

可以看到,整個方案非常簡單明確,即按照業(yè)務線進行了路由級別的拆分。整個系統(tǒng)可分為兩個部分:

  • 基座工程:用于管理子工程的路由切換、注冊子工程的路由和全局Store層、提供全局庫和復用層。
  • 子工程:用于開發(fā)子業(yè)務線業(yè)務代碼,一個子工程對應一個子業(yè)務線,并且包含三端代碼和復用層代碼。

基座工程和子工程聯(lián)系起來的橋梁則是子工程的入口文件地址和路由地址的映射信息。這些映射信息可以讓基座工程準確地發(fā)現(xiàn)子工程資源的路徑從而進行加載。

微前端架構下的業(yè)務變化

經(jīng)過微前端實踐的改造,我們的業(yè)務在結構上發(fā)生了如下的變化:

微前端在美團外賣的實踐(美團微前端架構)

如上圖所示,我們進行了微前端式的業(yè)務線拆分:

  • 原有的PC系統(tǒng)、H5系統(tǒng)、KA系統(tǒng)分別改造成了PC基座系統(tǒng)、H5基座系統(tǒng)和KA基座系統(tǒng)。
  • 原有的子業(yè)務線被拆分成了單獨的子倉庫,成為了業(yè)務線子工程(上圖中6個黑框豎列)。
  • 業(yè)務線子工程分別包含PC端、H5端、KA端以及該業(yè)務線復用層的代碼(上圖中3個純色背景橫列)。

新的拆分使得子工程能夠按照業(yè)務線進行劃分,獨立維護。在解決復用層的同時保證了子工程大小可控,即子工程只有單個業(yè)務線的代碼。而單個業(yè)務線的復雜度并不高,也降低了工程維護的復雜度。

采用微前端拆分的方案,使得我們的業(yè)務不僅在縱向上保有了復用的能力,更重要的是擁有了橫向擴展的能力,無論產(chǎn)品業(yè)務線如何膨脹,我們都可以更輕松地應對。那么為了實現(xiàn)以上的能力,我們做了哪些工作呢?下文我們會詳細進行說明。

基于React技術棧的中心路由基座式微前端

微前端拆分的方案,我們命名為:基于React技術棧的中心路由基座式微前端。在具體實現(xiàn)上,我們會分為動態(tài)化方案路由配置信息設計、子工程接口設計復用方案設計和流程方案設計等幾個模塊來逐一進行說明。

動態(tài)化方案

首先,我們需要路由的管理方案,使得子工程之間有能力互通切換。其次,我們需要Store層的方案,讓子工程有能力使用全局Store。并且,我們還需要CSS的加載方案,來加載子工程的樣式布局。下面來詳細說明這三個方案。

動態(tài)路由

動態(tài)路由方案是想要進行路由級別的拆分,首先我們要確定用什么來管理路由?很多實現(xiàn)方案傾向于使用特制路由來管理模塊。例如開源框架Single-Spa,實現(xiàn)了自己的一套路由監(jiān)聽來切換子工程,并且需要子工程實現(xiàn)特定的注冊、掛載、卸載等接口來完成子工程和基座工程的動態(tài)對接,還需要特定的模塊管理系統(tǒng),例如systemjs來輔助完成這一過程。毋庸置疑,這對我們原有工程的改造成本很大,還需要添加額外庫,進而造成包體積大小上的開銷。并且子工程的開發(fā)者需要熟悉這些特定的接口,學習成本也比較高。顯然,這對于我們的業(yè)務場景和需求來說很不劃算。

那么,我們選擇什么來做路由管理呢?最終我們使用了React-Router,這樣能夠保持我們原來的技術棧不變,同時對于工程的侵入也是最低,幾乎可以忽略不計。此外,React-Router完全可以滿足我們的需求,而且自動會幫助我們管理頁面的加載與卸載,而不是每次切換路由都重新初始化整個子應用,所以在加載速度體驗上也是最優(yōu)的,跟單頁應用的體驗一致。

在實現(xiàn)上也很簡單,如下圖所示:

微前端在美團外賣的實踐(美團微前端架構)

上面這個流程圖,展示了我們在基座工程中切換到子工程路由時,加載子工程并進行展示的過程。這里的重點步驟是加載子工程入口文件,并動態(tài)注冊子工程路由的過程。由于我們使用的是React-Router,顯然要使用其提供的動態(tài)能力來完成。這一過程也非常輕量,由于React-Router從版本4開始有了“破壞級”的升級,于是我們就調研了兩種方式進行動態(tài)加載路由(目前我們使用的是React-Router版本5),如下表所示:

微前端在美團外賣的實踐(美團微前端架構)

React-Router版本3中,實現(xiàn)的基本代碼思路如下:

// react-router V3 用于接收子工程的路由export default () => (    <Route        path="/subapp"        getChildRoutes={(location: any, cb: any) => {            const { pathname } = location.location;            // 取路徑中標識子工程前綴的部分, 例如 '/subapp/xxx/index' 其中xxx即路由唯一前綴            const id = pathname.split('/')[2];            const subappModule = (subAppMapInfo as any)[id];            if (subappModule) {                if (subappRoutes[id]) {                    // 如果已經(jīng)加載過該子工程的模塊,則不再加載,直接取緩存的routes                    cb(null, [subappRoutes[id]]);                    return;                }                // 如果能匹配上前綴則加載相應子工程模塊                currentPrefix = id;                loadAsyncSubapp(subappModule.js)                    .then(() => {                        // 加載子工程完成                        cb(null, [subappRoutes[id]]);                    })                    .catch(() => {                        // 如果加載失敗                        console.log('loading failed');                    });            } else {                // 可以重定向到首頁去                goBackToIndex();            }        }}    />);

而在React-Router版本4中,實現(xiàn)的基本代碼思路如下:

export const AyncComponent: React.FC<{ hotReload?: number; } & RouteComponentProps> = ({ location, hotReload }) => {    // 子工程資源是否加載完成    const [ayncLoaded, setAyncLoaded] = useState(false);    // 子工程url配置信息是否加載完成    const [subAppMapInfoLoaded, setSubAppMapInfoLoaded] = useState(false);    const [ayncComponent, setAyncComponent] = useState(null);    const { pathname } = location;    // 取路徑中標識子工程前綴的部分, 例如 '/subapp/xxx/index' 其中xxx即路由唯一前綴    const id = pathname.split('/')[2];    useEffect(() => {        // 如果沒有子工程配置信息, 則請求        if (!subAppMapInfoLoaded) {            fetchSubappUrlPath(id).then((data) => {                subAppMapInfo = data;                setSubAppMapInfoLoaded(true);            }).catch((url: any) => {                // 失敗處理                goBackToIndex();            });            return;        }        const subappModule = (subAppMapInfo as any)[id];        if (subappModule) {            if (subappRoutes[id]) {                // 如果已經(jīng)加載過該子工程的模塊,則不再加載,直接取緩存的routes                setAyncLoaded(true);                setAyncComponent(subappRoutes[id]);                return;            }            // 如果能匹配上前綴則加載相應子工程模塊            // 如果請求成功,則觸發(fā)JSONP鉤子window.wmadSubapp            currentPrefix = id;            setAyncLoaded(false);            const jsUrl = subappModule.js;            loadAsyncSubapp(jsUrl)                .then(() => {                    // 加載子工程完成                    setAyncComponent(subappRoutes[id]);                    setAyncLoaded(true);                })                .catch((urlList) => {                    // 如果加載失敗                    setAyncLoaded(false);                    console.log('loading failed...');                 });        } else {            // 可以重定向到首頁去            goBackToIndex();        }    }, [id, subAppMapInfoLoaded, hotReload]);    return ayncLoaded ? ayncComponent : null;};

可以看到,這種方式實現(xiàn)起來非常簡單,不需要額外依賴,同時滿足了我們“拆分”的訴求。

動態(tài)Store

對于Store層,我們原工程使用的是Redux,子工程通過路由動態(tài)注冊進來天然就可以訪問到全局Store,所以對于Store的訪問能夠自動支持。那么,如果子工程想要注冊自己的全局Store該怎么辦呢?而且我們還用了redux-saga來作為異步處理方案。redux-saga如何動態(tài)注冊呢?還是利用它們各自的API就可以達到我們的目的?從下圖中可以看到,支持動態(tài)Store也是花費很小的改造成本就可以完成。

微前端在美團外賣的實踐(美團微前端架構)

動態(tài)CSS

同樣的對應子工程的樣式布局,我們也需要通過某種途徑加載到基座工程中來。這個很自然地用異步加載CSS文件通過style標簽注入來完成,不過這里需要注意兩個問題:

一個問題是,加載子工程的JS入口文件和CSS文件可以同時發(fā)起請求,但是需要保證CSS文件加載完成后再進行JS入口文件的路由注冊。因為如果路由先注冊了頁面就會顯示出來,如果這時CSS文件還沒有加載完畢,就會出現(xiàn)頁面樣式閃動的問題。我們通過先加載CSS再加載JS的策略來避免這個問題的發(fā)生。

另一個問題是,怎么保證子工程的CSS不會和其他子工程沖突。我們利用PostCSS插件在編譯子工程時,按照分配給子工程的唯一業(yè)務線標識,為每一組CSS規(guī)則生成了命名空間來解決這個問題。而子業(yè)務線開發(fā)者是沒有感知的,可以沒有“心智負擔”地書寫子工程的樣式。

路由配置信息方案

在動態(tài)加載方案確定之后,基座工程怎么才能知道子工程的資源路徑,進而加載對應的JS和CSS資源呢?我們需要一組映射信息。如下圖所示,業(yè)務線唯一標識為Key,相應的靜態(tài)資源地址為Value。這樣的話,當基座工程切換到子工程時就可以拉取這個配置信息,在路由切換時準確地找到對應的子工程,進而進行后續(xù)的資源加載過程。這里可能會遇到的一個問題,即如果JS和CSS過大,是否能進行拆分?

根據(jù)我們業(yè)務的實際情況,目前靜態(tài)資源的大小是可控的,無需注冊多個,單一入口地址完全能夠滿足我們的業(yè)務需求,并且由于我們的改造完全基于現(xiàn)有技術棧。如果業(yè)務很復雜,完全可以在子工程中通過webpack的動態(tài)import進行路由懶加載,也就是說,子工程完全可以按照路由再次切分成chunks來減少JS的包體積。至于CSS本身就很小,長期也不會有進行切分的需要。

微前端在美團外賣的實踐(美團微前端架構)

子工程接口方案

子工程需要暴露它要注冊給基座工程的對象,來進行基座工程加載子工程的過程。在子工程入口文件中定義registerApp來傳遞注冊的對象,主要代碼如下:

import reducers from 'common/store/labor/reducer';import sagas from 'common/store/labor/saga';import routes from './routes/index';function registerApp(dep: any = {}): any {    return {        routes, // 子工程路由組件        reducers, // 子工程Redux的reducer        sagas, // 子工程的Redux副作用處理saga    };}export default registerApp

我們這里暴露了子工程的三個對象:這里最重要的就是routes路由組件,就是在寫React-Router(版本4及以上)的路由。子工程開發(fā)者只需要配置routes對象即可,沒有任何學習成本,其代碼如下:

/** * 子工程路由注冊說明 * 如注冊的路由如下: * path: 'index' * 路由前綴會被追加上,路由前綴規(guī)則見變量urlPrefix * 在主工程的訪問路勁為:/subapp/${工程注冊名稱}/index */const urlPrefix = `/subapp/${microConfig.name}/`;const routes = [    {        path: 'index',        component: IndexPage,    },];const AppRoutes = () => (    <Switch>        {            routes.map(item => (                <Route                    key={item.path}                    exact                    path={`${urlPrefix}${item.path}`}                    component={item.component}                />            ))        }        <Redirect to="/" />    </Switch>);export default AppRoutes;

除了上方的routes對象,還剩下兩個接口對象是:reducers和sagas,用于動態(tài)注冊全局Store相關的數(shù)據(jù)和副作用處理。這兩個接口我們在子工程中暫時沒有開放,因為按照業(yè)務線拆分過后,由于業(yè)務線間獨立性很強,全局Store的意義就不大了。我們希望子工程可以自行處理自己的Store,即每個業(yè)務線維護自己的Store,這里就不再展開進行說明了。

復用方案

基座工程除了路由管理之外,還作為共享層共享全局的基建,例如框架基本庫、業(yè)務組件等。這樣做的目的是,子業(yè)務線間如果有相同的依賴,切換的時候就不會出現(xiàn)重復加載的問題。例如下面的代碼,我們把React相關庫都以全局的方式導出,而子工程加載的時候就會以external的形式加載這些庫,這樣子工程的開發(fā)者不需要額外的第三方模塊加載器,直接引用即可,和平時開發(fā)React應用一致,沒有任何學習成本。而和各個業(yè)務都相關的公用組件等,我們會放到wmadMicro的全局命名空間下進行管理。主要代碼如下:

import * as React from 'react';import * as ReactDOM from 'react-dom';import * as ReactRouterDOM from 'react-router-dom';import * as Axios from 'axios';import * as History from 'history';import * as ReactRedux from 'react-redux';import * as Immutable from 'immutable';import * as ReduxSagaEffects from 'redux-saga/effects';import Echarts from 'echarts';import ReactSlick from 'react-slick';function registerGlobal(root: any, deps: any) {    Object.keys(deps).forEach((key) => {        root[key] = deps[key];    });}registerGlobal(window, {    // 在這里注冊暴露給子工程的全局變量    React,    ReactDOM,    ReactRouterDOM,    Axios,    History,    ReactRedux,    Immutable,    ReduxSagaEffects,    Echarts,    ReactSlick,});export default registerGlobal;

流程方案

在確定了程序拆分運行的整體銜接之后,我們還要確定開發(fā)方案、部署方案以及回滾方案。我們?nèi)绾伍_始開發(fā)一個子工程?以及我們?nèi)绾尾渴鹞覀兊淖庸こ蹋?/p>

開發(fā)流程

有兩種開發(fā)方案可以滿足獨立開發(fā)的目的:第一種是提供一個基座工程的Dev環(huán)境,子工程在本地啟動后在Dev環(huán)境進行開發(fā),這種開發(fā)方式要求有一套基座工程的更新機制,例如基座工程更新后要同步部署到Dev環(huán)境。第二種是子工程開發(fā)者拉取基座工程到本地并啟動本地開發(fā)環(huán)境,然后拉取子工程到本地,再啟動子工程本地開發(fā)環(huán)境進行開發(fā),這種開發(fā)方式是目前我們使用的方式。如下圖所示,我們提供了子工程腳手架來快速創(chuàng)建子工程,開發(fā)者無需做任何配置和額外學習成本,就可以像開發(fā)React應用一樣進行開發(fā)。

微前端在美團外賣的實踐(美團微前端架構)

熱更新

在開發(fā)過程中,我們希望我們的開發(fā)體驗和開發(fā)單頁應用的體驗一致,也要支持熱更新。由于我們的拆分,實際上有兩個服務,即基座和子工程,所以我們以上圖的方式完成了熱更新的支持:在子工程的module.hot中通過再次觸發(fā)基座工程中的JSONP鉤子來通知基座工程,來再次觸發(fā)renderApp達到子工程更新代碼則頁面熱刷新的目的。主要代碼如下:

// 在子工程入口文件import routes from './routes/index';function registerApp(dep: any = {}): any {    return {        routes,    };}if ((module as any).hot) {    (module as any).hot.accept('./routes/index', (): any => {        window.wmadSubapp(registerApp, true); // 支持子工程熱加載的信息傳遞    });}export default registerApp

Mock數(shù)據(jù)

子工程目前Mock數(shù)據(jù)的方式有三種:一是在基座本地Mock,這種Mock方式天然支持,因為基座工程基于外賣工程化Nine腳手架進行開發(fā),本身支持本地Mock。二是支持子工程本地Mock。三是使用公共Mock服務YAPI。目前子工程開發(fā)的Mock功能結合第一種方式和第三種方式進行。

部署方案

最后是部署方案,我們達成了獨立部署上線的目的,即子工程發(fā)布不需要基座工程的參與。之前所有子業(yè)務線都在一個工程中,打包速度隨著業(yè)務線的膨脹變得越來越慢,而如下的方案使得子工程的開發(fā)和部署完全獨立,單個業(yè)務線的打包速度會非???,從之前的分鐘級別降到了秒級別。如下圖所示,子工程部署只需要把子工程打包,并在上傳CDN之后,把配置信息更新即可,因為配置信息中有子工程新的資源地址,這樣就達到了發(fā)布上線的目的。

微前端在美團外賣的實踐(美團微前端架構)

整個部署過程我們是托管到Talos(美團內(nèi)部自研的部署工具)上的,配置信息我們是托管到Portm(美團內(nèi)部自研的文件存儲)上的(通過我們開發(fā)的Talos的插件UpdatePubInfo-To-Portm來更新我們的配置信息)。在靜態(tài)資源上傳到CDN之后,就可以更新配置信息,供主工程調用,也就完成了子工程上線的過程。利用美團現(xiàn)有服務,我們很迅速地完成了子工程單獨部署上線的整個流程。

微前端在美團外賣的實踐(美團微前端架構)

回滾方案

在部署方案中,我們通過Talos進行部署,它本身就帶有回滾功能。得益于子工程的發(fā)布和普通工程的發(fā)布并沒什么本質不同,都是將靜態(tài)資源放置到CDN上,通過靜態(tài)資源的的contenthash值來區(qū)分不同版本,所以回滾的時候,Talos取到上個版本(或者某個前版本)的靜態(tài)資源,再通過Portm更新我們的配置信息即可完成。整個過程和普通工程沒有區(qū)別,發(fā)版人員只需簡單地點下回滾按鈕即可。

微前端在美團外賣的實踐(美團微前端架構)

監(jiān)控方案

改變了原有的開發(fā)模式后,我們還對幾個關鍵節(jié)點進行了監(jiān)控報警的埋點。利用美團CAT(已經(jīng)在GitHub上開源)和天網(wǎng)(美團內(nèi)部的監(jiān)控系統(tǒng)),我們分別在子工程的配置信息、靜態(tài)資源加載等節(jié)點上進行了埋點上報,統(tǒng)計子工程加載成功率,及時發(fā)現(xiàn)可能出現(xiàn)的子工程切換問題。具體情況如下圖所示:

微前端在美團外賣的實踐(美團微前端架構)

上方左圖是按照端維度進行統(tǒng)計的示例,上方右圖是PC端按照產(chǎn)品線統(tǒng)計加載成功數(shù)的示例。默認都是統(tǒng)計當天的數(shù)據(jù),顯示‘-’的表明當前沒有數(shù)據(jù)。對資源加載的監(jiān)控目前有三種類型:JSON、JS和CSS,資源加載失敗的統(tǒng)計也包含這三種類型。天網(wǎng)的監(jiān)控按照分鐘級進行,每分鐘內(nèi)如果有加載失敗就會發(fā)出報警,偶爾的報警可能是用戶網(wǎng)絡的問題,如果出現(xiàn)大批量的報警就要引起重視了。

總結

以上就是微前端在外賣商家廣告端的實踐過程??偟膩碚f,我們完成了以下的目標:

  • 按照領域(業(yè)務線)拆分工程,工程的可維護性得到提高,相關領域進行了內(nèi)聚,無關領域進行了解耦。
  • 子工程提供了PC、H5、KA三端的物理復用土壤,消除了工程膨脹問題,工程大小也變得可控。
  • 子工程打包速度從分鐘級降為秒級,提高了開發(fā)體驗,加快了上線的速度。
  • 子工程開發(fā)支持熱更新,開發(fā)體驗不降級。
  • 子工程能夠單獨開發(fā)、單獨部署、單獨上線,業(yè)務線間互不影響。
  • 整體工程改造成本低,插拔式開發(fā),無侵入式代碼,在正常業(yè)務開發(fā)的同時短期內(nèi)就可以完成上線。
  • 開發(fā)者學習成本低,完整地保留了單頁應用開發(fā)的開發(fā)體驗,開發(fā)者可快速上手。

目前在美團廣告端,以微前端模式上線的子業(yè)務線已經(jīng)有很多個。另外還有多個正在開發(fā)的微前端子工程,剩余在主工程中的子業(yè)務線后續(xù)也可以無痛遷移出來成為子工程。我們內(nèi)部也在此過程中搜集了不少意見反饋,未來繼續(xù)在實踐中進行思考和完善。在此過程中,我們深知還有很多做得不夠完善甚至存在問題的地方,歡迎大家跟我們進行交流,幫我們提出寶貴意見或者給予指導。當然也歡迎大家加入我們團隊(文末有招聘信息),一起共建。

作者簡介

張嘯、魏瀟、天堯,均為美團外賣前端團隊研發(fā)工程師。

招聘信息

美團外賣廣告前端團隊誠招高級前端開發(fā)、前端開發(fā)專家。我們?yōu)樯碳姨峁┳儸F(xiàn)服務平臺,為用戶提供優(yōu)質廣告體驗,是外賣商業(yè)變現(xiàn)中的重要環(huán)節(jié)。歡迎各位小伙伴的加入,共同打造極致廣告產(chǎn)品。感興趣的同學可投遞簡歷至:tech@meituan.com(郵件標題注明:美團外賣廣告前端團隊)

相關新聞

聯(lián)系我們
聯(lián)系我們
公眾號
公眾號
在線咨詢
分享本頁
返回頂部
兴安盟| 麻城市| 河北省| 诸城市| 岚皋县| 赤水市| 成武县| 郁南县| 丹江口市| 杂多县| 曲阳县| 肇庆市| 富顺县| 泾川县| 紫阳县| 三明市| 公主岭市| 榆中县| 新疆| 贵溪市| 平定县| 尉犁县| 兰州市| 凤山市| 无极县| 张北县| 房产| 边坝县| 宁陵县| 牟定县| 晋州市| 阜阳市| 鄂温| 东乌| 镇巴县| 高要市| 同江市| 砀山县| 定兴县| 康保县| 班戈县|