頁面加載性能之優化LCP

影響LCP的四個因素以下:css

  • 較慢的服務器響應時間
  • 渲染阻塞的js和css
  • 較慢的資源加載時間
  • 客戶端渲染

較慢的服務器響應時間

瀏覽器獲取文檔的時間越長,用戶看到頁面的時間也會越長。較快的服務器響應時間,能夠直接改善每個頁面加載相關的指標,包括LCP。html

可使用 TTFB(Time to First Byte) 來測試服務器響應時間,你能夠經過如下手段來優化 TTFB 這個指標。vue

  • 優化服務器
  • 使用CDN
  • 緩存資源
  • html頁面優先使用緩存
  • 提早創建第三方鏈接

優化服務器

你是否在服務器上運行一些昂貴的查詢,佔用了服務器必定的時間?或者服務器上作了一些複雜的操做,致使頁面內容返回延後?分析和提高服務端代碼的效率能夠直接改善瀏覽器從服務端獲取數據的時間。react

比起僅僅是提供靜態頁面而言,不少服務端的web框架都會動態建立頁面。換句話說,比起直接返回一個現存的html文件,這些框架會執行一些邏輯來建立頁面。這就取決於數據庫查詢時間,或者UI框架建立組件的時間(好比: React)。大部分web框架都有提供性能指導,開發者能夠根據指導來提高處理速度。webpack

使用CDN

CDN全稱Content Delivery Network,是一個分佈在不一樣地域的服務器集羣。若是瀏覽器去請求數據,CDN會選擇就近的一個服務器給你返回,避免請求產生太長網絡路徑,甚至跨國。git

緩存資源

若是你的html是靜態的,每一次請求都不會變,能夠服務端緩存下來,不用每次從新建立頁面。經過緩存一份生成好的html到硬盤,服務端緩存能夠有效的下降TTFB,最小化資源的使用。github

  • 配置反向代理,在應用服務器以前配置一個緩存服務器,專門提供緩存內容。
  • 配置和管理雲服務商提供的緩存特性
  • 使用CDN來提供內容緩存,這樣用戶能夠更近的獲取到內容

html頁面優先使用緩存

service worker能夠實現這樣一個功能,優先使用緩存頁面,若是頁面有更新,會將新頁面緩存下來,下次啓動則使用新緩存。web

下圖是使用service worker的一個對比:數據庫

提早創建第三方鏈接

發往第三方服務的請求也會影響LCP,特別是當頁面關鍵內容依賴它們的時候。使用 rel="preconnect" 告知瀏覽器你的資源鏈接須要儘量地快。api

<link rel="preconnect" href="https://example.com">

也可使用 dns-prefetch 讓dns解析更快。

<link rel="dns-prefetch" href="https://example.com">

考慮到瀏覽器兼容性, dns-prefetch 能夠做爲 preconnect 的一個fallback。

<head>
  <link rel="preconnect" href="https://example.com">
  <link rel="dns-prefetch" href="https://example.com">
</head>
preconnect通常只配置一個,dns-prefetch能夠配置多個,因此通常把最關鍵的資源配置成preconnect,好比js或者css所在的cdn域名

渲染阻塞的js和css

在瀏覽器渲染任何內容以前,須要解析html,並生成dom樹。html解析器會被任何樣式文件 <link rel="stylesheet"> 以及同步腳本 <script src="main.js"> 阻塞並暫停解析。

這個不只影響FCP,也影響了LCP。延遲加載非關鍵的js和css能夠加速頁面的主內容的加載。

減小css阻塞時間

有如下三種方法:

  • 最小化css
  • 延後加載非關鍵的css
  • 內聯關鍵css

最小化css

移除css中沒必要要的字符、註釋和空格等,通常打包工具都會自帶相應的插件。

延後加載非關鍵的css

使用開發者工具中的 Coverage 能夠找到頁面未使用的css。

優化方案:

  • 移除無用的css,並將它們移到須要的頁面
  • rel="preload"onload 異步加載對於初次渲染無用的css

內聯關鍵css

將關鍵路徑的css直接放在 <head> 中內聯引用:

這樣能夠避免一次服務器請求,讓css阻塞時間更短。

若是你沒法手動添加內聯樣式,可使用第三方庫:

減小js阻塞時間

有如下三種方案:

  • 最小化並壓縮js文件
  • 延後未使用的js
  • 儘可能減小未使用的polyfills

減小資源加載時間

主要有如下幾種元素會影響LCP:

  • <img> 元素
  • <svg> 中的 <image> 元素
  • <video> 元素(若是定義了封面圖,會影響LCP)
  • url() 背景圖的元素
  • 塊級元素帶有文本節點或者內聯文本子元素

有如下幾種方式能夠保證這些文件儘快的加載:

  • 優化和壓縮圖片
  • 預加載重要資源
  • 壓縮文本文件
  • 自適應服務,如:根據網絡條件加載不一樣資源(例如:4g、3g、2g)
  • 用service worker緩存資源

優化和壓縮圖片

大部分網站的最大元素都是圖片,若是能加速這些圖片的加載,能有效改善LCP。參考如下步驟:

  • 考慮是否必須使用圖片,若是不是必須,移除
  • 壓縮圖片(用imagemin)
  • 轉換成新格式(webp)
  • 使用響應式圖片
  • 使用圖片CDN

預加載重要資源

有時候,在css或者js中聲明或者使用的一個重要資源可能比你預期的要晚獲取,好比字體文件。

若是你明確的知道某個資源須要提升優先級,可使用 <link rel="preload">

<link rel="preload" as="script" href="script.js">
<link rel="preload" as="style" href="style.css">
<link rel="preload" as="image" href="img.png">
<link rel="preload" as="video" href="vid.webm" type="video/webm">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

Chrome73版本以後,預加載同時支持響應式:

<link
  rel="preload"
  as="image"
  href="wolf.jpg"
  imagesrcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w"
  imagesizes="50vw"
>

壓縮文本文件

使用 Gzip 或者 Brotli,gzip支持度較好,brotli的壓縮比更高,但只有更新的瀏覽器才支持。

自適應服務

當加載頁面的主內容的時候,能夠根據用戶設備和網絡條件來加載不一樣的資源。要完成這些,可使用 Network Information, Device Memory, 和 HardwareConcurrency 的api。

if (navigator.connection && navigator.connection.effectiveType) {
  if (navigator.connection.effectiveType === '4g') {
    // Load video
  } else {
    // Load image
  }
}

如下是一些有用的屬性:

  • navigator.connection.effectiveType: 網絡類型,如4G等
  • navigator.connection.saveData: data-saver是否開啓
  • navigator.hardwareConcurrency: cpu核數
  • navigator.deviceMemory: 設備內存

用service worker緩存資源

能夠直接使用 workbox 的第三方庫更方便的緩存資源,這是谷歌提供的一個工具庫。

客戶端渲染

不少網站如今都使用客戶端渲染。一些框架像 angluar, react,vue等,能夠方便的建立spa的單頁面應用,部分替代了服務器的功能。

若是你構建的應用是以上這種方式,須要注意若是你的bundle的js文件過大,會影響LCP。若是不作優化,用戶可能長時間沒法看到頁面,也沒法交互,直到js所有下載執行完。有如下幾個優化項:

  • 減小關鍵js的大小
  • 使用服務端渲染
  • 使用預渲染

減小關鍵js的大小

與減小js阻塞時間同樣。

使用服務端渲染

這樣可讓內容在服務端渲染好,而後返回給瀏覽器,以此來減小LCP。但這種方式存在一些隱患:

  • 代碼複雜性過高,服務端和客戶端用的是同一套js
  • 服務端去執行js,並渲染html,會增長TTFB,相比於僅僅提供靜態html而言
  • 服務端渲染的頁面看上去彷佛能夠交互,但實際上仍是要等待js執行完成才能交互。簡單地說,會增長 TTI(Time to Interactive)

使用預渲染

預渲染是一個獨立的技術,主要是爲了解決服務端渲染的代碼複雜度。經過啓動一個無頭瀏覽器,在構建的時候就將每一個路由頁面渲染好並建立對應的html文件,這些文件也能夠和對應的js bundles一塊兒使用。

預渲染的方式,不能改善TTI,但對TTFB會比服務端渲染要更好些。

開發者工具

開發者工具已經能夠針對實驗數據進行這些指標的測試:

  • lighthouse
  • performance中的timeline

總結

本文只是對LCP的優化作了簡單而又比較全的介紹,後面的文章會針對個別項進行單獨的介紹。

參考

https://web.dev/optimize-lcp/

相關文章
相關標籤/搜索