# 知識體系與小冊格局
## 寫給讀者
提起性能優化,大家現在腦海里第一時間會映射出什么內容呢?
可能是類似[“雅虎軍規”](https://developer.yahoo.com/performance/rules.html?guccounter=1)和[《高性能 JavaScript》](https://book.douban.com/subject/5362856/)這樣歷久彌香的經典之作,也可能是搜索引擎聚合給你的一篇又一篇以性能優化為主題的個人或團隊實踐而來的“私貨”。至少當我確定自己的研發方向、并接到第一個性能優化任務時,我做的第一件事是向搜索引擎求助,第二件事是買書,然后開始了摸著石頭過河,前后花費了大量的時間和精力。我深感性能優化實在是前端知識樹中特別的一環——當你需要學習前端框架時,文檔和源碼幾乎可以告訴你所有問題的答案,當你需要學習 Git 時,你也可以找到放之四海皆準的實踐方案。但性能優化卻不一樣,它好像只能是一個摸索的過程。
這個摸索的過程是痛苦的、漫長的,也是緊要的。因為在如今的互聯網環境下,一個前端團隊如果只把性能優化這個任務寫在紙上,而不投入實踐,它將缺失最基本的競爭力。
筆者寫這本小冊,是希望通過短短十數個章節的講解,盡可能降低一些大家學習性能優化的成本。
一方面,這本小冊為沒有接觸過性能優化的新同學建立起一個正確的前端性能優化的“世界觀”,知道性能優化是什么、為什么、怎么做,從而使性能優化這件事情有跡可循,有路可走。這樣在面試現場被問到性能優化層面的問題時,能夠做到滔滔不絕、言之有物,而非像背書一樣羅列干巴巴的知識點,最終淹沒在茫茫的求職大軍中。另一方面,小冊可以為在職的工程師們提供一線團隊已經實踐過的“方法論”,知道什么場景下該做什么事情,最終在腦海中留下一張涵蓋核心原理和實踐的、可隨時查閱并且高度可擴展的性能優化思路索引表。然后在今后的開發生活中可以去踐行它,更進一步去挖掘它。把性能優化變作你前端工程師生涯的一門必修課,進而演化為自己研發方面的核心競爭力。
同時,相信大家可以明確這樣一個學習觀念:任何技術的掌握,都離不開一定比例的理論基礎和實際操作的支撐。
具體到前端性能優化這件事情上,我認為它是 20% 的理論,加上至少 80% 的實踐,甚至很多理論本身也都是我們在具體的業務場景中實踐出來的。所以希望大家閱讀本小冊時,能夠讀到一些“書本之外的東西”——最好是一邊讀一邊回憶自己既有的開發經歷,嘗試去留意哪些知識是已知的,哪些是未知的。
這樣讀完之后,就可以有的放矢地把這些知識轉換為自己的項目實踐——前端技術日新月異,性能方案永遠都在更迭,所以一定要形成自己的學習思路。
建議每一位讀者都帶著“學了就要用”的心態去讀這本小冊。如果閱讀結束,能夠為你帶來哪怕一個小小的開發習慣或者優化觀念上的改變,這數小時的閱讀時間就算沒有白費。
## 知識體系: 從一道面試題說起
在展開性能優化的話題之前,我想先拋出一個老生常談的面試問題:
> 從輸入 URL 到頁面加載完成,發生了什么?
這個問題非常重要,因為我們后續的內容都將以這個問題的答案為骨架展開。我希望正在閱讀這本小冊的各位可以在心里琢磨一下這個問題——無須你調動太多計算機的專業知識,只需要你用最快的速度在腦海中架構起這個抽象的過程——我們接下來所有的工作,就是圍繞這個過程來做文章。
我們現在站在性能優化的角度,一起簡單地復習一遍這個經典的過程:首先我們需要通過 DNS(域名解析系統)將 URL 解析為對應的 IP 地址,然后與這個 IP 地址確定的那臺服務器建立起 TCP 網絡連接,隨后我們向服務端拋出我們的 HTTP 請求,服務端處理完我們的請求之后,把目標數據放在 HTTP 響應里返回給客戶端,拿到響應數據的瀏覽器就可以開始走一個渲染的流程。渲染完畢,頁面便呈現給了用戶,并時刻等待響應用戶的操作(如下圖所示)。

我們將這個過程切分為如下的過程片段:
1. DNS 解析
2. TCP 連接
3. HTTP 請求拋出
4. 服務端處理請求,HTTP 響應返回
5. 瀏覽器拿到響應數據,解析響應內容,把解析的結果展示給用戶
大家謹記,我們任何一個用戶端的產品,都需要把這 5 個過程滴水不漏地考慮到自己的性能優化方案內、反復權衡,從而打磨出用戶滿意的速度。
## 從原理到實踐:各個擊破
我們接下來要做的事情,就是針對這五個過程進行分解,各個提問,各個擊破。
具體來說,DNS 解析花時間,能不能盡量減少解析次數或者把解析前置?能——瀏覽器 DNS 緩存和 DNS prefetch。TCP 每次的三次握手都急死人,有沒有解決方案?有——長連接、預連接、接入 SPDY 協議。如果說這兩個過程的優化往往需要我們和團隊的服務端工程師協作完成,前端單方面可以做的努力有限,那么 HTTP 請求呢?——在減少請求次數和減小請求體積方面,我們應該是專家!再者,服務器越遠,一次請求就越慢,那部署時就把靜態資源放在離我們更近的 CDN 上是不是就能更快一些?
以上提到的都是網絡層面的性能優化。再往下走就是瀏覽器端的性能優化——這部分涉及資源加載優化、服務端渲染、瀏覽器緩存機制的利用、DOM 樹的構建、網頁排版和渲染過程、回流與重繪的考量、DOM 操作的合理規避等等——這正是前端工程師可以真正一展拳腳的地方。學習這些知識,不僅可以幫助我們從根本上提升頁面性能,更能夠大大加深個人對瀏覽器底層原理、運行機制的理解,一舉兩得!
我們整個的知識圖譜,用思維導圖展示如下:

## 小冊格局
總的來說,我們將從**網絡層面**和**渲染層面**兩個大的維度來逐個點亮前端性能優化的技能樹。
這兩個維度的知識面貌各有千秋:在網絡層面,我們需要學習一些必需的理論基礎作為前置知識。這部分的學習或許不需要大家寫特別多的代碼,但需要大家對每一個知識點理解透徹,進而應用到自己日常優化的決策中去。網絡層面結束后,由本地存儲開始,我們會漸漸過渡到瀏覽器這一端的優化,大家喜聞樂見的“真代碼”就會相應地多起來。
為了使同學們耐心學習一些理論性稍強的知識,我也會盡自己所能去講述得有趣、易讀、可用,同時希望大家可以真的沉下心去理解這些知識,它們與大家喜聞樂見的框架和工具無異,一樣是實實在在的生產力。
“經驗豐富的人讀書用兩只眼睛,一只眼睛看到紙面上的話,另一只眼睛看到紙的背面”。在這本小冊,代碼片段固然有用,它們是“紙面上的話”,我自然希望大家可以記下來、用起來。而代碼之外那些反復講解的原理,則是“紙的背面”,同樣是我希望引起大家重視的內容。
現在相信大家已經對我們的優化觀念、知識結構、小冊格局都有了基本認知,那么我們就趕快趁熱打鐵,進入實戰技能的學習吧~
- 開篇:知識體系與小冊格局
- 網絡篇 1:webpack 性能調優與 Gzip 原理
- 網絡篇 2:圖片優化——質量與性能的博弈
- 存儲篇 1:瀏覽器緩存機制介紹與緩存策略剖析
- 存儲篇 2:本地存儲——從 Cookie 到 Web Storage、IndexDB
- 彩蛋篇:CDN 的緩存與回源機制解析
- 渲染篇 1:服務端渲染的探索與實踐
- 渲染篇 2:知己知彼——解鎖瀏覽器背后的運行機制
- 渲染篇 3:對癥下藥——DOM 優化原理與基本實踐
- 渲染篇 4:千方百計——Event Loop 與異步更新策略
- 渲染篇 5:最后一擊——回流(Reflow)與重繪(Repaint)
- 應用篇 1:優化首屏體驗——Lazy-Load 初探
- 應用篇 2:事件的節流(throttle)與防抖(debounce)
- 性能監測篇:Performance、LightHouse 與性能 API
- 前方的路:希望成為你的起點