前端重構實踐(二) —— 模塊化開發

  • 前言:

在上一篇文章中我介紹了我們對N產品性能優化的整個歷程,主要偏重優化方法。本篇我將介紹在這一過程中,我們的代碼出現了什麼樣的問題,以及我們是如何通過前端重構來解決掉這些問題,併產生了哪些收益。


  • 痛點

按需加載爲我們的頁面帶來了很大的性能提升,但同時也爲代碼結構帶來了很大的衝擊,很多直接調用的方式被改爲了模塊化的調用形式(先判斷模塊是否存在,不存在就先加載對應的js,再執行回調)。

 

而js代碼本身又不是模塊化形式的。就使得代碼結構很混亂,各種調用方式都存在,開發人員在寫代碼的時候不知道該直接調用還是模塊化調用。

打包配置混亂,散落在各個目錄結構中,經常出現重複打包和漏打包的現象,嚴重的還造成線上問題。

因爲長期的產品策略變更,導致代碼不同功能塊之間耦合嚴重,一些關鍵方法不知道都在哪裏被調用過,如果修改的時候有遺漏,就會出現問題。

沒有文檔。

沒辦法做自動化測試。

  • 思考

因爲以上問題,我們每次產品升級都如履薄冰,需要非常小心謹慎,測試也很耗費精力。爲了提高效率,我們必須要重構。

這次重構迫切要解決的問題有三點:

1. 代碼調用方式統一,希望加載方式可以對開發人員透明。

2. 模塊職責明確、模塊之間依賴關係清晰。

3. 按需加載的配置可以統一管理,不影響開發時的效率。

這三點,讓我很自然地就想到了JS模塊化開發

  • 模塊化開發:

關於模塊化框架和CommonJS規範,在網上有很多介紹的文章,我就不在這裏贅述了。我只說最關鍵的一點:每個模塊都有明確的定義(模塊名、輸入、輸出),模塊之間的依賴和調用必須通過require或use的形式。如下圖是一個common/pop模塊的示例代碼:


這種設計帶給我們最大的好處是:規範了代碼之間的調用方式,開發人員在寫use的時候,不用擔心這個模塊是否已經被加載,所有的加載策略和打包策略都對他是透明的。

  • 模塊依賴 & 自定義事件

如上面說到的,按照CommonJS規範,模塊之間有require和use兩種依賴形式,我們加入了第三種:fire(事件觸發)。通過自定義事件的監聽和觸發,我們實現一種弱依賴的形式。

fire適用於投統計、異常處理等場景,不會觸發代碼加載。

  • 打包配置:

將以前分散在各個地方的打包策略合併到同一個配置文件中,如下圖(示例代碼):

它起到兩個作用:1. 保證項目編譯的時候將模塊打包到對應文件;2. 在使用模塊的時候,去檢測它所在的js文件是否已經加載,如果沒有則自動加載。

可以看到,我們對css也做了同樣的模塊化加載的處理。

  • 文件加載 & CSS模塊化

對於按需加載的組織形式而言,文件的加載監控很重要。

早期我們對CSS做延遲加載的時候,碰到一個情況:由於這部分CSS加載是異步的,如果網絡狀況不好,就可能出現JS已經將頁面元素組裝好了,但是CSS還沒加載完成,這一部分頁面就會亂掉。後來我們採用了“先隱藏元素,等CSS加載結束再重寫display屬性來顯示元素”的方法,避免了這種case。不過這畢竟不是一個系統化的解決辦法。

如何鑑定文件加載的結束,特別是CSS文件的加載結束是個蠻有學問的事情。在框架中對於文件的下載監控,我們借鑑了SeaJS的思想,對於這塊感興趣的同學可以深入研究一下。

  • 整體架構

基礎層是對一些基礎模塊和session數據的封裝,這些方法每個模塊都會用到,就不再做單獨的require,打包成ctx變量傳入每個模塊的定義中進行使用。

應用層是具體的產品功能開發,對於數據的處理統一使用view/model/service的形式,由view從模板的textarea(性能優化考慮)中提取數據建立model,由service統一向server端發送異步請求進行持久化。

通用層是業務邏輯無關的組件,很多產品都可以複用,如分頁、截字、彈層、類定義等。

物理層:通過config.js來統一配置按需加載的打包策略,並在模板中對編譯加戳後的物理文件進行引用。

  • 代碼文檔:

既然每個模塊都有統一的定義方式,模塊之間的依賴和調用也有統一的形式,那麼我們通過對代碼進行自動分析,就生成了類似如下形式的代碼文檔

每個模塊的依賴與被依賴、調用與被調用信息,一目瞭然。

開發人員利用這個文檔可以清楚的知道他的每次修改都可能會影響到哪些模塊。

QA人員可以根據每次提測的模塊列表,評估出可能會影響到的case範圍。

這對於開發和測試的效率提升不言而喻。

最重要的是,這是有生命力的文檔,不需要維護,每次代碼寫完後就可以自動生成。

  • 單元測試:

按照模塊化進行重構之後,我們可以針對單個組件寫case進行測試。這裏用到了Qunit框架。效果如下圖:

  • 問題:

當然,模塊化框架並非前端開發的銀彈。我們在重構過程中也碰到了“不好調試”、“出現循環依賴後不好定位”等問題。這也是我們接下來要嘗試解決的方向。

另外,重構後我們發現,框架本身和模塊配置打包的代碼,合併壓縮後也有4-5k,這對於性能優化並沒有太大的幫助。

  • 總結:

模塊化框架對於按需加載、模塊劃分、代碼複用、自動文檔、單元測試、團隊合作等都有很大的幫助。

本次重構規範了JS和CSS的模塊化使用,讓模塊劃分變得更清晰,讓開發變得更單純,爲以後的升級維護奠定了一個很好的基礎,提高了測試的效率,並且使得“單元測試”,“自動化測試”,和“敏捷開發持續集成”等 成爲了可能。

本次重構還沒有對HTML做模塊化拆分,所以還沒辦法做到“模板的獨立渲染”。這會是我們團隊後續的工作方向之一。

by lizhouquan

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