問題場景:
在使用前端框架構建單頁應用時,伺服器會返回一份html檔案、抽取出來的css檔案和一份打包好的js檔案。html體積是極小的,相當於只提供了一個舞臺,而頁面結構的生成和更新完全由js根據路由和框架特點、業務邏輯來控制,加上css樣式渲染出完整的頁面。打包後的js檔案包括了框架和依賴庫(react、react-router等)還有業務邏輯程式碼,所以功能越複雜,體積很大。
問題原因分析:
瀏覽器從輸入url到完成顯示頁面有一個複雜的過程,這裡從載入檔案開始分析。瀏覽器解析獲得的html文件並生成DOM樹,當瀏覽器解析到外部的script時,解析會暫停,併傳送請求來載入script檔案並執行,然後才會繼續解析DOM。這就導致了過大的外部js檔案拖慢了頁面的載入渲染。有人提出可以加入 defer 屬性支援同步載入和瀏覽器快取策略,但這只是有限的優化手段,請求時間和執行時間過長也會影響到首屏的載入,影響了使用者體驗。
程式碼拆分原理
對於單頁應用來說,頁面是根據路由區分的,程式碼拆分其實就是按照頁面來拆分,每個頁面都對應一個分片。對多個頁面共享的程式碼又獨立拆分出來,對於有很多頁面和複雜依賴的應用,共享程式碼還可以進一步拆分為所有頁面共享的(React框架程式碼)和部分頁面共享的(元件模組),這樣當一個頁面載入時只需要載入頁面自己的分片和共享的分片就行,很大地提高了首屏渲染的速度。
三點注意:
- 使用webpack拆分。webpack 是根據依賴關係進行打包的模組打包工具。根據import()動態匯入的方式進行頁面、元件分片。拆分框架程式碼有兩種方式:一是使用SplitChunksPlugin將框架程式碼拆分並與其他分片放在一起;二是使用DllPlugin將框架程式碼拆分放在靜態資源伺服器上,html頁面上使用script引入,應用打包時配置對映關係檔案。對比SplitChunksPlugin的優點是可以將框架程式碼檔案放在cdn伺服器並配置強制快取,進一步提高載入速度。
- 由於程式碼拆分主要是針對首次首屏渲染的優化,所以頁面不能拆得太分散,3~4個為宜。
- 使用相應的程式碼拆分方案。比如React 程式碼拆分 和 Vue 的動態元件