內容簡介
涉及底層網路到上層框架值得長期投入眾課題。三位一體思路:性能度量+工具分析+最佳化解決。從用戶體驗角度理解瀏覽器處理頁面生命流程。剖析數據收集分析、各項性能指標定義及最佳化。
圖書目錄
第 1 篇 從 Vite 起步
第 1 章 從實踐開始 ··························· 2
1.1 Hello World ···························· 2
使用 DevTools ····················· 4
第一個最佳化 ························ 6
1.2 現實開發的例子 ······················· 7
設定開發環境 ······················ 7
Vite ································· 8
vite build ··························· 9
進一步最佳化 ······················ 11
引入 antd ························· 11
按需引入 ························· 13
動態 import ······················ 14
1.3 小結 ································· 15
第 2 篇 性能最佳化方法論
第 2 章 度量 ································· 18
2.1 科學的方法 ·························· 19
從一個客戶反饋說起 ··········· 19
不度量性能,就無法最佳化性能 ······························· 19
真實的用戶端性能 ·············· 20
2.2 初識 Performance API ··············· 21
構建首屏指標 ···················· 23
2.3 均值、分位數和秒開率 ············· 23
均值 ······························ 24
分位數 ···························· 25
秒開率 ···························· 26
如何選擇合適的統計指標 ······ 26
2.4 度量首屏 ···························· 27
FP ································· 27
FCP ······························· 27
FMP ······························ 28
如何度量 FMP ··················· 28
選定並度量首屏 ················· 30
2.5 度量流暢度 ·························· 30
度量流暢度的指標 ·············· 31
可視化工具 ······················ 31
用戶端度量 ······················ 32
2.6 Core Web Vitals ····················· 34
LCP ······························· 34
FID ································ 38
CLS ······························· 39
2.6 小結 ·································· 41
第 3 章 分析 ································· 42
3.1 分析方法 ···························· 43
確定目標 ························· 43
收集數據 ························· 43
清洗數據 ························· 44
統計值分析 ······················ 44
時序分析 ························· 45
維度分析 ························· 46
相關性分析 ······················ 48
3.2 常用的過程指標 ····················· 48
TTFB ····························· 49
DOMReady 和 Load ············· 50
3.3 Performance API 詳解 ··············· 51
Navigation Timing API ·········· 51
Peformance Entry API ··········· 53
Resource Timing ················· 54
Navigation Timing Level 2 ······ 55
Paint Timing ····················· 56
User Timing ······················ 56
3.4 分階段性能分析 ···················· 58
常用的指標 ······················ 58
其他值得分析的指標 ··········· 59
3.5 小結 ································· 59
第 4 章 實驗 ································· 60
4.1 最佳化不是照搬軍規 ·················· 61
時代在發展 ······················ 61
最佳化的木桶效應明顯 ··········· 62
用戶環境差異大 ················· 62
性能實驗 ························· 62
4.2 用實驗驗證最佳化 ···················· 63
混沌問題 ························· 64
設計實驗 ························· 64
分桶 ······························ 65
上報和分析數據 ················· 68
A/B Test 背後的數學 ············ 68
結論不重要,重要的是方法 ··· 69
4.3 用實驗改進最佳化 ···················· 69
建立模型 ························· 69
實驗修正 ························· 70
4.4 小結 ································· 71
第 5 章 工具 ································· 72
5.1 DevTools ···························· 73
Network 面板 ···················· 73
Performance 面板 ················ 76
5.2 WebPageTest ························ 81
發起測試 ························· 82
報告 ······························· 83
Waterfall 視圖 ··················· 83
5.3 小結 ································· 87
第 3 篇 網路協定與性能
第 6 章 TTFB 為什麼這么長 ··············· 90
6.1 TTFB 的合理值 ····················· 91
精確定義 ························· 92
RTT ······························· 92
RTT 一般需要多久 ·············· 93
TTFB 的構成····················· 93
實驗環境驗證 ···················· 94
6.2 如何最佳化 TTFB ····················· 95
減少請求的傳輸量 ·············· 96
減少伺服器端的處理時間 ······ 96
減少 RTT ························· 98
TTFB 的值越小越好嗎 ·········· 98
6.3 小結 ·································· 99
第 7 章 建立連線為什麼這么慢 ·········· 100
7.1 建立連線應該耗時多久 ············ 101
TCP 協定 ························ 101
建立連線需要多少個 RTT ····· 101
抓包驗證 ························ 102
7.2 如何最佳化建立連線的耗時 ········· 103
減少物理距離 ··················· 103
preconnect ······················· 103
復用連線 ························ 103
域名收攏 ························ 104
TCP Fast Open ·················· 104
QUIC 和 HTTP/3 ··············· 104
7.3 小結 ································ 105
第 8 章 Fetch 之前瀏覽器在乾什麼 ····· 106
8.1 重定向 ······························ 107
HTML 重定向 ·················· 109
有哪些重定向 ·················· 109
8.2 瀏覽器打開耗時 ··················· 112
初始化標籤頁的時間 ·········· 112
unload 的耗時 ··················· 112
8.3 如何最佳化 beforeFetch 耗時 ········ 114
重定向邏輯前置 ················ 115
合併重定向 ····················· 115
避免使用短鏈 ·················· 116
使用 beforeFetch 度量和分析 ····························· 116
8.4 小結 ································ 117
第 9 章 HTTPS 協定比 HTTP 協定
更慢嗎 ····························· 118
9.1 HTTPS 協定為什麼安全 ··········· 119
對稱加密和非對稱加密 ········ 119
SSL/TLS 的實現 ················ 120
SSL/TLS 握手 ·················· 122
TLS False Start ·················· 124
TLS 1.3 ·························· 124
9.2 HTTPS 協定如何吊銷證書 ········· 125
CRL ······························ 125
OCSP ···························· 126
OCSP Stapling ·················· 126
瀏覽器支持的情況 ············· 126
證書類型 ························ 127
證書驗證機制對性能的影響 ···· 129
9.3 HTTPS 協定更慢嗎 ················ 129
確保證書鏈完整 ················ 129
啟用 TLS 1.3 ···················· 129
不濫用 EV 證書 ················ 130
開啟 OSCP Stapling ············ 130
9.4 小結 ································· 130
第 10 章 HTTP/2、HTTP/3 和性能 ······ 131
10.1 HTTP/2 和性能 ···················· 131
連線復用為什麼不生效 ······· 131
頭部壓縮對我們有什麼影響 ··· 137
為什麼沒有廣泛使用 Server Push ···························· 140
10.2 為什麼還需要 HTTP/3 ············ 144
HTTP/2 存在什麼問題 ········ 145
HTTP/3 如何解決問題 ········ 146
10.3 小結 ······························· 148
第 11 章 壓縮和快取 ······················ 150
11.1 傳輸速度和壓縮速度如何兼得 ···· 151
Content-Encoding ·············· 151
gzip 壓縮和 br 壓縮 ··········· 152
實時壓縮 ······················· 152
離線壓縮 ······················· 153
如何最佳化傳輸性能 ············ 154
11.2 HTTP 快取什麼時候會失效 ······ 154
快取不僅僅是瀏覽器的事情 ···························· 154
快取 Header ···················· 154
11.3 小結 ······························· 157
第 4 篇 瀏覽器與性能
第 12 章 瀏覽器和性能 ···················· 160
12.1 第一次渲染時都發生了什麼 ····· 161
最小的渲染路徑 ··············· 162
儘快返回 HTML ··············· 167
減少資源的阻塞 ··············· 167
12.2 為什麼 DOM 操作很慢 ··········· 168
幀 ··································· 168
重排 ································ 169
重繪 ································ 170
訪問 DOM 屬性 ················· 170
如何最佳化 DOM 操作 ··········· 171
12.3 小結 ······························· 172
第 13 章 異步任務和性能 ················· 173
13.1 事件循環機制 ····················· 174
為什麼要有事件循環 ········· 174
多執行緒阻塞模型 ··············· 174
事件循環 ······················· 175
13.2 宏任務和微任務 ·················· 176
13.3 Promise 的 polyfill 性能 ··········· 178
如何正確實現 Promise ········ 178
13.4 requestAnimationFrame ··········· 180
13.5 小結 ······························· 181
第 14 章 記憶體為什麼會影響性能 ········· 182
14.1 記憶體 ······························· 182
記憶體管理 ·························· 183
14.2 記憶體泄漏 ·························· 188
記憶體泄漏和性能 ··············· 188
常見的導致記憶體泄漏的原因 ··· 188
記憶體泄漏問題的診斷工具 ···· 189
14.3 小結 ······························· 191
第 15 章 使用 ServiceWorker 改善性能 ······························· 193
15.1 ServiceWorker 概述 ··············· 194
AppCache······················· 194
ServiceWorker·················· 195
ServiceWorker 能做什麼 ······ 195
15.2 使用 ServiceWorker 進行快取 ···· 196
Cache API ······················ 196
IndexDB ························ 201
控制快取的 Cache Key ······· 201
更加靈活的快取更新策略 ···· 203
15.3 API 提前載入 ····················· 204
15.4 ServiceWorker 冷啟動 ············ 205
開啟 Navigation Preload ······ 206
消費 Navigation Preload ······ 206
15.5 小結 ······························· 207
第 16 章 字型對性能的影響 ·············· 208
16.1 字型導致的布局偏移 ············· 208
如何定位布局偏移 ············ 208
16.2 如何避免字型帶來的布局偏移 ···· 210
如何儘快載入字型 ············ 211
字型檔的格式 ··············· 211
字型的載入 ···················· 212
預載入字型 ···················· 213
裁剪字型的大小 ··············· 214
16.3 小結 ······························· 214
第 5 篇 前端工程與性能
第 17 章 構建工具和性能 ················· 218
17.1 為什麼需要打包 ·················· 219
CommonJS ····················· 220
AMD ···························· 220
CMD ···························· 221
異步模組載入器 ··············· 222
依賴載入最佳化 ················· 223
模組打包器 ···················· 224
ES Module ····················· 225
17.2 構建工具可以做什麼 ············· 226
構建工具和構建最佳化 ········· 227
為什麼要最佳化打包體積 ······ 227
Bundle 分析 ···················· 228
Tree Shaking ··················· 229
Scope Hoisting ················· 231
Code Splitting ·················· 233
代碼壓縮 ······················· 234
Vite 和 Bundleless ············· 237
17.3 小結 ······························· 237
第 18 章 伺服器端渲染和性能 ··········· 239
18.1 SSR 和同構 ······················· 241
18.2 SSR 的性能最佳化 ·················· 241
快取 ································ 242
數據預取 ·························· 245
按需渲染 ·························· 245
流式渲染 ·························· 246
18.3 小結 ······························· 246
第 6 篇 跨端技術與 CDN
第 19 章 WebView 和性能 ················ 248
19.1 WebView 和 Native 的區別 ······· 249
LayoutInflater ·················· 249
載入 XML 的具體過程 ······· 250
Measure ························· 250
Layout ·························· 251
Paint ···························· 252
Surface ·························· 253
SurfaceFlinger ·················· 253
差異 ····························· 253
19.2 WebView 的通信成本 ············ 254
JavaScript 調用 Native ········· 254
Native 調用 JavaScript ········· 258
雙向通信 ······················· 258
通信對性能的影響 ············ 259
減少通信數據量 ··············· 259
避免頻繁通信 ·················· 259
19.3 React Native 的懶載入有何不同 ······························· 260
Web 實現 ······················ 260
基於滾動容器的懶載入 ······ 260
基於位置獲取的懶載入 ······ 262
虛擬列表 ······················· 263
19.4 React Native 如何減小打包體積 ······························· 265
Metro ··························· 265
度量 ···························· 266
分析 ···························· 266
手動 Tree Shaking ············· 267
利用 Babel 外掛程式進行最佳化 ···· 269
體積和性能的關係 ············ 271
19.5 API 並行請求 ····················· 271
發起請求 ·························· 272
請求攔截 ·························· 273
一致性檢驗 ······················· 274
命中率分析 ······················· 274
19.6 小結 ······························· 274
第 20 章 CDN 和性能 ····················· 275
20.1 什麼是 CDN ······················· 275
解析 ································ 276
邊緣節點 ·························· 276
回源 ································ 277
快取策略 ·························· 277
20.2 如何提升快取命中率 ············· 278
如何在端側統計快取命中的情況 ····························· 278
減少快取分裂 ·················· 279
快取忽略動態參數 ············ 279
歸一化 Vary Header ··········· 280
長效快取 ······················· 280
20.3 動態加速 ·························· 281
海外加速 ·························· 282
連線復用 ·························· 282
客戶端連線復用 ················· 282
HTTPS 最佳化 ······················ 283
動靜分離 ·························· 283
壓縮 ································ 284
什麼場景適合使用動態加速 ··· 284
20.4 自動 polyfill ······················· 284
什麼是 polyfill ················· 284
Polyfill.io ······················· 285
實現原理 ······················· 287
20.5 邊緣計算和性能 ·················· 288
CDN 的可程式功能 ··········· 288
Hello World ···················· 289
自定義 Cache Key ············· 289
前置重定向 ···················· 290
流式渲染 ······················· 290
20.6 小結 ······························· 291