瀏覽器前端優化
優化全都是與速度和滿意度有關。
-
從使用者體驗的角度,我們希望前端提供可以快速載入和執行的網頁。
-
而從開發者體驗的角度,我們希望前端是快速、簡單而規範的。
這不僅會給我們帶來快樂的使用者和快樂的開發者,而且由於 Google 偏向於優化,SEO 排名也會顯著提高。
如果你已經花費了大量時間來改善你網站的 Google Pagespeed Insights分數,那麼這將有助於揭示這一切實際上意味著什麼,以及我們必須為優化前端所採取的大量策略。
背景
最近我的整個團隊有機會花一些時間加快把我們提出的升級變為程式碼庫,可能是用 React。這確實讓我思考起了我們該如何建立前端。很快,我意識到瀏覽器將是我們的方法中的一個重要因素,同時也是我們知識中的大瓶頸。
方法
首先
我們不能控制瀏覽器或者改變它的行為方式,但是我們可以理解它的工作原理,這樣就可以優化我們提供的負載。
幸運的是,瀏覽器行為的基礎原理是相當穩定而且文件齊全的,並且在相當長一段時間內肯定不會發生顯著變化。
所以這至少給了我們一個目標。
其次
另一方面,程式碼、技術棧、架構和模式是我們可以控制的東西。它們更靈活,變化的更快,並給我們這一邊提供了更多選擇。
因此
我決定從外向內著手,搞清楚我們程式碼的最終結果應該是什麼樣的,然後形成編寫程式碼的意見。在這第一篇博文中,我們打算專注於對於瀏覽器來說我們需要了解的一切。
瀏覽器都做了什麼
下面我們來建立一些知識。如下是我們希望瀏覽器要執行的一些簡單 HTML:
<!DOCTYPE html> <html> <head> <title>The "Click the button" page</title> <meta charset="UTF-8"> <link rel="stylesheet" href="styles.css" /> </head> <body> <h1> Click the button. </h1> <button type="button">Click me</button> <script> var button = document.querySelector("button"); button.style.fontWeight = "bold"; button.addEventListener("click", function () { alert("Well done."); }); </script> </body> </html>
瀏覽器如何渲染網頁
當瀏覽器接收到 HTML 時,就會解析它,將其分解為瀏覽器所能理解的詞彙,而這個詞彙由於HTML5 DOM 規範定義,在所有瀏覽器中是保持一致的。然後瀏覽器通過一系列步驟來構造和渲染頁面。如下是一個很高層次的概述:
-
使用 HTML 建立文件物件模型(DOM)。
-
使用 CSS 建立 CSS 物件模型(CSSOM)。
-
基於 DOM 和 CSSOM 執行指令碼(Script)。
-
合併 DOM 和 CSSOM 形成渲染樹(Render Tree)。
-
使用渲染樹佈局(Layout)所有元素的大小和位置。
-
繪製(Paint)所有元素。
步驟一 — HTML
瀏覽器開始從上到下讀取標記,並且通過將它分解成節點,來建立 DOM 。
HTML 載入優化策略
- 樣式在頂部,指令碼在底部
雖然這個規則有例外和細微差別,不過總體思路是儘可能早地載入樣式,儘可能晚地載入指令碼。原因是指令碼執行之前,需要 HTML 和 CSS 解析完成,因此,樣式儘可能的往頂部放,這樣在底部指令碼開始編譯和執行之前,樣式有足夠的時間完成計算。
下面我們進一步研究如何在優化的同時做細微調整。
- 最小化和壓縮
這適用於我們提交的所有內容,包括 HTML、CSS、JavaScript、圖片和其它資源。
最小化是移除所有多餘的字元,包括空格、註釋、多餘的分號等等。
壓縮(比如 GZip)是將程式碼或者資源中重複的資料替換為一個指向原始例項的指標,大大壓縮下載檔案的大小,並且是在客戶端解壓檔案。
雙管齊下的話,可以潛在將負載降低 80% 到 90%。比如:光 bootstrap 就節省了 87% 的負載。
- 可訪問性
雖然可訪問性不會讓頁面的下載變得更快,但是會大大提高殘障人士的滿意度。要確保是給所有人提供的!給元素加上 aria 標籤,給圖片提供 alt 文字,以及所有其它好東西。
使用像 WAVE 這樣的工具確認在哪些地方可以改善可訪問性。
步驟二 — CSS
當瀏覽器發現任何與節點相關的樣式時(即外部樣式表、內部樣式表或行內樣式),就立即停止渲染 DOM ,並用這些節點來建立 CSSOM。這就是人們稱 CSS 阻塞渲染的原因。這裡是不同型別樣式的一些優缺點。
//外部樣式 <link rel="stylesheet" href="styles.css"> // 內部樣式 <style> h1 { font-size: 18px; } </style> // 行內樣式 <button style="background-color: blue;">Click me</button>
CSSOM 節點的建立與 DOM 節點的建立類似,隨後,兩者會被合併。這就是現在它們的樣子:
CSSOM 的構建會阻塞頁面的渲染,因此我們想在樹中儘可能早地載入樣式,讓它們儘可能輕便,並且在有效的地方延遲載入它們。
CSS 載入優化策略
- 使用 media 屬性
media 屬性指定要載入樣式必須滿足的條件,比如:是最大還是最小解析度?是面向螢幕閱讀器嗎?
桌面是很強大,但是移動裝置不是,所以我們想給移動裝置儘可能最輕的負載。我們可以假設先只提供移動端樣式,然後對桌面端樣式放一個媒體條件。雖然這樣做不會阻止桌面端樣式下載,不過會阻止它阻塞頁面載入和使用寶貴的資源。
// 這個 css 在所有情況都會下載,並阻塞頁面的渲染。 // media="all" 是預設值,並且與不宣告任何 media 屬性一樣。 <link rel="stylesheet" href="mobile-styles.css" media="all"> // 在移動端,這個 css 會在後臺下載,而且不會中斷頁面載入。 <link rel="stylesheet" href="desktop-styles.css" media="min-width: 590px"> // CSS 中只為列印檢視計算的媒體查詢 <style> @media print { img { display: none; } } </style>
- 延遲載入 CSS
如果我們有一些樣式可以等到首屏有價值的內容渲染完成後,再載入和計算,比如出現在首屏以下的,或者頁面變成響應式之後不那麼重要的東西。我們可以把樣式載入寫在指令碼中,用指令碼等待頁面載入完成,然後再插入樣式。
<html> <head> <link rel="stylesheet" href="main.css"> </head> <body> <div class="main"> 摺疊內容之上的重要部分。 </div> <div class="secondary"> 摺疊內容之下。頁面載入之後,向下滾動才會看到的東西。 </div> <script> window.onload = function () { // 載入 secondary.css } </script> </body> </html>
- 較小的特殊性
鏈在一起的元素越多,自然要傳輸的資料就越多,因而會增大 CSS 檔案,這是一個明顯的缺點。不過這樣做還有一個客戶端計算的損耗,即會把樣式計算為較高的特殊性。
// 更具體的選擇器 == 糟糕 .header .nav .menu .link a.navItem { font-size: 18px; } // 較不具體的選擇器 == 好 a.navItem { font-size: 18px; }
- 只載入需要的樣式
這聽起來可能有點愚蠢或者裝模作樣,不過如果你已經從事前端工作多年的話,就會知道 CSS 的一個最大問題是刪除東西的不可預測性。設計的時候它就是被下了不斷增長這樣的詛咒。
要儘可能多削減 CSS ,可以使用類似uncss)包這樣的工具,或者如果想有一個網上的替代品,那就到處找找,還是有挺多選擇的。
步驟三 — JavaScript
然後,瀏覽器會不斷建立 DOM / CSSOM 節點,直到發現任何 JavaScript 節點,即外部或者行內的指令碼。
// 外部指令碼 <script src="app.js"></script> // 內部指令碼 <script> alert("Oh, hello"); </script>
由於指令碼可能需要訪問或操作之前的 HTML 或樣式,我們必須等待它們構建完成。
因此瀏覽器必須停止解析節點,完成建立 CSSOM,執行指令碼,然後再繼續。這就是人們稱 JavaScript 阻塞解析器的原因。
瀏覽器有種稱為'預載入掃描器'的東西,它會掃描 DOM 的指令碼,並開始預載入指令碼,不過指令碼只會在先前的 CSS 節點已經構建完成後,才會依次執行。
假如這就是我們的指令碼:
var button = document.querySelector("button"); button.style.fontWeight = "bold"; button.addEventListener("click", function () { alert("Well done."); });
那麼這就是我們的 DOM 和 CSSOM 的效果:
JavaScript 載入優化策略
優化指令碼是我們可以做的最重要的事情之一,同時也是大多數網站做得最糟糕的事情之一。
- 非同步載入指令碼
通過在指令碼上使用 async 屬性,可以通知瀏覽器繼續,用另一個低優先順序的執行緒下載這個指令碼,而不要阻塞其餘頁面的載入。一旦指令碼下載完成,就會執行。
<script src="async-script.js" async></script>
這意味著這段指令碼可以隨時執行,這就導致了兩個明顯的問題。首先,它可以在頁面載入後執行很長時間,所以如果依靠它為使用者體驗做一些事情,那麼可能會給使用者一個不是最佳的體驗。其次,如果它剛好在頁面完成載入之前執行,我們就沒法預測它會訪問正確的 DOM/CSSOM 元素,並且可能會中斷執行。
async 適用於不影響 DOM 或 CSSOM 的指令碼,而且尤其適用於與 HTML 和 CSS 程式碼無關,對使用者體驗無影響的外部指令碼,比如分析或者跟蹤指令碼。不過如果你發現了任何好的使用案例,那就用它。
- 延遲載入指令碼
defer 跟 async 非常相似,不會阻塞頁面載入,但會等到 HTML 完成解析後再執行,並且會按出現的次序執行。
這對於會作用於渲染樹上的指令碼來說,確實是一個好的選擇。不過對於載入摺疊內容之上的頁面,或者需要之前的指令碼已經執行的指令碼來說,並不重要。
<script src="defer-script.js" defer></script>
這裡是使用 defer 策略的另一個好選擇,或者也可以使用 addEventListener。如果想了解更多,請從這裡開始閱讀。
// 所有物件都在 DOM 中,並且所有影象、指令碼、link 和子幀都完成了載入。 window.onload = function () { }; // 在 DOM 準備好時呼叫,在影象和其它外部內容準備好之前 document.onload = function () { }; // JQuery 的方式 $(document).ready(function () { });
不幸的是 async 和 defer 對於行內指令碼不起作用,因為只要有行內指令碼,瀏覽器預設就會編譯和執行它們。當指令碼內嵌在 HTML 中時,就會立即執行,通過在外部資源上使用上述兩個屬性,我們只是把指令碼抽取出來,或者延遲把指令碼釋出到 DOM/CSSOM。
- 操作之前克隆節點
當且僅當對 DOM 執行多次修改時看到了不必要的行為時,就試試這招。
先克隆整個 DOM 節點,對克隆的節點做修改,然後用它來替換原始節點,這樣可能效率更高。因為這樣就避免了多次重畫,降低了 CPU 和記憶體消耗。這樣做還可以避免更改頁面時的抖動和無樣式內容的閃爍(Flash of Unstyled Content,FOUC)。
// 通過克隆,高效操作一個節點 var element = document.querySelector(".my-node"); var elementClone = element.cloneNode(true); // (true) 也克隆子節點, (false) 不會 elementClone.textContent = "I've been manipulated..."; elementClone.children[0].textContent = "...efficiently!"; elementClone.style.backgroundColor = "green"; element.parentNode.replaceChild(elementClone, element);
請注意,克隆的時候並沒有克隆事件監聽器。有時這實際上剛好是我們想要的。過去我們已經用過這種方法來重置不呼叫命名函式時的事件監聽器,而且那時也沒有 jQuery 的 .on() 和 .off() 方法可用。
- Preload/Prefetch/Prerender/Preconnect
這些屬性基本上也實現了它們所做的承諾,而且都棒極了。不過,這些屬性都是相當新,還沒被瀏覽器普遍支援,也就是說對我們大多數人來說它們實際上不是真正的競爭者。不過,如果你有空的話,可以看看這裡和這裡。
步驟四 — 渲染樹
一旦所有節點已被讀取,DOM 和 CSSOM 準備好合併,瀏覽器就會構建渲染樹。如果我們把節點當成單詞,把物件模型當成句子,那麼渲染樹便是整個頁面。現在瀏覽器已經有了渲染頁面所需的所有東西。
步驟五 — 佈局
然後我們進入佈局階段,確定頁面上所有元素的大小和位置。
步驟六 — 繪製
最終我們進入繪製階段,真正地光柵化螢幕上的畫素,為使用者繪製頁面。
整個過程通常會在幾秒或者十分之一秒內發生。我們的任務是讓它做得更快。
如果 JavaScript 事件改變了頁面的某個部分,就會導致渲染樹的重繪,並且迫使我們再次經歷佈局和繪製。現在瀏覽器足夠智慧,會僅進行部分重畫。不過我們不能指望靠這就能高效或者高效能。
話雖如此,不過很顯然 JavaScript 主要是在客戶端基於事件,而且我們想讓它來操作 DOM,所以它就得做到這一點。我們只是必須限制它的不良影響。
至此你已經足夠認識到要感謝 Tali Garsiel 的演講。這是 2012 年的演講,但是資訊依然是真實的。她在此主題上的綜合論文可以在這裡讀到。
如果你喜歡迄今為止所讀過的內容,但仍然渴望知道更多的底層技術性的東西,那麼所有知識的權威就是HTML5 規範。
我們差不多搞定了,不過請和我多待段時間!現在我們來探討為什麼需要知道上面的所有知識。
瀏覽器如何發起網路請求
本節中,我們將理解如何才能高效地把渲染頁面所需的資料傳輸給瀏覽器。
當瀏覽器請求一個 URL 時,伺服器會響應一些 HTML。我們將從超級小的開始,慢慢增加複雜性。
假如這就是我們頁面的 HTML:
<!DOCTYPE html> <html> <head> <title>The "Click the button" page</title> </head> <body> <h1> Button under construction... </h1> </body> </html>
我們需要學習一個新術語,關鍵渲染路徑(Critical Rendering Path,CRP),就是瀏覽器渲染頁面所需的步數。如下就是現在我們的 CRP 示意圖看起來的樣子:
瀏覽器發起一個 GET 請求,在我們頁面(現在還沒有 CSS 及 JavaScript)所需的 1kb HTML 響應回來之前,它一直是空閒的。接收到響應之後,它就能建立 DOM,並渲染頁面。
關鍵路徑長度
三個 CRP 指標的第一個是路徑長度。我們想讓這個指標儘可能低。
瀏覽器用一次往返來獲取渲染頁面所需的 HTML,而這就是它所需的一切。因此我們的關鍵路徑長度是 1,很完美。
下面我們上一個檔次,加點內部樣式和內部 JavaScript。
<!DOCTYPE html> <html> <head> <title>The "Click the button" page</title> <style> button { color: white; background-color: blue; } </style> </head> <body> <button type="button">Click me</button> <script> var button = document.querySelector("button"); button.addEventListener("click", function () { alert("Well done."); }); </script> </body> </html>
如果我們檢查一下 CRP 示意圖,應該能看到有兩點變化。
新增了兩步,建立 CSSOM和執行指令碼。這是因為我們的 HTML 有內部樣式和內部指令碼需要計算。不過,由於沒有發起外部請求,關鍵路徑長度沒變。
但是注意,渲染沒那麼快了。而且我們的 HTML 大小增加到了 2kb,所以某些地方還是受了影響。
關鍵位元組數
那就是三個指標之二,關鍵位元組數出現的地方。這個指標用來衡量渲染頁面需要傳送多少位元組數。並非頁面會下載的所有位元組,而是隻是實際渲染頁面,並把它響應給使用者所需的位元組。
不用說,我們也想減少這個數。
如果你認為這就不錯了,誰還需要外部資源啊,那就大錯特錯了。雖然這看起來很誘人,但是它在規模上是不可行的。在現實中,如果我的團隊要通過內部或者行內方式給頁面之一提供所需的一切,頁面就會變得很大。而瀏覽器不是為了處理這樣的負載而建立的。
看看這篇關於像 React 推薦的那樣內聯所有樣式時,頁面載入效果的有趣文章。DOM 變大了四倍,掛載花了兩倍的時間,到可以響應多花了 50% 的時間。相當不能接受。
還要考慮一個事實,就是外部資源是可以被快取的,因此在回訪頁面,或者訪問用相同資源(比如 my-global.css)的其它頁面時,瀏覽器就用發起網路請求,而是用其快取的版本,從而為我們贏得更大的勝利。
所以下面我們更進一步,對樣式和指令碼使用外部資源。注意這裡我們有一個外部 CSS 檔案、一個外部 JavaScript 檔案和一個外部 asyncJavaScript 檔案。
<!DOCTYPE html> <html> <head> <title>The "Click the button" page</title> <link rel="stylesheet" href="styles.css" media="all"> <script type="text/javascript" src="analytics.js" async></script> // async </head> <body> <button type="button">Click me</button> <script type="text/javascript" src="app.js"></script> </body> </html>
如下是現在 CRP 示意圖看起來的樣子:
瀏覽器得到頁面,建立 DOM,一發現任何外部資源,預載入掃描器就開始介入。繼續,開始下載 HTML 中所找到的所有外部資源。CSS 和 JavaScript 有較高的優先順序,其它資源次之。
它挑出我們的 styles.css 和 app.js,開闢另一條關鍵路徑去獲取它們。不過不會挑出 analytics.js,因為我們給它加了 async屬性。瀏覽器依然會用另一個低優先順序的執行緒下載它,不過因為它不會阻塞頁面渲染,所以也與關鍵路徑無關。這正是 Google 自己的優化演算法對網站進行排名的方式。
關鍵檔案
最後,是我們最後一個 CRP 指標,關鍵檔案,也就是瀏覽器渲染頁面需要下載的檔案總數。在例三中,HTML 檔案本身、CSS 和 JavaScript 檔案都是關鍵檔案。async 的指令碼不算。當然,檔案越少越好。
回到關鍵路徑長度
現在你可能會認為這肯定就是最長的關鍵路徑吧?我的意思是說要渲染頁面,我們只需要下載 HTML、CSS 和 JavaScript,而且只需要兩個往返就可以搞定。
HTTP1 檔案限制
不過,生活依然沒那麼簡單。拜 HTTP1 協議所賜,我們的瀏覽器一次從一個域名併發下載的最大檔案數是有限制的。範圍從 2(很老的瀏覽器)到 10(Edge)或者 6(Chrome)。
你可以從這裡檢視使用者瀏覽器請求你的域名時的最大併發檔案數。
你可以並且應該通過把一些資源放在影子域名上,來繞開這個限制,從而最大限度地提高優化潛力。
警告:不要把關鍵的 CSS 放到根域名之外的其他地方,DNS 查詢和延遲都會抵消這樣做時所帶來的任何可能的好處。
HTTP2
如果網站是 HTTP2,並且使用者的瀏覽器也是相容的,那麼你就可以完全避開這個限制。不過,這種好事並不常見。
可以在這裡測試你網站的 HTTP2。
TCP 往返限制
另一個敵人逼近了!
任何一次往返可傳輸的最大資料量是 14kb,對於包括所有 HTML、CSS 和指令碼在內的所有網路請求都是如此。這來自於防止網路擁堵和丟包的一個 TCP 規範。
如果一次請求中,我們的 HTML 或者任何累積的資源超過了 14kb,那麼就需要多做一次往返來獲取它們。所以,是的,這些大的資源確實會給 CRP 新增很多路徑。
大招
現在將我們的大網頁傾巢而出。
<!DOCTYPE html> <html> <head> <title>The "Click the button" page</title> <link rel="stylesheet" href="styles.css"> // 14kb <link rel="stylesheet" href="main.css"> // 2kb <link rel="stylesheet" href="secondary.css"> // 2kb <link rel="stylesheet" href="framework.css"> // 2kb <script type="text/javascript" src="app.js"></script> // 2kb </head> <body> <button type="button">Click me</button> <script type="text/javascript" src="modules.js"></script> // 2kb <script type="text/javascript" src="analytics.js"></script> // 2kb <script type="text/javascript" src="modernizr.js"></script> // 2kb </body> </html>
現在我知道一個按鈕就有很多 CSS 和 JavaScript,但是它是一個很重要的按鈕,它對我們來說意義重大。所以就不要評判,好嗎?
整個頁面被很好地最小化和壓縮到 2kb,遠低於 14kb 的限制,所以我們又回到正好一次 CRP 往返了,而瀏覽器開始忠實地用一個關鍵檔案,即我們的 HTML,來建立 DOM。
CRP 指標:長度 1,檔案數 1,位元組數 2kb
瀏覽器發現了一個 CSS 檔案,而預載入掃描器識別出所有外部資源(CSS 和 JavaScript),併傳送一個請求開始下載它們。但是等一等,第一個 CSS 檔案是 14kb,超出了一次往返的最大負載,所以它本身就是一個 CRP。
CRP 指標:長度 2,檔案數 2,位元組數 16kb
然後它繼續下載資源。餘下的資源低於 14kb,所以可以在一次往返中搞定。不過由於總共有 7 個資源,而且我們的網站還沒啟用 HTTP2,而且用的是 Chrome,所以這次往返只能下載 6 個檔案。
CRP 指標:長度 3,檔案數 8,位元組數 28kb
現在我們終於可以下載完最終檔案,並開始渲染 DOM了。
CRP 指標:長度 4,檔案數 9,位元組數 30kb
我們的 CRP 總共有 30kb 的關鍵資源,在 9 個關鍵檔案和 4 個關鍵路徑中。有了這個資訊,以及一些關於連線中延遲的知識,我們實際上就可以開始對給定使用者的頁面效能進行真正準確的估計了。
瀏覽器網路優化策略
- Pagespeed Insights
使用Insights 來確定效能問題。Chrome DevTools 中還有個 audit標籤。
- 善用 Chrome 開發者工具
DevTools 如此驚人。我們為它單獨寫一整本書,不過這裡已經有不少資源可以幫助你。這裡)有一篇開始解釋網路資源的文章值得一讀。
- 在好的環境中開發,在糟糕的環境中測試
你當然想在你的 1tb SSD、32G 記憶體的 Macbook Pro 上開發,不過對於效能測試,應該轉到 Chrome 中的 network 標籤下,模擬低頻寬、節流 CPU 連線,從而真正得到一些有用的資訊。
- 合併資源/檔案
在上面的 CRP 示意圖中,我省略了一些你不需要知道的東西。不過基本上,每接收到一個外部 CSS 和 JavaScript 檔案後,瀏覽器都會構建 CSSOM,並執行指令碼。所以,儘管你可以在一次往返中傳遞幾個檔案,它們每個也都會讓瀏覽器浪費寶貴的時間和資源,所以最好還是將檔案合併在一起,消除不必要的載入。
- 在 head 部分為首屏設定內部樣式
是讓 CSS 和 JavaScript 內部化或者內聯,以防止獲取外部資源,還是相反,讓資源變成外部資源,這樣就可以快取,從而讓 DOM 保持輕量,二者並非非黑即白。
但是有一個很好的觀點是對首屏關鍵內容設定內部樣式,可以避免在首次有意義的渲染時獲取資源。
- 最小化/壓縮圖片
這很簡單、基礎,有很多選擇可以這樣做,選一個你最喜歡的即可。
- 延遲載入圖片直到頁面載入後
用一些簡單的原生 JavaScript,你就可以延遲載入出現在摺疊部分之下或者對首次使用者響應狀態不重要的圖片。這裡有一些不錯的策略。
- 非同步載入字型
字型載入的代價非常高,如果可以的話,你應該使用帶回退的 web 字型,然後逐步渲染字型和圖示。這看起來可能不咋樣,不過另一個選擇是如果字型還沒有載入,頁面載入時就完全沒有文字,這被稱為不可見文字的閃爍(Flash Of Invisible Text,FOIT)。
- 是否真正需要 JavaScript/CSS?
你需要嗎?請回答我!是否有原生 HTML 元素可以產生用指令碼一樣的行為?是否可以用行內樣式或圖示而不是內部/外部資源?比如,內聯一個 SVG。
- CDN
內容分發網路(CDN)可用於為使用者提供物理上更近和更低延遲的位置,從而降低載入時間。
現在你開心慘了,已經知道了足夠多的東西,可以從這裡走出去,自己探索有關這個主題的更多東西了。我推薦參加這個免費的 Udacity 課程,並且閱讀Google 自己的 優化文件。
如果你渴望更底層的知識,那麼這本免費電子書《高效能瀏覽器網路》是個開始的好地方。
總結
關鍵渲染路徑是最重要的,它讓網站優化有規律可循。需要關注的 3 個指標是:
1 — 關鍵位元組數
2 — 關鍵檔案數
3 — 關鍵路徑數
這裡我所寫的應該足以讓你掌握基礎知識,並幫助你解釋 Google Pagespeed Insights對你的效能有什麼看法。
最佳實踐的應用將伴隨著良好的 DOM 結構、網路優化和可用於減少 CRP 指標的各種策略的結合。讓使用者更高興,讓 Google 的搜尋引擎更高興。
在任何企業級網站中,這將是一項艱鉅的任務,但是你必須遲早做到這一點,所以不要再承擔更多的技術性債務,並開始投資于堅實的效能優化策略。
感謝你閱讀至此,如果你真的做到了。衷心希望能幫到你,有任何反饋或者糾正,請給我發訊息。
在本部落格的下一部分中,我希望給出一個真實世界的例子,說明如何在我自己的團隊的大量程式碼庫中實現所有這些原則。我們在一個域上擁有超過 2000 個可管理內容的頁面,並且每天為數十萬個頁面瀏覽量提供服務,因此這將很有趣。
不過這可能還需要段時間,我現在需要休息一下。
相關文章
- 前端效能優化——桌面瀏覽器前端優化策略前端優化瀏覽器
- 前端效能優化之桌面瀏覽器優化策略前端優化瀏覽器
- 前端效能優化 —— 移動端瀏覽器優化策略前端優化瀏覽器
- 前端效能優化(一)——瀏覽器工作原理前端優化瀏覽器
- 前端效能優化 之 瀏覽器快取前端優化瀏覽器快取
- 前端效能優化之移動端瀏覽器優化策略前端優化瀏覽器
- 前端效能優化(二)——瀏覽器快取機制前端優化瀏覽器快取
- 前端優化:瀏覽器快取技術介紹前端優化瀏覽器快取
- 前端基於瀏覽器儲存的AJAX效能優化前端瀏覽器優化
- 瀏覽器效能優化-渲染效能瀏覽器優化
- 優化-瀏覽器快取和壓縮優化優化瀏覽器快取
- 前端效能優化:細說瀏覽器渲染的重排與重繪前端優化瀏覽器
- 前端面試瀏覽器系列:瀏覽器快取前端面試瀏覽器快取
- 瀏覽器重繪(repaint)重排(reflow)與優化[瀏覽器機制]瀏覽器AI優化
- 現代瀏覽器效能優化-JS篇瀏覽器優化JS
- 瀏覽器渲染過程與效能優化瀏覽器優化
- 前端優化,瞭解瀏覽器重排與重繪前端優化瀏覽器
- 瀏覽器層合成與頁面效能優化瀏覽器優化
- 從瀏覽器渲染原理談動畫效能優化瀏覽器動畫優化
- 瀏覽器工作原理及web 效能優化(上)瀏覽器Web優化
- 瀏覽器帶你學前端瀏覽器前端
- Web前端瀏覽器相容初探Web前端瀏覽器
- 瀏覽器的載入與頁面效能優化瀏覽器優化
- 谷歌chrome瀏覽器network中Stalled分析和優化谷歌Chrome瀏覽器優化
- 前端發展史及瀏覽器核心前端瀏覽器
- 「前端那些事兒」① 瀏覽器渲染引擎前端瀏覽器
- 前端chrome瀏覽器除錯總結前端Chrome瀏覽器除錯
- 前端必看!各大瀏覽器 CSS Hack 收集前端瀏覽器CSS
- 【高效能JS】重繪、重排與瀏覽器優化方法JS瀏覽器優化
- 瀏覽器渲染流水線解析與網頁動畫效能優化瀏覽器網頁動畫優化
- 瀏覽器頁面資源載入過程與優化瀏覽器優化
- 讓我們再聊聊瀏覽器資源載入優化瀏覽器優化
- Win10 Edge瀏覽器有哪些優點?Edge瀏覽器有哪些不足?Win10瀏覽器
- 【瀏覽器】瀏覽器基本工作原理瀏覽器
- 優秀的開源影象瀏覽器瀏覽器
- web前端進階篇(二) 瀏覽器 WebpackWeb前端瀏覽器
- 前端面試-主流瀏覽器以及其核心前端面試瀏覽器
- 前端面試:Http協議與瀏覽器前端面試HTTP協議瀏覽器