淺談大型項目前端架構設計(轉載)

原文鏈接:https://juejin.im/post/5cea1f705188250640005472 

1、綜合

我在2年之前,寫過一篇中小型項目的前端架構淺談。

隨着能力的上升,以及在阿里巴巴工作的經驗,是時候寫一篇大型項目的前端架構分析了。

本篇文章不會更多側重於具體技術實現,而是嘗試從更高角度出發,分析爲什麼要這麼做,這些設計能解決什麼問題,成本和收益如何。

由於作者能力有限,可能會有所缺漏或者部分錯誤,歡迎讀者指出。

1.1、適用場景:

本篇文章,適用於單個/多個大型項目、擁有超過10個以上的前端開發的場景。

前端項目的規模不同,成本收益比也會有所差別。

通常來說,人員越多、項目複雜度越高,那麼收益/成本的比值越大。

對於人數較少、項目簡單的開發團隊,可能有部分措施不適用,因此應該根據具體情況來選用。

1.2、核心思想:

【1】解決問題:前端架構的設計,應是用於解決已存在或者未來可能發生的技術問題,增加項目的可管理性、穩定性、可擴展性。

【2】人效比:對於需要額外開發工作量的事務(本文中存在一些需要一定開發量的內容),我們在決定是否去做的時候,應該考慮到兩個要素:

第一個是花費的人力成本,第二個是未來可能節約的時間和金錢、避免的項目風險與資損、提高對業務的支撐能力以帶來在業務上可衡量的更高的價值、以及其他價值。

【3】定性和定量:架構裏設計的內容,一定要有是可衡量的意義的,最好是可以定量的——即可以衡量帶來的收益或減少的成本,至少是可以定性的——即雖然無法用數字闡述收益,但我們可以明確這個是有意義的,例如增加安全性降低風險。

【4】數據敏感:專門寫這一條強調數據作爲依據的重要性。

當我們需要說服其他部門/上級管理者,以推動我們設計的內容時,只有數據——特別是跟錢有關的數據,纔是最有說服力的證明。

由於篇幅所限,本文很難直接給出定量的值,因此建議架構設計者,先確保項目中設計使用2.7裏的埋點系統,根據埋點系統獲取的數據,對項目效果進行定量分析,並以此寫成PPT和其他部門/上級管理者進行協調。

1.3、切入角度:

分爲基礎層和應用層。

基礎層偏基礎設施建設,與業務相關性較低。

應用層更貼近用戶,用於解決某一個問題。

部分兩個都沾邊的,根據經驗劃分到其中一個。

1.4、其他

由於已經談到架構層級,因此很多內容,並不僅僅只屬於前端領域,有很多內容是複合領域(前端、後端、運維、測試),因此需要負責架構的人,技術棧足夠全面,對未來發展有足夠的前瞻性。

文章的內容結構爲:【項目】—>【解決的問題和帶來的好處】—>【項目的實際意義】

2、基礎層設計

2.1、自建Gitlab

這個是基礎的基礎了。本不應該提的,不過考慮到我最近面試的幾家公司,有的公司(人數並不少)並沒有使用Gitlab,因此專門提一下,並且使用這個的難度非常低。

強烈建議使用Gitlab進行版本管理,自建Gitlab難度並不大,方便管理,包括代碼管理、權限管理、提交日誌查詢,以及聯動一些第三方插件。

意義:

公司代碼是公司的重要資產,使用自建Gitlab可以有效保護公司資產。

2.2、版本管理

版本管理的幾個關鍵點:

  • 發佈後分支鎖死,不可再更改:指當例如0.0.1版本成功發佈後,不可再更改0.0.1分支上的代碼,否則可能會導致版本管理混亂。

  • 全自動流程發佈;指應避免開發者提交後,手動編譯打包等操作,換句話說,開發人員發佈後,將自動發佈到預發佈/生產環境。開發人員不和相關環境直接接觸。實現這個需要參考下面的2.3。

  • 多版本並存;指當例如發佈0.0.2版本後,0.0.1版本的代碼應仍保存在線上(例如CDN),這樣當出現線上bug時,方便快速回滾到上一個版本。

意義:

提高項目的可控性。

2.3、自動編譯發佈Jenkins

這個工具用於在代碼發佈後,執行一系列流程,例如自動編譯打包合併,然後再從Gitlab發佈到CDN或者靜態資源服務器。

使用這個工具,可以讓一般研發人員不關心代碼傳到Gitlab後會發生什麼事情,只需要專心於開發就可以了。

意義:

讓研發人員專心於研發,和環境、運維等事情脫鉤。

2.4、純前端版本發佈

純前端版本發佈分爲兩步:

  • 前端發佈到生產環境——此時可以通過外網鏈接加正確的版本號訪問到新版本的代碼,但頁面上的資源還是舊版本;

  • 前端通過配置工具(或者是直接更新html文件),將html中引入的資源,改爲新版本。

解決的問題是:當前端需要發佈新版本時,可以不依賴於後端(根據實際情況,也可以不依賴於運維)。

畢竟有很多需求並不需要後端介入,單純改個前端版本後就要後端發佈一次,顯然是一件非常麻煩的事情。

這個需要專門的工具,用於配置版本發佈,我最近就在寫這個。

意義:

提高發布效率,降低發佈帶來的人員時間損耗(這些都是錢),也可以在前端版本回滾的時候,速度更快。

 

2.5、統一腳手架

適用場景:有比較多獨立中小項目。好處:

  • 可以減少開發人員配置腳手架帶來的時間損耗(特殊功能可以fork腳手架後再自行定製);

  • 統一項目結構,方便管理,也降低項目交接時帶來的需要熟悉項目的時間;

  • 方便統一技術棧,可以預先引入固定的組件庫;

意義:

提高開發人員在多個項目之間的快速切換能力,提高項目可維護性,統一公司技術棧,避免因爲環境不同導致奇怪的問題。

2.6、Node中間層

適用場景:需要SEO且前端使用React、vue,或前端介入後端邏輯,直接讀取後端服務或者數據庫的情況。

  • SEO:仁者見仁智者見智,雖然很多公司已經不做了,但通常認爲,還是有一定意義的(特別是需要搜索引擎引流的時候),因此React或者Vue的同構是必須的。並且同構還可以降低首頁白屏時間;

  • 前端讀取後端服務/數據庫:好處是提高前端的開發效率和對業務的支持能力,缺點是可能導致P0級故障。

意義:

讓前端可以侵入後端領域,質的提升對業務的支持能力。

2.7、埋點系統

強烈推薦前端做自己的埋點系統。這個不同於後端的日誌系統。

前端埋點系統的好處:

  • 記錄每個頁面的訪問量(日周月年的UV、PV);

  • 記錄每個功能的使用量;

  • 捕捉報錯情況;

  • 圖表化顯示,方便給其他部門展示;

埋點系統是前端高度介入業務,把握業務發展情況的一把利劍,通過這個系統,我們可以比後端更深刻的把握用戶的習慣,以及給產品經理、運營等人員提供準確的數據依據。

當有了數據後,前端人員就可以針對性的優化功能、佈局、頁面交互邏輯、用戶使用流程。

埋點系統應和業務解耦,開發人員使用時註冊,然後在項目中引入。然後在埋點系統裏查看相關數據(例如以小時、日、周、月、年爲週期查看)

意義:

數據是money,數據是公司的生命線,數據是最好的武器。

2.8、監控和報警系統

監控和報警系統應基於埋點系統而建立,在如以下場景時觸發:

  • 當訪問量有比較大的變化(比如日PV/UV只有之前20%以下)時,自動觸發報警,發送郵件到相關人員郵箱;

  • 比如報錯量大幅度上升(比如200%或更高),則觸發報警;

  • 當一段時間內沒有任何訪問量(不符合之前的情況),則觸發報警;

  • 每過一段時間,自動彙總訪問者/報錯觸發者的相關信息(例如系統、瀏覽器版本等);

建設這個系統的好處在於,提前發現一些不容易發現的bug(需要埋點做的比較紮實)。

有一些線上bug,因爲用戶環境特殊,導致無法被開發人員和測試人員發現。

但其中一部分bug又因爲不涉及資金,並不會導致資損(因此也不會被後端的監控系統所發現),這樣的bug非常容易影響項目裏某個鏈路的正常使用。

意義:

提高項目的穩定性,提高對業務的把控能力。

降低bug數,降低資損的可能性,提前發現某些功能的bug(在工單到來之前)。

2.9、安全管理

前端的安全管理,通常要依賴於後端,至於只跟單純有關係的例如dom.innerHTML=  xxx  這種太基礎,就不提了。

安全管理的很難從架構設計上完全避免,但還是有一定解決方案的,常見安全問題如下:

  • XSS注入:對用戶輸入的內容,需要轉碼(大部分時候要server端來處理,偶爾也需要前端處理),禁止使用eval函數;

  • https:這個顯然是必須的,好處非常多;

  • CSRF:要求server端加入CSRF的處理方法(至少在關鍵頁面加入);

意義:

減少安全漏洞,避免用戶受到損失,避免遭遇惡意攻擊,增加系統的穩定性和安全性。

2.10、Eslint

Eslint的好處很多,強烈推薦使用:

  • 降低低級bug(例如拼寫問題)出現的概率;

  • 增加代碼的可維護性,可閱讀性;

  • 硬性統一代碼風格,團隊協作起來時更輕鬆;

總的來說,eslint推薦直接配置到腳手架之中,對我們提高代碼的可維護性的幫助會很大。可以考慮在上傳到gitlab時,硬性要求eslint校驗,通過的才允許上傳。

意義:

提高代碼的可維護性,降低團隊協作的成本。

2.11、灰度發佈

灰度發佈是大型項目在發佈時的常見方法,指在發佈版本時,初始情況下,只允許小比例(比如1~5%比例的用戶使用),若出現問題時,可以快速回滾使用老版本,適用於主鏈路和訪問量極大的頁面。

好處有以下幾點:

  • 生產環境比開發環境複雜,灰度發佈時可以在生產環境小範圍嘗試觀察新版本是否可以正常運行,即使出問題,也可以控制損失。

  • 對於大版本更新,可以先灰度一部分,觀察埋點效果和用戶反饋(即所謂的搶先試用版)。假如效果並不好,那麼回滾到老版本也可以及時止損;

  • 當我們需要驗證某些想法或問題的時候,可以先灰度一部分,快速驗證效果如何,然後查漏補缺或者針對性優化;

灰度發佈通常分爲多個階段:

【1】1%;

【2】5~10%;

【3】30~50%;

【4】全量推送(100%)。

灰度發佈一定要允許配置某些IP/賬號訪問時,可以直接訪問到灰度版本。

意義:

降低風險,提高發布靈活度。

2.12、前後端分離

這個並不是指常見的前後端分離,而是指在分配前後端管控的領域。

中小項目常見的情況是後端只提供接口和讓某個url指向某個html,前端負責html、css、js等靜態資源。

但大型項目並不建議這麼做,建議前端負責除html以外的靜態資源,而html交給後端處理,理由有很多:

  • 後端進行渲染,方便統一插入一些代碼和資源,例如埋點js,監控js,國際化文本資源,頁面標識符等。這些通常是後端通過調用某些服務直接寫入的;

  • 當頁面需要統一的頭尾時(參考淘寶裏我的淘寶頁面),前端不應該關注這些跟當前頁面無關的東西;

  • 某些東西,如果通過html來管理,那麼耦合度太高了,違背瞭解耦和分離的原則;

  • 前端版本發佈在後端引入某種功能模塊後,可以從單獨的頁面控制前端發佈內容,比更新html更方便,也利於灰度發佈;

意義:

更規範的進行頁面管理,降低頁面和功能的耦合度,減少複雜頁面的環境配置時間。

2.13、Mock

Mock也是常見前端系統之一,用於解決在後端接口未好時,生成返回的數據。

我個人不太建議開發一個專門的系統來Mock,更好的Mock手法是直接嵌入到腳手架之中。思路如下:

  • 當在開發環境下,訪問鏈接通常是localhost:8000/index.html,此時加入後綴 ?debug=true;

  • 封裝好的異步請求在發現當前鏈接有以上標誌時,認爲是測試環境,訪問/userinfo 時,不去讀取線上的數據(因爲也讀取不到),去本地環境讀取 src/test_ajax/userinfo.json,並將內容返回給用戶;

  • 異步請求正常拿到數據,在頁面中顯示;

  • 當線上接口可以獲取到數據後,從network裏找到返回的數據,放入/ src/test_ajax/userinfo.json中,此時再次本地調試的話,相當於使用的是線上的真實數據。

這種處理,可以降低mock的複雜度,隨時更改mock時返回的數據,比單獨開發一個mock系統性價比更高。

意義:

在前後端並行開發時,降低溝通交流成本,方便開發完畢後直接對接。

2.14、定期備份

備份是常被忽略的一件事情,但當我們遇見毀滅性場景時,缺少備份帶來的損失是非常大的,常見場景:

  • 服務器損壞,導致存在該服務器上的內容全部完蛋;

  • 觸發某致命bug或者錯誤操作(例如rm -f),導致文件和數據全部消失;

  • 數據庫出現錯誤操作或出現問題,導致用戶數據、公司資產遭受嚴重損失;

總的來說,沒人想遇見這樣的場景,但我們必須考慮這種極端情況的發生,因此需要從架構層面解決這個問題。

常見方法是定期備份、多機備份、容災系統建設等。

意義:

避免在遭遇極端場景時,給公司帶來不可估量的損失。

3、應用層設計

3.1、多頁和單頁

除了特殊場景,通常推薦使用多頁架構。理由如下:

  • 多頁項目,頁面和頁面之間是獨立的,不存在交互,因此當一個頁面需要單獨重構時,不會影響其他頁面,對於有長期歷史的項目來說,可維護性、可重構性要高很多;

  • 多頁項目的缺點是不同頁面切換時,會有一個白屏時間,但通常來說,這個時間並不長,大部分現有大公司的線上網頁,都是這樣的,因此認爲是可以接受的;

  • 多頁項目可以單次只更新一個頁面的版本,而單頁項目如果其中一個功能模塊要更新(特別是公共組件更新),很容易讓所有頁面都需要更新版本;

  • 多頁項目的版本控制更簡單,如果需要頁面拆分,調整部分頁面的使用流程,難度也會更低;

  • 灰度發佈更友好;

之前面試的一家,採用了單頁的形式,之前因爲種種原因,同時採用了ng和react。

由於項目歷史也比較久(3年以上),結果導致目前繼續維護更新的難度很大,即使想部分重構,也很麻煩。

意義:

降低長期項目迭代維護的難度,

3.2、以應用爲單位劃分前端項目

在項目比較大的時候,將所有頁面的前端文件放入到同一個代碼倉庫裏,我之前參與過一家企業的前端項目開發,發現其就是這麼做的。

根據使用經驗來看,存在很多問題:

  • 會極大的增加代碼的維護難度;

  • 項目會變得很醜陋;

  • 不方便權限管理,容易造成頁面誤更改或代碼泄密;

  • 任何人都有權利改任何他能看到的頁面(在合併代碼的時候,管理人員並不能確定他本次修改的頁面是否是需求裏他應該改的頁面);

  • 發佈成本高,即使改一個頁面,也需要發佈所有資源;

因此,我們應該避免這種現象的發生,個人推薦以應用爲單位進行開發、發佈。

所謂應用即指一個業務涉及到的前後端代碼,好處很多:

  • 方便進行管理,當某個業務有需求變更時,可以只給研發人員該業務前端應用的developer權限;

  • 在需要發佈某業務時,只需要發佈該業務的所屬應用即可;

意義:

規範項目,增加代碼的安全性,降低項目維護成本。

3.3、基礎組件庫的建設

這個蠻基礎的,對於組件庫的建設,不建議研發人員較少時去做這件事情,專職前端開發人數少於10人時,建議使用比較靠譜的第三方UI庫,例如Antd,這樣性價比更高。

設計基礎組件庫的前提,是要求統一技術棧,這樣才能最大化基礎組件庫的效益。組件庫建議以使用以下參考標準:

  • 使用ts;

  • 可擴展性強;

  • 適用程度高;

  • 文檔清楚詳細;

  • 版本隔離,小版本優化加功能,大改需要大版本更新;

  • 和UI協調統一,要求UI交互參與進來;

總的來說,建設起來後,利大於弊,但是需要專人維護,因此還是有一定成本的。

意義:

統一不同/相同產品線之間的風格,給用戶更好的體驗,減少單次開發中寫UI組件時浪費的時間和人力,提高開發效率。

3.4、技術棧統一

前端有三大主流框架,還有兼容性最強jQuery,以及各種第三方庫,UI框架。

因此項目需求如果複雜一些,很容易形成一個大雜燴。

因此前端的技術棧必須統一,具體來說,建議實現以下舉措:

  • 三大框架選型其一,團隊水平一般推薦Vue、水平較好推薦React,對外項目選React或者ng;

  • 需要兼容IE8或更老版本時,建議使用jQuery;

  • 組件庫自建或者統一選擇一個固定的第三方;

  • 一些特殊第三方庫統一使用一個版本,例如需要使用地圖時,固定使用高德或百度或騰訊地圖;

  • 基礎設施建設應避免重複造輪子,所有團隊儘量共用,並有專門的前端平_臺負責統一這些東西,對於特殊需求,可以新建,但應當有說服力;

總的來說,技術棧統一的好處很多,可以有效提高開發效率,降低重複造輪子產生的成本。

意義:

方便招人,簡化團隊成員培養成本,以及提高項目的可持續性。

3.5、瀏覽器兼容

常見的問題是IE6、7、8,以及部分小衆瀏覽器(PC和手機)產生的奇怪問題。因此應該考慮統一解決方案,避免bug的重複產生。常見解決方案有:

  • 配置postcss,讓某些css增加兼容性前綴;

  • 寫一個wepback的loader,處理某些特殊場景;

  • 規範團隊代碼,使用更穩定的寫法(例如移動端避免使用fixed進行佈局);

  • 對常見問題、疑難問題,總結解決方案並團隊共享;

  • 建議或引導用戶使用高版本瀏覽器(比如chrome);

意義:

避免瀏覽器環境產生的bug,以及排查此類bug所浪費的大量時間。

3.6、內容平_臺建設

爲了提高公司內部的溝通效率,總結經驗,以及保密原因。

應建設一個內部論壇+博客站點。

其具備的好處如下:

  • 可以記錄公司的歷史;

  • 研發同學之間分享經驗;

  • 總結轉載一些外界比較精品的文章,提高大家的眼界;

  • 增加公司內部同學的交流,有利於公司的團隊和文化建設;

  • 對某些技術問題可以進行討論,減少因沒有達成共識帶來的溝通損耗;

衆所周知,大型互聯網公司通常都有這樣一個內部論壇和博客站點。

其降低了公司的溝通和交流成本,也增加了公司的技術積累。

意義:

博客增強技術積累,論壇增強公司內部溝通能力。

3.7、權限管理平_臺

當公司內部人員較多時,應有一個專門的平_臺,來管理、規範用戶的權限以及可訪問內容。

權限管理平_臺有幾個特點:

 

  • 必然和Server端天然高耦合度,因此需要有專門的控制模塊負責處理權限問題(負責Server端開發處理,或者前端通過中間層例如Node層介入處理);

  • 自動化流程控制,即用戶創建、申請、審批、離職自動刪除,都應該是由系統推進並提醒相關人士,必要時應能觸發報警;

  • 權限應有時效性,減少永久性權限的產生;

  • 審批流程應清晰可見,每一階段流程應具體明確;

  • 應與公司流程緊密結合,並且提高可修改性,方便公司後期進行流程優化;

意義:

使得公司內部流程正規化、信息化。

3.8、登錄系統設計(單點登錄)

當公司內部業務線比較複雜但相互之間的耦合度比較高時,我們應該考慮設計添加單點登錄系統。

具體來說,用戶在一處登錄,即可以在任何頁面訪問,登出時,也同樣在任何頁面都失去登錄狀態。SSO的好處很多:

  • 增強用戶體驗;

  • 打通了不同業務系統之間的用戶數據;

  • 方便統一管理用戶;

  • 有利於引流;

  • 降低開發系統的成本(不需要每個業務都開發一次登錄系統和用戶狀態控制);

總的來說,大中型web應用,SSO可以帶來很多好處,缺點卻很少。

意義:

用戶體驗增強,打通不同業務之間的間隔,降低開發成本和用戶管理成本。

3.9、CDN

前端資源的加載速度是衡量用戶體驗的重要指標之一。

而現實中,因爲種種因素,用戶在加載頁面資源時,會受到很多限制。

因此上CDN是非常有意義的,好處如下:

  • 用戶來自不同地區,加入CDN可以使用戶訪問資源時,訪問離自己比較近的CDN服務器,降低訪問延遲;

  • 降低服務器帶寬使用成本;

  • 支持視頻、靜態資源、大文件、小文件、直播等多種業務場景;

  • 消除跨運營商造成的網絡速度較慢的問題;

  • 降低DDOS攻擊造成的對網站的影響;

CDN是一種比較成熟的技術,各大雲平_臺都有提供CDN服務,價格也不貴,因此CDN的性價比很高。

意義:

增加用戶訪問速度,降低網絡延遲,帶寬優化,減少服務器負載,增強對攻擊的抵抗能力。

3.10、負載均衡

目前來看,負載均衡通常使用Nginx比較多,以前也有使用Apache。

當遇見大型項目的時候,負載均衡和分佈式幾乎是必須的。負載均衡有以下好處:

  • 降低單臺server的壓力,提高業務承載能力;

  • 方便應對峯值流量,擴容方便(如舉辦某些活動時);

  • 增強業務的可用性、擴展性、穩定性;

負載均衡已經是蠻常見的技術了,好處不用多說,很容易理解。

意義:

增強業務的可用性、擴展性、穩定性,可以支持更多用戶的訪問。

3.11、多端共用一套接口

目前常見場景是一個業務,同時有PC頁面和H5頁面,由於業務是一樣的,因此應避免同一個業務有多套接口分別適用於PC和H5端。

因此解決方案如下:

  • 後端提供的接口,應該同時包含PC和H5的數據(即單獨對一個存在亢餘數據);

  • 接口應當穩定,即當業務變更時,應儘量採取追加數據的形式;

  • 只有在單獨一端需要特殊業務流程時,設計單端獨有接口;

多端共用接口,是減少開發工作量,並且提高業務可維護性的重要解決方案。

意義:

降低開發工作量,增強可維護性。

4、總結

由於各個公司具體情況不同,項目也具有特殊性,因此以上設計不可強行套入,應根據自己公司規模、項目進展、人員數量等,先添加比較重要的功能和設計。

並需要考慮到長期項目的可維護性和發展需要,對部分基礎設施進行提前研發設計。

篇幅所限,因此無法面面俱到,只提了一些我認爲比較重要的架構層面需要考慮的內容,歡迎大家補充

 

 

寫下你的留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章