PageSpeed 規則和建議

伊利亞 (Ilya Grigorik)
Ilya Grigorik

本指南將深入探討 PageSpeed Insights 規則的全貌:最佳化關鍵轉譯路徑時應留意哪些事項,以及原因。

排除會妨礙顯示的 JavaScript 和 CSS

為了將首次轉譯作業最快,請盡可能減少並 (如果可能) 消除網頁上的重要資源數量、盡量減少下載的關鍵位元組數,以及最佳化重要路徑的長度。

最佳化 JavaScript 使用情形

除非將 JavaScript 資源標示為 async,或透過特殊 JavaScript 程式碼片段新增,否則根據預設,JavaScript 資源會封鎖剖析器。封鎖 JavaScript 的剖析器會強制瀏覽器等待 CSSOM 並暫停建構 DOM,導致初次顯示的時間大幅延遲。

偏好使用非同步 JavaScript 資源

非同步資源將文件剖析器解除封鎖,並允許瀏覽器在執行指令碼前避免封鎖 CSSOM。通常,如果指令碼可以使用 async 屬性,也代表第一次轉譯時並非必要。建議在初始轉譯後,以非同步方式載入指令碼。

避免同步伺服器呼叫

使用 navigator.sendBeacon() 方法,限制 unload 處理常式中 XMLHttpRequests 傳送的資料。由於許多瀏覽器需要同步這類要求,因此頁面轉換速度可能會變慢,以下程式碼顯示如何使用 navigator.sendBeacon() (而非在 unload 處理常式) 將資料傳送至 pagehide 處理常式中的伺服器。

    <script>
      function() {
        window.addEventListener('pagehide', logData, false);
        function logData() {
          navigator.sendBeacon(
            'https://putsreq.herokuapp.com/Dt7t2QzUkG18aDTMMcop',
            'Sent by a beacon!');
        }
      }();
    </script>

新的 fetch() 方法可讓您輕鬆非同步要求資料。由於目前只有部分地區提供這項功能,因此建議您在使用前,先使用功能偵測功能測試此是否為啟用狀態。這個方法使用 Promise 處理回應,而非使用多個事件處理常式。與 XMLHttpRequest 的回應不同,擷取回應是從 Chrome 43 開始的串流物件。也就是說,呼叫 json() 也會傳回 Promise。

    <script>
    fetch('./api/some.json')
      .then(
        function(response) {
          if (response.status !== 200) {
            console.log('Looks like there was a problem. Status Code: ' +  response.status);
            return;
          }
          // Examine the text in the response
          response.json().then(function(data) {
            console.log(data);
          });
        }
      )
      .catch(function(err) {
        console.log('Fetch Error :-S', err);
      });
    </script>

fetch() 方法也可以處理 POST 要求。

    <script>
    fetch(url, {
      method: 'post',
      headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
      },
      body: 'foo=bar&lorem=ipsum'
    }).then(function() { // Additional code });
    </script>

延後剖析 JavaScript

為了盡量減少瀏覽器轉譯網頁時需要執行的工作量,請延後所有非必要的指令碼,讓網頁在初始轉譯時用來轉譯可見內容。

避免長時間執行 JavaScript

長時間執行的 JavaScript 會阻止瀏覽器建構 DOM、CSSOM 及轉譯頁面,因此延後到後續轉譯時非必要的初始化邏輯和功能為止。如果您需要執行冗長的初始化序列,不妨將其分割成數個階段,讓瀏覽器能夠處理其中的其他事件。

最佳化 CSS 的使用方式

必須透過 CSS 建構算繪樹狀結構,而 JavaScript 通常會在網頁初始建構期間封鎖 CSS。確認所有非必要的 CSS 都標示為非重要 CSS (例如平面和其他媒體查詢),且關鍵 CSS 的數量和傳送時間越短。

在文件標頭中加入 CSS

請盡早在 HTML 文件中指定所有 CSS 資源,以便瀏覽器發現 <link> 標記,並盡快向 CSS 發送要求。

避免匯入 CSS

CSS 匯入 (@import) 指令可讓某個樣式表從其他樣式表檔案匯入規則。不過,請避免使用這些指令,因為這些指令會為重要路徑帶來額外的往返作業:只有在收到並剖析具有 @import 規則本身的 CSS 樣式表之後,才會找到匯入的 CSS 資源。

嵌入禁止轉譯 CSS

為獲得最佳成效,建議您考慮將重要的 CSS 直接內嵌至 HTML 文件中。這種做法可避免重要路徑造成額外的往返作業,而且如果正確完成,即可傳送「一往返」重要路徑長度,其中只有 HTML 是造成阻斷的資源。

意見回饋: