owned this note changed 4 years ago
Linked with GitHub

你的 JS 該減肥了!5個提升網頁載入速度的技巧 / Shubo(趙勗博)

歡迎來到 Modern Web 2020 共筆

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

共筆入口:https://hackmd.io/@ModernWeb/2020
手機版請點選上方 按鈕展開議程列表。

簡報下載

共筆從這開始

前端工程師都該懂的6個網頁載入加速技巧 (加速 30% 真實案例分享) | Shubo’s Notes

1. 優化網頁載入速度

為什麼要加快載入速度

  • 載入速度 = 使用者體驗
  • 根據 Amazon 內部統計,慢 100ms = 營收減少 1%
  • SEO

第一步:善用測速工具

如何決定優化的優先順序

  • 修正以後改善最多的項目
  • 業務範圍中最容易改動的部分
  • 先做出成果,得到主管信任,爭取更多優化空間
  • 例:優化圖片尺寸,涉及 app 上傳 / 後端處理
  • 例:優化 JavaScript bundle 體積,前端可自己修改 build 設定 (優先優化圖片尺寸)

2. 我的JS很肥會怎樣嗎?

瀏覽器運作原理

  • 結論: JS bundle 越大,網頁載入越慢
  • 瀏覽器:解析 HTML > 建立 DOM TREE > 渲染頁面
  • JS "blocks" DOM tree 的建立過程
  • 下載 + 執行 JS 越慢,block 越久,越慢渲染畫面

Code Splitting

  • 將單一JS檔案拆分成許多小塊
    • 平行載入
    • 有需要時才載入
    • 各自可被快取

3. 拆分出Vendor Bundle

  • Webpack runtime and manifest: 負責模組之間互動,體積可忽略不計
  • Application Bundle: UI / 商業邏輯,經常變動
  • Vendor Bundle: 第三方套件 / node_modules,不太變動

Why Vendor Bundle?

  • 通常變動不頻繁
  • 可被快取
  • 此配置在有 cache 情況下載入更快

未優化Bundle的規劃

桌機版 手機版 說明
arcade.js 585KB 426KB 商業邏輯
omlib.js 205KB 205KB 內部 lib/ API
vendor.js 366KB 366KB 第三方套件
sum 1156KB 997KB

運用工具分析配置是否合理

  • 運⽤ webpack-bundle-analyzer 作視覺化分析
  • application bundle
    • 裡⾯有 node_modules
    • 併入 vendor bundle 更好

取出 Vendor bundle

  • 將 node_modules 統一打包成 vendor.js
  • 結果
桌機版 手機版 說明
arcade.js 585KB 310KB 426KB 218KB 商業邏輯
omlib.js 205KB 205KB 內部 lib/ API規格
vendor.js 366KB 632KB 366KB 632KB 第三方套件
sum 1156KB 997KB1055KB*

效果:減少 application bundle 的⼤⼩,加快再訪者載入速度

4. Dynamic Loading

  • 對新用戶而言,網站整體大小不變
  • 如何減少整體下載量?動態下載需要的模組
  • ⽤到某段程式碼的時候才透過網路下載 JS bundle

ESM import()

  • Webpack 支援 ESM import() 語法實現 dynamic import

根據路徑做 Dynamic Import

  • 為何根據路徑?
    • GA數據顯⽰使⽤者⼤多停留在熱⾨⾴⾯,換⾴次數少
  • react-router ⽀援 dynamic import
桌機版 手機版 說明
arcade.js 310KB 235KB 218KB 189KB 商業邏輯
omlib.js 205KB 205KB 第三方套件
vendor.js 632KB 632KB 內部 lib/ API規格
sum 1156KB 1072KB* 1055KB 1026KB* * 體積最⼤的⾸⾴~20KB

效果:減少 application bundle 下載量

對肥大套件做 Dynamic import

  • 哪些套件適合 dynamic import?
    • 很肥大
    • 使用頻率低
    • eg. JSZip (27KB), moment.js (64KB), request (70KB), hls.js (77KB)
  • 結果
桌機版 手機版 說明
arcade.js 235KB 189KB 商業邏輯
omlib.js 205KB 205KB 內部 lib/ API規格
vendor.js 632KB 267KB 632KB 267KB 第三方套件
sum 1072KB 784KB* 1026KB 707KB* * 以使⽤頻率最⾼的⾸⾴為例

效果:⼤幅減少整體下載量

5. Tree-Shaking

  • 將沒有用到的程式碼從 JS bundle 中移除
  • 必須使用 ESM import/export (靜態結構)

如何設定 Tree-shaking

  • 將專案中 CommonJS 的 require/module.exports 語法改寫成 ES Module 的 import/export 語法
  • 在 package.json 中標示具有 side effets 的模組(例如CSS)
  • 結果
桌機版 手機版 說明
arcade.js 235KB 189KB 商業邏輯
omlib.js 205KB 87KB 205KB 87KB 內部 lib/ API規格
vendor.js 267KB 267KB 第三方套件
sum 784KB 666KB* 707KB 589KB*

效果:⼤幅減少整體下載量

6. 其他小技巧

第三方套件使用 CDN 版本

  • 經常被使用的第三方套件 eg. React/jQuery
  • 容易被快取
  • react-dom: 36KB

使用 preset-env 減少 Polyfill 體積

  • Polyfill: 讓舊的瀏覽器也能支援新的 API
  • preset-env: preset-2015 的加強版
    • preset: babel-loader的語法 plugin 集合
    • 根據支援瀏覽器清單,自動引入polyfill
    • 結果:31KB 18KB
  • 最終結果
桌機版 手機版 說明
arcade.js 585KB 235KB 426KB 189KB 商業邏輯
omlib.js 205KB 87KB 205KB 87KB 內部 lib/ API規格
vendor.js 366KB 267KB 366KB 267KB 第三方套件
sum 1156KB 666KB(-43%) 997KB 589KB* (-41%)

根據 GA 數據,平均載入所需時間減少 30%

結論

  • 拆分出 vendor bundle
  • 根據路徑做 dynamic import
  • 對肥大第三方套件做 dynamic import
  • 使用 tree shaking 移除沒用到的程式碼
  • 熱門第三方套件使用 CDN 版本
  • 使用 preset-env 減少 Polyfill 體積
tags: MW20 維運與測試 負載平衡
Select a repo