關(guān)鍵環(huán)節(jié))
1. 從URL到頁面渲染的全鏈路解析作為一名前端工程師我經(jīng)常被問到從輸入U(xiǎn)RL到頁面顯示發(fā)生了什么這個(gè)問題。說實(shí)話第一次被問到時(shí)我也只能回答出DNS解析、建立連接、下載資源、渲染頁面這樣的籠統(tǒng)答案。直到后來參與了幾次大型項(xiàng)目的性能優(yōu)化才真正理解這個(gè)過程中每個(gè)環(huán)節(jié)的細(xì)節(jié)和陷阱。這個(gè)看似簡(jiǎn)單的問題實(shí)際上涵蓋了網(wǎng)絡(luò)協(xié)議棧、瀏覽器引擎、渲染管線等計(jì)算機(jī)科學(xué)的多個(gè)核心領(lǐng)域。根據(jù)我的實(shí)踐經(jīng)驗(yàn)完整的流程至少包含20個(gè)關(guān)鍵環(huán)節(jié)每個(gè)環(huán)節(jié)都可能成為面試官的追問點(diǎn)。下面我就結(jié)合具體案例拆解這個(gè)前端工程師的經(jīng)典考題。2. 網(wǎng)絡(luò)請(qǐng)求階段的關(guān)鍵環(huán)節(jié)2.1 DNS解析的隱藏細(xì)節(jié)當(dāng)你在地址欄輸入www.example.com并按下回車時(shí)第一個(gè)觸發(fā)的是DNS查詢。但這個(gè)過程比大多數(shù)人想象的復(fù)雜瀏覽器緩存檢查瀏覽器會(huì)首先檢查自己的DNS緩存chrome://net-internals/#dns這個(gè)緩存通常有1分鐘左右的TTL。我在優(yōu)化電商網(wǎng)站時(shí)發(fā)現(xiàn)合理設(shè)置DNS Prefetch可以將首屏?xí)r間縮短200-300ms。系統(tǒng)調(diào)用與本地緩存如果瀏覽器緩存未命中會(huì)調(diào)用gethostbyname等系統(tǒng)函數(shù)。這里有個(gè)坑Linux的nscd服務(wù)緩存可能導(dǎo)致DNS更新延遲我曾在灰度發(fā)布時(shí)因此踩坑。# 查看Linux DNS緩存需要安裝nscd sudo systemctl status nscd sudo nscd -g | grep hosts遞歸查詢過程完整的DNS查詢會(huì)經(jīng)過本地DNS服務(wù)器如8.8.8.8根域名服務(wù)器返回.com的NS記錄TLD服務(wù)器返回example.com的NS記錄權(quán)威域名服務(wù)器返回最終的A記錄實(shí)際項(xiàng)目中建議將DNS查詢時(shí)間控制在100ms以內(nèi)。可以通過dig命令診斷dig trace www.example.com2.2 TCP連接的優(yōu)化空間拿到IP地址后瀏覽器會(huì)通過系統(tǒng)調(diào)用socket()創(chuàng)建套接字然后開始經(jīng)典的三次握手SYN客戶端發(fā)送SYN1, SeqXSYN-ACK服務(wù)端回復(fù)SYN1, ACKX1, SeqYACK客戶端發(fā)送ACKY1這里有幾個(gè)優(yōu)化點(diǎn)TCP Fast Open可以在首次SYN時(shí)就攜帶數(shù)據(jù)減少RTT。我在移動(dòng)端項(xiàng)目實(shí)測(cè)可降低100ms延遲。初始擁塞窗口現(xiàn)代Linux默認(rèn)是10個(gè)MSS約14KB對(duì)于小文件可以調(diào)大。SYN Cookie防護(hù)應(yīng)對(duì)DDoS攻擊但會(huì)略微增加延遲。// Node.js中設(shè)置TCP參數(shù)示例 const server require(net).createServer(); server.on(connection, (socket) { socket.setNoDelay(true); // 禁用Nagle算法 });2.3 TLS握手的性能陷阱對(duì)于HTTPS站點(diǎn)TCP連接后還需要TLS握手ClientHello支持的加密套件、隨機(jī)數(shù)等ServerHello選擇的加密方式、證書等密鑰交換ECDHE或RSA等算法應(yīng)用數(shù)據(jù)傳輸優(yōu)化建議啟用TLS 1.3只需1-RTT使用OCSP Stapling避免額外查詢配置Session Ticket實(shí)現(xiàn)0-RTT# Nginx配置示例 ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_session_tickets on; ssl_session_timeout 1d;3. 瀏覽器處理階段3.1 關(guān)鍵路徑渲染優(yōu)化瀏覽器拿到HTML后解析過程大致如下構(gòu)建DOM樹字節(jié)→字符→令牌→節(jié)點(diǎn)→樹構(gòu)建CSSOM同樣需要從字節(jié)到樣式樹的過程構(gòu)建渲染樹合并DOM和CSSOM排除不可見元素布局計(jì)算計(jì)算每個(gè)節(jié)點(diǎn)的幾何信息繪制將布局信息轉(zhuǎn)換為屏幕像素性能關(guān)鍵點(diǎn)避免CSS阻塞將關(guān)鍵CSS內(nèi)聯(lián)非關(guān)鍵CSS異步加載優(yōu)化JavaScript執(zhí)行使用defer/async避免長(zhǎng)時(shí)間任務(wù)減少回流重繪使用transform/opacity等屬性!-- 優(yōu)化資源加載示例 -- link relpreload hrefcritical.css asstyle link relstylesheet hrefnon-critical.css mediaprint onloadthis.mediaall3.2 JavaScript執(zhí)行細(xì)節(jié)當(dāng)解析器遇到