在上一篇文章中我介紹了咱們對N產品性能優化的整個歷程,主要偏重優化方法。本篇我將介紹在這一過程當中,咱們的代碼出現了什麼樣的問題,以及咱們是如何經過前端重構來解決掉這些問題,併產生了哪些收益。css
按需加載爲咱們的頁面帶來了很大的性能提高,但同時也爲代碼結構帶來了很大的衝擊,不少直接調用的方式被改成了模塊化的調用形式(先判斷模塊是否存在,不存在就先加載對應的js,再執行回調)。前端
而js代碼自己又不是模塊化形式的。就使得代碼結構很混亂,各類調用方式都存在,開發人員在寫代碼的時候不知道該直接調用仍是模塊化調用。jquery
打包配置混亂,散落在各個目錄結構中,常常出現重複打包和漏打包的現象,嚴重的還形成線上問題。性能優化
由於長期的產品策略變動,致使代碼不一樣功能塊之間耦合嚴重,一些關鍵方法不知道都在哪裏被調用過,若是修改的時候有遺漏,就會出現問題。網絡
沒有文檔。session
沒辦法作自動化測試。架構
由於以上問題,咱們每次產品升級都如履薄冰,須要很是當心謹慎,測試也很耗費精力。爲了提升效率,咱們必需要重構。框架
此次重構迫切要解決的問題有三點:異步
1. 代碼調用方式統一,但願加載方式能夠對開發人員透明。ide
2. 模塊職責明確、模塊之間依賴關係清晰。
3. 按需加載的配置能夠統一管理,不影響開發時的效率。
這三點,讓我很天然地就想到了JS模塊化開發
關於模塊化框架和CommonJS規範,在網上有不少介紹的文章,我就不在這裏贅述了。我只說最關鍵的一點:每一個模塊都有明確的定義(模塊名、輸入、輸出),模塊之間的依賴和調用必須經過require或use的形式。以下圖是一個common/pop模塊的示例代碼:
這種設計帶給咱們最大的好處是:規範了代碼之間的調用方式,開發人員在寫use的時候,不用擔憂這個模塊是否已經被加載,全部的加載策略和打包策略都對他是透明的。
如上面說到的,按照CommonJS規範,模塊之間有require和use兩種依賴形式,咱們加入了第三種:fire(事件觸發)。經過自定義事件的監聽和觸發,咱們實現一種弱依賴的形式。
fire適用於投統計、異常處理等場景,不會觸發代碼加載。
將之前分散在各個地方的打包策略合併到同一個配置文件中,以下圖(示例代碼):
它起到兩個做用:1. 保證項目編譯的時候將模塊打包到對應文件;2. 在使用模塊的時候,去檢測它所在的js文件是否已經加載,若是沒有則自動加載。
能夠看到,咱們對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