PageSpeed 規則和建議

Ilya Grigorik
Ilya Grigorik

發布日期:2018 年 8 月 17 日

本指南將從整體角度檢視 PageSpeed Insights 規則:在最佳化關鍵運算路徑時,應注意哪些事項,以及原因為何。

移除會妨礙顯示的 JavaScript 和 CSS

如要縮短首次算繪時間,請盡量減少頁面上的關鍵資源數量,並盡可能移除這些資源,同時減少下載的關鍵位元組數量,並最佳化關鍵路徑長度。

最佳化 JavaScript 用量

除非標示為 async,或使用特殊 JavaScript 程式碼片段新增,否則 JavaScript 資源會根據預設遭到剖析器封鎖。解析器阻擋 JavaScript 會迫使瀏覽器等待 CSSOM,並暫停 DOM 的建構作業,進而大幅延遲首次轉譯作業的時間。

優先使用非同步 JavaScript 資源

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

避免同步伺服器呼叫

請使用 navigator.sendBeacon() 方法,限制 unload 處理常式中 XMLHttpRequest 傳送的資料。由於許多瀏覽器要求這類要求必須同步處理,因此這類要求可能會導致網頁轉換速度變慢,有時甚至會明顯變慢。以下程式碼會示範如何使用 navigator.sendBeacon(),在 pagehide 處理常式中傳送資料至伺服器,而不是在 unload 處理常式中傳送資料。

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

fetch() 方法提供更佳的方式,可異步要求資料。fetch() 會使用 Promise 處理回應,而非多個事件處理常式。與 XMLHttpRequest 的回應不同,fetch() 回應是串流物件。這表示對 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

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

避免匯入 CSS

CSS 匯入指示詞 (@import) 可讓一個樣式表匯入其他樣式表檔案中的規則。不過,請避免使用這些指示詞,因為這會在關鍵路徑中引入額外的往返作業:只有在收到並剖析含有 @import 規則的 CSS 樣式表後,系統才會發現匯入的 CSS 資源。

嵌入禁止轉譯 CSS

為獲得最佳效能,建議您直接將必要 CSS 嵌入 HTML 文件。這麼做可避免在關鍵路徑中產生額外的往返傳輸,如果執行正確,則可提供「單趟」關鍵路徑長度,其中只有 HTML 是阻斷資源。

意見回饋