項(xiàng)目重構(gòu)是每一家穩(wěn)定發(fā)展的互聯(lián)企業(yè)的必經(jīng)之路, 就像一個(gè)產(chǎn)品的誕生, 會(huì)經(jīng)歷產(chǎn)品試錯(cuò)和產(chǎn)品迭代 一樣洞豁。
隨著業(yè)務(wù)或新技術(shù)的不斷發(fā)展, 已有架構(gòu)已無法滿足更多業(yè)務(wù)擴(kuò)展的需求, 所以只有通過重構(gòu)來讓產(chǎn)品“進(jìn)化”, 才能跟上飛速發(fā)展的時(shí)代浪潮.
一. 重構(gòu)原因及準(zhǔn)備
這里我結(jié)合自己的實(shí)際經(jīng)驗(yàn)總結(jié)一下項(xiàng)目重構(gòu)的幾個(gè)原因:
1. 技術(shù)因素
技術(shù)因素主要有如下幾個(gè)方面:
- 早期技術(shù)團(tuán)隊(duì)在技術(shù)選型上的誤判(常發(fā)生于MVP類型的產(chǎn)品快速上線導(dǎo)致的技術(shù)調(diào)研不夠充分)
- 新老技術(shù)框架的更替(比如從 jquery 遷移到 vue/react)
- 技術(shù)團(tuán)隊(duì)交接出現(xiàn)的斷層(老技術(shù)團(tuán)隊(duì)的架構(gòu)設(shè)計(jì)更不上新技術(shù)團(tuán)隊(duì)的發(fā)展, 出現(xiàn)架構(gòu)上的“平替”)
- 技術(shù)架構(gòu)升級(jí)(比如隨著業(yè)務(wù)發(fā)展, 由傳統(tǒng)的MPA應(yīng)用轉(zhuǎn)為基于微前端模式的SPA應(yīng)用)
- 安全,性能,代碼質(zhì)量等原因?qū)е碌募夹g(shù)重構(gòu)
2. 產(chǎn)品因素
- 產(chǎn)品形態(tài)調(diào)整(比如由純PC應(yīng)用轉(zhuǎn)為響應(yīng)式應(yīng)用, 或者從H5到支持跨端)
- 產(chǎn)品業(yè)務(wù)調(diào)整(非常常見的重構(gòu)理由之一)
- 產(chǎn)品指標(biāo)調(diào)整(如兼容性, 性能指標(biāo)等導(dǎo)致的代碼重構(gòu))
上面是我列出來的比較典型的重構(gòu)場(chǎng)景, 也是我們未來在設(shè)計(jì)產(chǎn)品技術(shù)架構(gòu)之前需要考慮的方面. 為了提高自己設(shè)計(jì)的架構(gòu)穩(wěn)定性, 我們需要提前和產(chǎn)品溝通明確, 以降低后期重構(gòu)和維護(hù)成本.
最后總結(jié)幾條架構(gòu)設(shè)計(jì)的經(jīng)驗(yàn):
- 能做規(guī)范的一定要嚴(yán)格做好規(guī)范
- 在設(shè)計(jì)架構(gòu)之前, 一定要充分理解業(yè)務(wù)場(chǎng)景, 明確產(chǎn)品的技術(shù)交付指標(biāo)
- 架構(gòu)設(shè)計(jì)以可溯源 為基本要求
- 不要盲目追求最好的方案, 以局部最優(yōu)解為工程設(shè)計(jì)理念
2. 做項(xiàng)目重構(gòu)之前, 需要有哪些準(zhǔn)備
當(dāng)然做項(xiàng)目重構(gòu)也是有技術(shù)門檻的,不是所有程序員都能做好重構(gòu)工作, 建議大家具備如下幾種技術(shù)能力:
- 對(duì)項(xiàng)目所使用的框架語言有相對(duì)深入的理解和掌握
- 有一定的前端工程化經(jīng)驗(yàn)(如webpack, vite, gulp, nodejs, babel, AST等有一定的研究)
- 熟悉常用的web性能優(yōu)化方案
- 熟悉常見的設(shè)計(jì)模式和前端編碼規(guī)范
- 熟悉前端主流的技術(shù)框架的設(shè)計(jì)原理和工程設(shè)計(jì)思想
接下來我們一起看看常見的幾種項(xiàng)目重構(gòu)場(chǎng)景及其重構(gòu)方向.
二. 不同類型項(xiàng)目重構(gòu)的方法論
1. 業(yè)務(wù)系統(tǒng)自身的重構(gòu)
業(yè)務(wù)系統(tǒng)自身的重構(gòu)一般可以包含如下幾個(gè)方面:
- 業(yè)務(wù)代碼優(yōu)化
業(yè)務(wù)代碼優(yōu)化主要是針對(duì)一些核心業(yè)務(wù)代碼, 進(jìn)行流程上, 邏輯上的重構(gòu), 讓它更具可讀性和維護(hù)性, 同時(shí)保證業(yè)務(wù)操作的兼容性, 具體方案如下:
復(fù)雜業(yè)務(wù)邏輯需要編寫注釋
代碼中訪問性屬性提供兼容邏輯(常見的比如訪問對(duì)象屬性, a.b.c, 如果a,b為非對(duì)象則整段代碼將報(bào)錯(cuò))
代碼結(jié)構(gòu)優(yōu)化(比如冗長(zhǎng)的
if else
或者“回調(diào)地獄” 可以采用適配器模式或者es6+
語法來優(yōu)化)方法參數(shù)調(diào)優(yōu)(一個(gè)函數(shù)有多個(gè)參數(shù), 可以使用參數(shù)對(duì)象來提高可讀性,降低使用偏差)
業(yè)務(wù)代碼性能優(yōu)化(復(fù)雜后臺(tái)系統(tǒng)比如低代碼類產(chǎn)品, 前端需要處理很多數(shù)據(jù)和邏輯, 此時(shí)可以用合適的數(shù)據(jù)結(jié)構(gòu)和算法優(yōu)化
js
計(jì)算)函數(shù)式編程思想優(yōu)化業(yè)務(wù)函數(shù)(可選)
業(yè)務(wù)代碼進(jìn)行單元測(cè)試, 提高代碼質(zhì)量(可選)
代碼規(guī)范
早期可能由某名研發(fā)單獨(dú)負(fù)責(zé)的項(xiàng)目, 對(duì)代碼規(guī)范和格式要求不是很高, 但是需要考慮后期團(tuán)隊(duì)擴(kuò)容帶來的協(xié)作開發(fā)問題, 這個(gè)時(shí)候如果沒有統(tǒng)一的規(guī)范, 不同研發(fā)小伙伴可能寫出的代碼千奇百怪, 導(dǎo)致后期維護(hù)成本巨大, 尤其是涉及到需要維護(hù)他人代碼時(shí). 所以我們重構(gòu)的另一個(gè)目標(biāo)就是降低代碼理解成本, 保證項(xiàng)目代碼在閱讀時(shí)就像同一個(gè)寫出來的, 這樣對(duì)后期邏輯復(fù)用, 組件解耦, 問題定位以及業(yè)務(wù)代碼維護(hù)將非常有幫助.
常用的措施有:
- 代碼格式規(guī)范(如
eslint
) - 邏輯語法類型約束(如
typescript
) - 代碼規(guī)范(如css命名規(guī)范OOCSS, BEM等, 文件命名規(guī)范, js變量命名復(fù)規(guī)范等)
- git 提交規(guī)范(常見的是在git hooks的提交階段對(duì)提交格式等進(jìn)行校驗(yàn))
當(dāng)然, 這些都是需要結(jié)合自身團(tuán)隊(duì)和項(xiàng)目來定的, 這里只做參考.
- 工程化優(yōu)化
工程化優(yōu)化主要有以下幾個(gè)場(chǎng)景:
- 由于業(yè)務(wù)不斷增加, 系統(tǒng)的復(fù)雜性加大導(dǎo)致的本地運(yùn)行和打包速度越來越慢
- 由于項(xiàng)目代碼量的增加導(dǎo)致頁面臃腫, 需要進(jìn)行合理的拆分
- 基于已有的工程經(jīng)驗(yàn)沉淀, 需要對(duì)工程化配置做進(jìn)一步升級(jí), 優(yōu)化
- 老舊腳手架無法適應(yīng)當(dāng)前的項(xiàng)目生產(chǎn)效率
接下來我會(huì)針對(duì)以上場(chǎng)景, 進(jìn)行一些解決方案的分享.
- 由于業(yè)務(wù)不斷增加, 系統(tǒng)的復(fù)雜性加大導(dǎo)致的本地運(yùn)行和打包速度越來越慢
針對(duì)這種情況, 我們可以借助 speed-measure-webpack-plugin
插件,它可以分析 webpack
的總打包耗時(shí)以及每個(gè) plugin
和 loader
的打包耗時(shí),從而讓我們對(duì)打包時(shí)間較長(zhǎng)的部分進(jìn)行針對(duì)性優(yōu)化。
同時(shí)默認(rèn)情況react
, react-dom
, react-router
等公共模塊在每次構(gòu)建都會(huì)參與打包, 這些實(shí)際上是沒有必要的, 我們可以將其傳到 cdn
上, 從而減少webpack
的打包”工作量“.
我們可以安裝 html-webpack-externals-plugin
來實(shí)現(xiàn)將指定模塊從打包列表中排除, 具體用法如下:
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
module.exports = {
// ...其他配置代碼
plugins: [
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'react',
entry: 'https://cdn.dooring.cn/umd/react.production.min.js',
global: 'React',
},
{
module: 'react-dom',
entry:
'https://cdn.dooring.cn/umd/react-dom.production.min.js',
global: 'ReactDOM',
},
],
}),
],
};
為了追求更驚一步的打包效率, 我們可以使用并行的方式構(gòu)建, 同樣 webpack
生態(tài)也提供了對(duì)應(yīng)的模塊 parallel-webpack
. 具體用法大家可以看文檔, 非常簡(jiǎn)單方便.
其他還有很多優(yōu)化的方案, 這里我列一下, 大家可以根據(jù)實(shí)際情況使用:
-
配置并行壓縮(
terser-webpack-plugin
,css-minimizer-webpack-plugin
,html-minimizer-webpack-plugin
等都支持parallel
參數(shù)) -
預(yù)編譯資源模塊(可以利用
webpack.DllPlugin
來提前將公共模塊打包以便后續(xù)直接復(fù)用) -
使用構(gòu)建緩存(
webpack5
內(nèi)置的cache
模塊, 或者cache-loader
) -
對(duì)打包體積進(jìn)行分析, 以便有針對(duì)性的優(yōu)化(如
webpack-bundle-analyzer
)
當(dāng)然除了對(duì)已有構(gòu)建工具的優(yōu)化, 我們可以評(píng)估一下重構(gòu)成本, 將構(gòu)建內(nèi)核替換vite
等更高效的構(gòu)建工具.
- 由于項(xiàng)目代碼量的增加導(dǎo)致頁面臃腫, 需要進(jìn)行合理的拆分
針對(duì)項(xiàng)目代碼量的增加導(dǎo)致頁面臃腫, 我們可以從項(xiàng)目本身的角度, 對(duì)項(xiàng)目進(jìn)行拆解, 將公共模塊抽離為公用業(yè)務(wù)類庫或者組件庫:
除了對(duì)項(xiàng)目進(jìn)行可復(fù)用性拆分之外, 我們還需要根據(jù)系統(tǒng)復(fù)雜量級(jí), 近一步拆分項(xiàng)目, 比如將一個(gè)巨石工程拆分為多個(gè)子工程, 單獨(dú)運(yùn)行維護(hù), 或者采用之前熱點(diǎn)討論的微前端的模式, 比如使用 qainkun
, single-spa
, Micro App
, EMP
, Garfish
, Bit
這些優(yōu)秀的微前端框架.
綜上, 我們可以根據(jù)項(xiàng)目復(fù)雜度, 做如下優(yōu)化:
- 模塊 & 組件化
- 拆分子系統(tǒng)(已有架構(gòu)不變的MPA模式)
- 拆分子系統(tǒng)(微前端)
當(dāng)然我們始終需要保持一個(gè)理念: 局部最優(yōu), 誤增繁復(fù).
- 基于已有的工程經(jīng)驗(yàn)沉淀, 需要對(duì)工程化配置做進(jìn)一步升級(jí), 優(yōu)化
這種情況主要是在項(xiàng)目發(fā)展穩(wěn)定之后, 需要思考的重構(gòu)方向, 比如早期由于業(yè)務(wù)場(chǎng)景單一, 很多公共配置都寫在業(yè)務(wù)代碼里的, 隨著業(yè)務(wù)復(fù)雜之后, 很多模塊都需要使用改配置或者變量, 比如:
// a.js
const publicDomain = 'https://dooring.vip';
const serverUrl = 'https://xxx.cn';
// b.js
const publicDomain = 'https://dooring.vip';
// c.js
const appid = 'xxxxxxxx';
const website_Logo = 'http://h5.dooring.cn/logo.png';
對(duì)于這種零散且固定的變量, 未來可能會(huì)被多個(gè)頁面或者模塊復(fù)用, 所以為了降低成本, 我們可以把這些通用配置提取到外層, 作為公共配置文件, 這樣后期新項(xiàng)目也能享受開箱即用的配置體驗(yàn).
拿我的親身經(jīng)驗(yàn), 比如幾年前我開發(fā)的低代碼項(xiàng)目H5-Dooring
, 有一些零散的配置信息分散在項(xiàng)目的各個(gè)角落, 后面經(jīng)過幾次重構(gòu)優(yōu)化之后, 整個(gè)項(xiàng)目只需要在配置文件中輕松配置內(nèi)容, 即可一鍵控制頁面的走向, 這里分享一下優(yōu)化過后的配置文件:
// h5-dooring全局配置文件
define: {
START_ENV,
lang,
// 配置h5端訪問的域名
h5Domain: 'h5.dooring.cn',
// 設(shè)置當(dāng)前版本號(hào)
curVersion: dooringVersion,
// 備案信息
copyright: 'xxxxx-3',
// 是否顯示更新彈窗
showUpdateModal: true,
// 更新日志
updateList: [
"1\. 新增表格組件",
"2\. 國(guó)際化優(yōu)化",
"3\. 表單詳情頁支持內(nèi)部滾動(dòng)",
"4\. 個(gè)人圖片庫性能優(yōu)化",
"5\. 下載代碼功能優(yōu)化"
],
// 網(wǎng)站logo地址
logo: 'http://cdn.dooring.cn/dr/logo.ff7fc6bb.png',
// 入口頁面是否展示贊助品牌和版權(quán)提示
showAdsAndTip: true,
// 登錄時(shí)獲取登錄碼的二維碼
qrcode: 'http://cdn.dooring.cn/dr%2Fcode1.png',
// 友情鏈接展示
friendLinks: [
{
name: 'V6',
link: 'http://v6.dooring.cn/beta',
title: '可視化大屏編輯器'
},
{
name: 'Power',
link: '/powernice',
title: '文檔編輯器'
}
],
// 默認(rèn)語言
defaultLocale: 'zh-CN',
langMap: langMap
},
這樣, 我們的工程化結(jié)果就可以讓不同的技術(shù)小伙伴輕松的享受, 讓項(xiàng)目創(chuàng)建的成本和自由度得到極大的提升.
- 老舊腳手架無法適應(yīng)當(dāng)前的項(xiàng)目生產(chǎn)效率
對(duì)于這種場(chǎng)景, 我們就需要對(duì)腳手架自身有更多的研究和了解, 比如熟悉webpack
設(shè)計(jì)思想, 熟悉babel
的工作流程, 熟悉 nodejs
開發(fā)工具鏈的一些模式等, 這里分享幾個(gè)比較成熟的先進(jìn)腳手架, 大家如果覺得老項(xiàng)目工程比較老舊, 可以往這幾個(gè)方向重構(gòu):
- 基于webpack5.0的項(xiàng)目腳手架
- vite
- umi4.0
如果大家對(duì)以上三種之一比較熟悉, 也可以基于他們二次封裝成符合自身業(yè)務(wù)場(chǎng)景的DIY項(xiàng)目工具.
- 渲染層優(yōu)化
渲染層優(yōu)化主要表現(xiàn)在產(chǎn)品的體驗(yàn)上, 比如:
- 提高首屏加載速度
- 白屏體驗(yàn)優(yōu)化
- 大數(shù)據(jù)列表渲染優(yōu)化
- api請(qǐng)求優(yōu)化
- 動(dòng)畫性能優(yōu)化
- dom過載導(dǎo)致的頁面卡頓優(yōu)化
以上是我之前遇到的一些渲染優(yōu)化的維度, 接下來和大家一一介紹解決思路.
1. 提高首屏加載速度
有很多方法可以幫助我們提高首屏加載速度, 比如:
- 靜態(tài)資源放cdn, 提高不同地域用戶訪問資源的速度
- 頁面或路由懶加載, 降低首次加載單一頁面的代碼體積
- 靜態(tài)資源(如圖片, 視頻等)懶加載
- 資源壓縮(比如開啟gzip模式)
當(dāng)然還存在很多客觀因素, 比如用戶所在區(qū)域?yàn)槿蹙W(wǎng)環(huán)境, 我們可以根據(jù)網(wǎng)速提供一個(gè)最小化弱網(wǎng)可替代頁面, 來保證我們網(wǎng)站的可用性和可訪問性.
2. 白屏體驗(yàn)優(yōu)化
對(duì)于白屏優(yōu)化, 也有很多成熟的例子, 比如采用骨架屏:
如果我們的項(xiàng)目是基于 vue-cli
構(gòu)建的,那么可以使用比較成熟的的 page-skeleton-webpack-plugin
方案,否則我們?nèi)匀豢梢赃x擇 vue-router
提供的 vue-server-renderer
.
當(dāng)然你的項(xiàng)目是使用react
的, 也可以輕松使用如 react-content-loader
這樣的svg方案來定制自己的骨架屏.
除了骨架屏之外, 我們還可以提供一個(gè)模版頁面或者加載動(dòng)畫, 以便在頁面加載完成之前給用戶一個(gè)優(yōu)雅的過渡提示. 比如:
3. 大數(shù)據(jù)列表渲染優(yōu)化
對(duì)于一些中后臺(tái)復(fù)雜的系統(tǒng)模塊, 可能會(huì)涉及到一次渲染大量列表項(xiàng)或者多級(jí)組織樹的情況:
尤其是在大公司或者大集團(tuán)中出現(xiàn)的頻率非常高, 這種情況我們就需要用到虛擬列表或者節(jié)點(diǎn)懶加載的方式了. 虛擬列表應(yīng)用非常廣泛, 目前也有幾個(gè)成熟的方案大家可以直接使用:
- vue virtual scroll list
- react-virtualized
- rc-virtual-list
如果你的項(xiàng)目目前還好沒有使用這種方案, 不妨評(píng)估一下, 是否可以用這些方案為自己項(xiàng)目保駕護(hù)航.
4. api請(qǐng)求優(yōu)化
api
請(qǐng)求優(yōu)化主要正對(duì)這種場(chǎng)景: 頁面的渲染依賴于某個(gè)或者某些請(qǐng)求的完成, 或者由于某個(gè)頁面請(qǐng)求量過大導(dǎo)致每次重新進(jìn)入頁面都需要造成一定的性能開銷.
對(duì)于這兩種情況, 其實(shí)不僅僅是對(duì)瀏覽器渲染有影響, 還會(huì)極大的增加服務(wù)器的壓力, 所以我們需要對(duì)請(qǐng)求或者頁面進(jìn)行一定范圍的緩存.
比如說我們可以把不長(zhǎng)變動(dòng)的請(qǐng)求數(shù)據(jù)存在 indexedDB 中, 當(dāng)?shù)诙卧L問直接可以從 indexedDB 中拿到請(qǐng)求數(shù)據(jù), 這樣既降低了服務(wù)器壓力, 也提高了二次渲染的效率.
其次我們可以對(duì)部分頁面做路由緩存, 避免每次切換都重新渲染, 當(dāng)然這只針對(duì)于不需要實(shí)時(shí)更新數(shù)據(jù)的頁面而言. 我之前也分享了一篇瀏覽器緩存接口實(shí)戰(zhàn)的文章, 大家感興趣的可以學(xué)習(xí)參考, 對(duì)于 indexedDB
, 我封裝了一個(gè)開箱即用的庫, 大家可以直接使用:
github地址: https://github.com/MrXujiang/xdb
5. 動(dòng)畫性能優(yōu)化
這也是個(gè)老生常談的問題, 這里直接分享幾個(gè)方案:
- 優(yōu)化精簡(jiǎn)
DOM
結(jié)構(gòu)亩鬼,合理布局 - 使用
transform
代替 left,top 減少使用引起頁面重排的屬性 - 開啟硬件加速(比如設(shè)置
transform: translateZ(0)
或者transform: translate3d(0, 0, 0)
) - 盡量避免瀏覽器創(chuàng)建不必要的圖形層
- 盡量減少
js
動(dòng)畫,如需要阿蝶,使用性能更友好的requestAnimationFrame
- 使用
chrome performance
工具調(diào)試動(dòng)畫性能
由于dom動(dòng)畫有上限很低, 所以對(duì)于一些更復(fù)雜的動(dòng)畫渲染, 我們可以采用 svg
或者 canvas
來代替, 以降低 dom
對(duì)瀏覽器內(nèi)存的占用.
6. dom過載導(dǎo)致的頁面卡頓優(yōu)化
一個(gè)頁面如果dom數(shù)量過多, 會(huì)產(chǎn)生很多問題, 一方面會(huì)使得瀏覽器內(nèi)存占用過高, 導(dǎo)致其他不相關(guān)的js邏輯操作進(jìn)行阻塞或者失效, 表現(xiàn)就是頁面卡頓或者無響應(yīng).
為了解決這個(gè)問題我們?nèi)匀豢梢允褂?strong>虛擬滾動(dòng)的方案或者懶加載的方案, 保證用戶當(dāng)前屏幕下的dom
在一個(gè)合理的范圍內(nèi), 如果是無法避免必須要展示大段dom
元素, 我們可以用一個(gè)單獨(dú)的頁面來承載或者嵌入, 避免頁面其他部分宕機(jī). 也可以對(duì)復(fù)雜dom
進(jìn)行局部“冷凍”(在非激活狀態(tài)將其轉(zhuǎn)化為圖片, 激活時(shí)在逐漸渲染)
- 產(chǎn)品需求層優(yōu)化
產(chǎn)品需求層面導(dǎo)致的重構(gòu)主要場(chǎng)景比如:
- 項(xiàng)目國(guó)際化支持
- 項(xiàng)目埋點(diǎn)
- 整體項(xiàng)目UI升級(jí)
當(dāng)然還有很到場(chǎng)景這里不一一介紹了. 以上列的場(chǎng)景都是比較常見的, 而且也有很多解決方案, 后期我會(huì)一一復(fù)盤. 我們?cè)陧?xiàng)目重構(gòu)之前或者立項(xiàng)之前, 這幾種情況也是需要重點(diǎn)考慮的, 畢竟都是大工作量的任務(wù).
2. 技術(shù)升級(jí)帶來的重構(gòu)
技術(shù)升級(jí)帶來的重構(gòu)主要有前端框架的升級(jí), 前端設(shè)計(jì)模式的升級(jí), 腳手架的升級(jí). 后面兩個(gè)主要是圍繞前端技術(shù)的不斷演進(jìn), 我們采取的程序性升級(jí), 比如從傳統(tǒng)的 gulp
升級(jí)到 webpack
, 或者從 webpack
升級(jí)到vite
等. 前者比較常見的場(chǎng)景是企業(yè)中有很多老的系統(tǒng), 采用的是比較傳統(tǒng)的技術(shù)方案如 CMD 模式 + jquery
, 但是新項(xiàng)目采用的是 webpack + vue 或者 react
, 此時(shí)我們需要更新項(xiàng)目情況來有選擇的做重構(gòu):
- 老項(xiàng)目只需要少量維護(hù)的情況
這種情況我們就不需要大刀闊斧的重新用新框架再寫一套了, 我們只需要在重構(gòu)時(shí), 對(duì)老項(xiàng)目代碼做好足夠的注釋, 類庫的封裝即可:
其次我們需要做好js
變量隔離, 因?yàn)閭鹘y(tǒng)模式我們會(huì)在 window
頂層定義大量 var
全局變量, 作為優(yōu)化的一部分, 我們可以采用閉包自執(zhí)行和變量約定來規(guī)范我的js
變量定義, 以防止全局的變量污染.
- 老項(xiàng)目仍然需要不斷迭代, 并且后期會(huì)有新的模塊
這種情況我們需要做評(píng)估和拆分, 如果是小模塊, 我們可以用 jquery插件
的方式快速爹迭代, 如果是頁面級(jí)別的迭代, 并且交互比較復(fù)雜, 我們可以將老系統(tǒng)的新頁面拆離一個(gè)子工程, 采用最新的框架(如vue)來開發(fā)迭代, 再通過 MPA
的方式和老系統(tǒng)做集成:
- 老項(xiàng)目和新項(xiàng)目需要相互通信, 嵌套
這種場(chǎng)景下最好的方式就是用iframe + postmessage
, 或者我們可以參考類似微前端的方式來管理組織不同子系統(tǒng).
3. 組件庫重構(gòu)
對(duì)于一個(gè)包含很多子系統(tǒng)的復(fù)雜的項(xiàng)目系統(tǒng)來說雳锋,要想設(shè)計(jì)一個(gè)好的架構(gòu),第一步就是合理劃分組件羡洁,組件的粒度拆成的足夠細(xì)玷过,這樣才能最大限度的復(fù)用組件。
對(duì)于任何一個(gè)復(fù)雜系統(tǒng)來說筑煮,最重要的就是實(shí)現(xiàn)錯(cuò)綜復(fù)雜的業(yè)務(wù)功能辛蚊,但是不同模塊或者子系統(tǒng)之間很多業(yè)務(wù)往往是相通的或者相似的,如果這個(gè)時(shí)候我們每個(gè)頁面對(duì)于實(shí)現(xiàn)類似的業(yè)務(wù)場(chǎng)景都去重復(fù)去寫一遍業(yè)務(wù)代碼真仲,那完全是沒必要的袋马,對(duì)于可維護(hù)性來說也是一種打擊,所以基于這種場(chǎng)景我們的 業(yè)務(wù)組件 就很有必要出場(chǎng)了秸应。我們可以把功能或者需求類似的有機(jī)體封裝成一個(gè)業(yè)務(wù)組件飞蛹,并對(duì)外暴露接口來實(shí)現(xiàn)靈活的可定制性,這樣的話我們就可以再不同頁面不同子系統(tǒng)中復(fù)用同樣的邏輯和功能了灸眼。
同理,不同頁面中往往有可能出現(xiàn)視覺或者交互完全相同或者類似的區(qū)塊墓懂,為了提高可復(fù)用性和提高開發(fā)效率焰宣,我們往往會(huì)基于基礎(chǔ)組件和業(yè)務(wù)組件再進(jìn)行一次封裝,讓其成為一個(gè)獨(dú)立的區(qū)塊以便直接復(fù)用捕仔。
通過這樣一層層封裝匕积,我們就逐漸搭建了一套完整的組件化系統(tǒng)盈罐,基于這種模式的開發(fā)往往也是一個(gè)好的前端架構(gòu)的開始。但要注意一點(diǎn)就是高層次的組件一定會(huì)依賴低層次的組件闪唆,但是低層次的組件不可以包含高層次的組件盅粪。(聽起來有點(diǎn)像rudex的單向數(shù)據(jù)流法則),他們的關(guān)系就好像下圖:
所以對(duì)組件庫的重構(gòu)需要對(duì)我們的項(xiàng)目有一個(gè)本質(zhì)的認(rèn)知, 并對(duì)頁面進(jìn)行有效的拆分, 從而達(dá)到局部的最優(yōu), 降低后續(xù)的維護(hù)成本, 并能提高整個(gè)系統(tǒng)甚至跨系統(tǒng)的復(fù)用.
有關(guān)如何從0到1教你搭建前端團(tuán)隊(duì)的組件系統(tǒng) 我之前也寫過詳細(xì)的文章, 大家可以參考學(xué)習(xí)一下.
總結(jié)
系統(tǒng)重構(gòu)是一個(gè)持續(xù)的過程, 我們不僅要有持續(xù)學(xué)習(xí)的態(tài)度, 還需要不斷的實(shí)踐和積累優(yōu)秀的最佳實(shí)踐, 這樣才能在不斷重構(gòu)中讓我們的系統(tǒng)不斷適應(yīng)復(fù)雜多變的“社會(huì)環(huán)境”.