大型 SPA 項(xiàng)目架構(gòu)設(shè)計(jì)與重構(gòu)
點(diǎn)擊上方關(guān)注 前端技術(shù)江湖,一起學(xué)習(xí),天天進(jìn)步
大型 SPA 項(xiàng)目架構(gòu)設(shè)計(jì)與重構(gòu)
本文主要為分享我司 控制臺(tái)[1] 最近兩年的架構(gòu)演進(jìn),遇到的問(wèn)題和解決方案等。控制臺(tái)項(xiàng)目包含近百個(gè)不同產(chǎn)品,跨部門、跨地域協(xié)作開發(fā),是一個(gè)比較典型的大型 SPA 前端項(xiàng)目。
先說(shuō)下為何要做架構(gòu)重構(gòu),老架構(gòu)以及老架構(gòu)下的一些問(wèn)題。
老架構(gòu)介紹
控制臺(tái)老架構(gòu)底層為 angular@1,使用 angular 的 ui-router 和 lazy-load 來(lái)進(jìn)行項(xiàng)目的按需加載運(yùn)行。大部分項(xiàng)目通過(guò) angular 掛載 react 實(shí)例,雖然很多業(yè)務(wù)代碼和 angular 無(wú)關(guān),但是依然有很多地方(如 services、路由等)依賴 angular。
老架構(gòu)存在的問(wèn)題
老架構(gòu)存在的問(wèn)題主要分為兩部分,運(yùn)行時(shí)問(wèn)題和開發(fā)時(shí)問(wèn)題:
運(yùn)行時(shí)問(wèn)題
老架構(gòu)嚴(yán)重依賴 angular
由于當(dāng)初整套架構(gòu)設(shè)計(jì)基于 angular 的能力,導(dǎo)致啟動(dòng)器體量大、加載慢、性能差。
老架構(gòu)下的依賴體量重
老架構(gòu)下公共部分主要分為 common 和 components,里面存在大量的歷史遺留、冗余、無(wú)效代碼,歷史包袱重,而且依賴混亂,無(wú)法安全清理。
耦合嚴(yán)重
老架構(gòu)下的項(xiàng)目,雖然大部分項(xiàng)目代碼已經(jīng)都是 react 代碼,但是有一些 services 依然依賴 angular。啟動(dòng)器、公共依賴、項(xiàng)目間的代碼耦合嚴(yán)重。
性能問(wèn)題
啟動(dòng)器重、依賴重、語(yǔ)言文件混合導(dǎo)致過(guò)大、初始化內(nèi)容過(guò)多等各種問(wèn)題導(dǎo)致項(xiàng)目加載慢、執(zhí)行慢。
開發(fā)時(shí)問(wèn)題
使用麻煩、風(fēng)險(xiǎn)高
老架構(gòu)的項(xiàng)目結(jié)構(gòu)為一個(gè)主項(xiàng)目和 N 個(gè)子項(xiàng)目,主項(xiàng)目中包含著開發(fā)腳本、開發(fā)依賴,其它的項(xiàng)目如依賴、啟動(dòng)器、項(xiàng)目均作為子模塊(git submodule)管理。
開發(fā)時(shí)需要檢查主倉(cāng)庫(kù)更新,檢查依賴更新,執(zhí)行開發(fā)腳本,還需注意啟動(dòng)器項(xiàng)目的版本、沖突、依賴更新等,使用成本高。
升級(jí)成本高
開發(fā)環(huán)境無(wú)法安全升級(jí),由于所以依賴、腳本都是全項(xiàng)目共享,升級(jí)會(huì)直接影響到上百個(gè)子項(xiàng)目,導(dǎo)致不能隨意變動(dòng)。
新架構(gòu)

控制臺(tái)項(xiàng)目分三層,啟動(dòng)器、公共模塊、業(yè)務(wù)模塊。
啟動(dòng)器
啟動(dòng)的承載著網(wǎng)站最基本的功能,包括:
骨架屏 瀏覽器兼容處理 - 不兼容版本提示 項(xiàng)目路由管理( router-service) - 跨項(xiàng)目跳轉(zhuǎn)項(xiàng)目加載/掛載/卸載(微前端 rapiop[2]) 模塊管理器(mod[3]) 主題 - 主題加載/切換 基礎(chǔ)依賴 - babel polyfill、reset-stylesentry- 錯(cuò)誤上報(bào)matomo- 用戶行為分析、數(shù)據(jù)上報(bào)其它的一些內(nèi)部服務(wù)等
公共模塊
services
services 為內(nèi)部的一些公共服務(wù)。
user- 用戶信息intl- 語(yǔ)言翻譯das- 數(shù)據(jù)上報(bào)region、project等
libs
libs 用于輸出一些常用的公共模塊、開源庫(kù)。
react、react-dom、react-router-react相關(guān)庫(kù)components[4] - 公共組件庫(kù) apexcharts、react-apexcharts- 圖標(biāo)庫(kù)lodash等工具庫(kù)
components
components 包括控制臺(tái)相關(guān)的一些業(yè)務(wù)組件
common-components- 常用的業(yè)務(wù)組件、布局、路由組件等umon-components- 監(jiān)控相關(guān)組件code-components- 代碼編輯器組件ulog-components、pay-components等
其它模塊
sidebar、navbar- 公共部分的 UIstyles- 通用的樣式react-adapter- 項(xiàng)目適配器,減少樣板代碼(注冊(cè)微前端、初始化語(yǔ)言、依賴加載等)
業(yè)務(wù)模塊
業(yè)務(wù)模塊主要為各業(yè)務(wù)項(xiàng)目,分為老項(xiàng)目、新項(xiàng)目。
優(yōu)化后
輕量無(wú)依賴啟動(dòng)器 職責(zé)明確 模塊拆分、自治[5]、依賴明確 無(wú)耦合
運(yùn)行流程
進(jìn)入頁(yè)面:
瀏覽器兼容檢測(cè), polyfill、基本依賴加載reset樣式加載,主題、matomo、sentry初始化灰度信息獲取,未登陸則跳回登陸 使用灰度信息初始化微前端、模塊管理器 根據(jù)當(dāng)前 url匹配項(xiàng)目,如果為老項(xiàng)目則加載老啟動(dòng)器,進(jìn)入老項(xiàng)目加載流程,新項(xiàng)目直接加載項(xiàng)目、依賴

開發(fā)
開發(fā)環(huán)境拆分為兩部分:CLI 和 dev-dependences。
CLI
提供 CLI 工具,提供開發(fā)、構(gòu)建、打包分析、codemod、依賴管理等功能。
dev-dependences
包含了項(xiàng)目的開發(fā)依賴:webpack、eslint、loaders 等,存在多版本,可方便后續(xù)的升級(jí)迭代,降低升級(jí)成本和風(fēng)險(xiǎn)。
提供依賴對(duì)應(yīng)的功能腳本:開發(fā)、構(gòu)建等。
開發(fā)啟動(dòng)
通過(guò) CLI 啟動(dòng)開發(fā)命令,會(huì)根據(jù)命令啟動(dòng)啟動(dòng)器(線上/預(yù)發(fā)步/本地),啟動(dòng)指定項(xiàng)目中的開發(fā)依賴中的開發(fā)腳本并通信,合并線上灰度信息和本地文件信息。
優(yōu)勢(shì)
升級(jí)維護(hù)安全 使用方便
現(xiàn)狀
目前處于新架構(gòu)老架構(gòu)共存的狀態(tài),大部分的老項(xiàng)目在逐漸替換舊的 services 等,進(jìn)行平滑升級(jí)。
關(guān)于本文
作者:嘿嘿Z
https://juejin.cn/post/7000988622086209566
The End
歡迎自薦投稿到《前端技術(shù)江湖》,如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),記得點(diǎn)個(gè) 「在看」哦
點(diǎn)個(gè)『在看』支持下 
