跳至主要内容

網站使用體驗核心指標 (Core Web Vitals)


  • 提供多個指標評估網站的性能
  • 幫助我們關注網站性能中幾項重要的參考指標

架構圖​

About page experience

Page Experience 是一整組排名因素的訊號,這組訊號底下又可以被拆分成 6 個不同的項目。 而其中綠色區塊的 3 個項目被 Google 稱為 Core Web Vitals(網站活力指標),這 3 個項目都是與『網站速度』有關的指標

資料來源:Google. (2020). Evaluating page experience for a better web. Retrieved from

webmasters


Core Web Vitals 的 3 個指標​

2020 年的當前集合重點放在用戶體驗的三個方面

  • 最大內容繪製 (LCP) (Largest Contentful Paint)
    • 頁面的 LCP 應在頁面開始加載的 2.5 秒內出現,用來評估載入性能
  • 首次輸入延遲 (FID) (First Input Delay) ❤️
    • 頁面的 FID 應小於 100 毫秒,用來評估網頁的可互動性
  • 累積佈局偏移 (CLS) (Cumulative Layout Shift) 🐱
    • 頁面的 CLS 應保持在 0.1 以下,用來評估視覺穩定性

圖片參考


最大內容繪製 (LCP) (Largest Contentful Paint)​

  • 可見範圍內(viewport)最大的 可視內容完成渲染的時間
  • LCP 有可能是圖片、影片或是文字區塊
  • 透過 Chrome 套件看最大 LCP 元素 :

LCP 範例​

LCP example

說明 : 最大的元素會隨著內容加載而變化。 在第一個範例中,新內容被添加到 DOM 中,這改變了最大的元素。 在第二個範例中,Layout 發生變化,之前最大的內容從 Viewport 中刪除。

圖片範例


優化 LCP 技巧​


減少伺服器回應時間​

可使用Time to First Byte 第一個 byte 載入時間(TTFB) 來測量 Server 響應時間 (waiting for server response)

  1. 針對主機進行優化

  2. 使用 CDN 將網頁內容分發到全球各個地區的 Server 上

    • 讓網頁可從最近的 Server 獲取內容,從同時加速網頁加載速度。
    • 將靜態資源(如圖、CSS 和 JavaScript 文件)保存到 CDN 上,以減少 Server 的負載,並通過保存來提供高用戶體驗。
  3. 優先使用緩存提供 HTML 頁面

    • 可以透過 Service Worker API 實作
    • 使用 Next.js 的 SSG 有助於提高網站的性能及 SEO
    • 配置反向代理(Varnish、nginx)来提供缓存内容
  4. 儘早讓第三方的資源提早載入

    對第三方域的服務器請求也會影響 LCP,尤其是當瀏覽器需要這些請求來在頁面上顯示關鍵內容的情況下。使用rel="preconnect"來告知瀏覽器您的頁面打算盡快建立連接。

    當網頁需要取得跨來源(cross-origin)的資源時可預先建立 TCP 連線!

    • 連接 CDN 取得圖片或其他靜態資源都建議加上此設定 🔥
    • 此設定可改善 TTFB 與 FCP 問題 (DNS, TCP Handshake, TLS Handshake)
    <link rel="preconnect" href="https://cdn.jsdelivr.net" />
    <link rel="preconnect" href="https://font.googleapis.com" />

加快資源載入的時間​

1. 優化圖片 / 影片​

大部分網站的最大元素都是圖片,如果能加速這些圖片的加載,能有效改善 LCP

  • 技巧:

    • 將圖片壓縮: .png /.jpg -> .webp(已壓縮圖片)

    • 把圖片放在 CDN 參考來源

    • 使用響應式圖片

    • 延遲加載其他非 LCP 圖像(Viewport 內的圖片不要延遲加載)

      • Using Intersection Observer
        • image 再加上 lazy,並使用 JavaScript 延遲加載,等接近 viewport 時在更換 data-srcset =>src 跨瀏覽器兼容作法
      • 使用瀏覽器的 lazy loading(在 Viewport 內或是靠近 Viewport 時開始載入) 參考來源
    • 使用<link rel="preload">來更加及時地獲取圖片資源或是 LCP 元素(從 ChromDev Tools 找到 LCP 元素)

      瀏覽器解析 HTML 流程:

      • before: 瀏覽器經由解析 HTML 後,進而從 JS 檔案中找到 LCP 圖檔。
      • after: 瀏覽器解析 HTML 同時經由 preload 得知,要預先加載 LCP 大圖,同時下載 JS 檔案,省下從 js 檔案找到 LCP 圖片的時間,減少延遲時間
      <link as="image" href="sample.jpg" rel="preload">
    • 若圖檔存在第三方網域,可以加上 proconnect 和 dns-prefetch 儘早建立連線或是預先做 DNS 解析

    • 使用 srcset 屬性 和 size 屬性

      • 根據螢幕的 pixel density(適用於圖片大小固定的情況) 或是圖片在螢幕上的實際寬度(適用於圖片會隨螢幕大小變化的情況),決定要載入哪張圖片。
      • 針對擁有高解析度的螢幕提供更精細的圖片大小,確保不同大小的圖片都擁有相同的長寬比例(aspect ratio)
    // 根據裝置的 Pixel Density 載入不同版本的圖片
    // 桌機螢幕的 pixel density 通常是 1x,而中高階的手機通常都有 3x。
    <img src="https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=200&h=200&q=80&txt=200&txt-size=20&fm=jpg"
    alt="Cat" title="依據螢幕大小顯示不同圖片" loading="lazy" decoding="async"
    srcset="
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=200&h=200&q=80&txt=200%20%281x%29&txt-size=20&fm=jpg,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=300&h=300&q=80&txt=300%20%281.5x%29&txt-size=30&fm=jpg 1.5x,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=400&h=400&q=80&txt=400%20%282x%29&txt-size=40&fm=jpg 2x,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=600&h=600&q=80&txt=600%20%283x%29&txt-size=60&fm=jpg 3x "
    />

    // 根據圖片寬度載入不同版本的圖片
    // srcset 的寬度 (w) 的算法是:圖片寬度 (pixel) * Pixel Density,預設圖片寬度 = 100% 的 viewport 寬度。
    // e.g. Viewport = 1000px,1x 的螢幕,圖片寬度 = 1000w ; Viewport = 500px,2x 的螢幕,圖片寬度 = 1000w。(因為在 pixel density = 2x 的螢幕上,顯示寬 500px 的圖片實際上需要 1000px)
    // 只有在 srcset 以 w 為單位時才可使用 sizes。
    <image src="https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=200&h=200&q=80&txt=200&txt-size=20&fm=jpg"
    alt="Cat" title="依據螢幕大小顯示不同圖片" loading="lazy" decoding="async"
    srcset="
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=200&h=200&q=80&txt=200&txt-size=20&fm=jpg 200w,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=320&h=320&q=80&txt=320&txt-size=30&fm=jpg 320w,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=481&h=481&q=80&txt=481&txt-size=40&fm=jpg 481w,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=769&h=769&q=80&txt=769&txt-size=60&fm=jpg 769w,
    https://images.unsplash.com/photo-1529778873920-4da4926a72c2?fit=clamp&w=1025&h=1025&q=80&txt=1025&txt-size=60&fm=jpg 1025w
    "
    sizes="
    (max-width: 320px) 200px,
    (max-width: 481px) 320px,
    (max-width: 769px) 481px,
    (max-width: 1025px) 769px,
    1025px
    "
    />
    • 使用 fetchpriority="high" 指定圖像元素來提高 LCP 圖像的優先級 官方建議
        <img src="hero-image.jpg" fetchpriority="high" alt="Hero">
    • 使用<picture>標籤載入圖片 參考來源
      • 瀏覽器會自動判斷並下載其中一種格式的圖片 ( AVIF > WebP > JPG )
    <picture>
    <source srcset="image.avif" type="image/avif">
    <source srcset="image.webp" type="image/webp">
    <img src="image.jpg" alt="A description of the image."
    width="300" height="200" loading="lazy" decoding="async">
    </picture>
    • 延遲載入 Videos
      • 對於不自動播放的影片加上 preload="none" 參考來源
      <video controls preload="none" poster="one-does-not-simply-placeholder.jpg">
      <source src="one-does-not-simply.webm" type="video/webm">
      <source src="one-does-not-simply.mp4" type="video/mp4">
      </video>
資訊

如果 LCP 是圖像,渲染時間是圖片加載後立即繪製的時間。這意味著 Lazy loading Viewport 內的圖片無助於減少 LCP。

如果 LCP 是文本元素, 則考慮最早的字體加載。 所以字體可以更新,而 LCP 渲染時間保持不變。

2. 優化 CSS​

CSS 文件可以包含空格、縮進或註釋等字符。這些字符對於瀏覽器來說都不是必要的,而對這些文件進行削減能夠確保將這些字符刪除。最終,在減少了阻塞渲染的 CSS 數量後,充分渲染頁面主要內容所需的時間(LCP) 也總是能夠相應地縮短。

  • 可以透過 Webpack 將 CSS 打包 參考來源

  • 把關鍵 CSS 放在 HTML 檔裡面 參考來源

    • 內聯關鍵 CSS
  • 預先下載關鍵資源 參考來源

    • 通過在 HTML 文檔的 head <link rel=preload> 標記來預加載關鍵資源 參考來源
      • 預載的 JS / CSS 都不會真的執行,只會被背景下載而已
      • 下載的過程不會佔用主執行緒,但會提高優先權! 👍
      • 透過 preload 只會提前去請求該資源,然後存在記憶體中,在你需要的時候自己再去使用(只限同一頁面) 參考來源
    // 如果LCP元素是從外部 css 或 JavaScript 文件引用 獲得,則加上preload提高優先度
    // 假設 LCP元素是 css 指定的 background-image 時,可以先針對這張圖片做 preload
    <!-- Load the stylesheet that will reference the LCP image. -->
    <link rel="stylesheet" href="/path/to/styles.css">

    <!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
    <link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">
  • 延遲加載非關鍵 CSS(onLoad) 參考來源

    • 使用 Chrome 開發者工具中的代碼覆蓋率選項卡查找您網頁上任何未使用的 CSS。(紅色表示未使用的代碼,綠色表示使用過的代碼)

    優化方式: 參考來源

    • 如果是在您網站的單獨頁面上使用,可以將所有未使用的 CSS 完全刪除或移動到另一個樣式表。
    • 對於任何初始渲染時不需要的 CSS,請使用 loadCSS 來異步加載文件
    • 用 JS 延遲加載尚未用到的 CSS
      var link = document.createElement("link");
      link.id = cssId;
      link.rel = "stylesheet";
      link.type = "text/css";
      link.href = "http://website.example/css/stylesheet.css";
      head.appendChild(link);
  • 優化 CSS 背景圖片

       // 手機
    @media (max-width: 480px) {
    background-image: url(images/background-mobile.jpg);
    }
    // 平板電腦
    @media (min-width: 481px) and (max-width: 1024px) {
    background-image: url(images/background-tablet.jpg);
    }

3. 優化字體​

  • 用 Brotli 將文字檔案進行壓縮,須先檢查 Server 是否已經自動壓縮文件

  • 使用<link rel="preload">來更加及時地獲取文字檔案,但這是以從加載其他資源中奪走瀏覽器資源為代價的。

  • 如果是使用第三方資源加載字體,要使用 preconnect

    <head>
    <link rel="preconnect"href="https://fonts.com">
    </head>
  • use font-display: 加上 display=swap 後,網頁會先以系統預設的字體呈現,等 Web Font 下載完畢之後再進行替換,所以不會有白一片的情況發生。
    參考來源 1 參考來源 2

    https://fonts.googleapis.com/css2?family=Crimson+Pro&display=swap
  • 優化您的字體請求 : 加上 text=,在字體請求 URL 中指定一個值。這允許 Google Fonts 返回針對您的請求優化的字體文件。在某些情況下,這可以將字體文件的大小減少多達 90%。 參考來源

    https://fonts.googleapis.com/css2?family=Comfortaa&text=Hello
  • 把 inlining font declarations 放在 <head> 裡面 參考來源

    <head>
    <style>
    @font-face {
    font-family: "Open Sans";
    src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    }

    body {
    font-family: "Open Sans";
    }

    ...etc.

    </style>
    </head>

4. 優化 Javascript​

瀏覽器在能夠渲染任何內容之前,需要將 HTML 標記解析為 DOM 樹。如果 HTML 解析器遇到任何外部樣式表(<link rel="stylesheet"/>)或同步 JavaScript 標籤(<script src="main.js"/>),則會暫停解析。

瀏覽器在完成渲染前,遇到 CSS 或是需要同步的 JS 的外連檔案時,HTML 會暫停解析,改去下載該檔案, 所以需要讓延遲渲染的情況減到最低

  • 使用 async 或 defer 延遲加載任何非關鍵的 JavaScript Sentry price

  • 延遲加載第三方 script 參考來源

    form.addEventListener("submit", (e) => {
    e.preventDefault();
    import("library.moduleA")
    .then((module) => module.default) // using the default export
    .then(() => someFunction())
    .catch(handleError());
    });

    const someFunction = () => {
    // uses moduleA
    };
  • 使用 service workers 緩存來自第三方服務器的腳本

  • code splitting

    • 如果網站嚴重依賴 client 端呈現,可以減少負責呈現 JavaScript 的大小可能會改善最大內容繪製 (LCP)時間
  • 查看瀏覽器有多少 CSS 和 JS 代碼未使用。

  • Tree shaking 參考來源

  • 確認資源的重要度,預先載入 關鍵 Script,等到需要用的時候直接讀取(限定同一頁)

    // 預先載入
    方法1: <link rel="preload" href="my-script.js" as="script">

    方法2:
    var preloadLink = document.createElement('link');
    preloadLink.href = 'my-script.js';
    preloadLink.rel = 'preload';
    preloadLink.as = 'script';
    document.head.appendChild(preloadLink);

    // 在需要用到時再載入
    方法1: <script src="my-script.js"></script>
    方法2:
    var preloadedScript = document.createElement('script');
    preloadedScript.src = 'my-script.js';
    document.body.appendChild(preloadedScript);
  • 延遲載入非關鍵 JS 實作(FB SDK、loadJS)

      var script = document.createElement("script");
    script.src = src;
    script.async = true;
    script.addEventListener('load', onload);
    document.head.appendChild(script);

    或者用 async 屬性,讓其在背景下載後再做解析和執行

    <script async scr="https://platform.twitter.com/widget.js" charset="utf-8" />
  • 使用 Intersection Observer ,等到進入 Viewport 時加載

  • 可以使用 Webpack 的 plugin : preload-webpack-plugin 協助設定需要 preload 的資源,讓某些打包的檔案可以預先載入

    plugins: [
    new HtmlWebpackPlugin(),
    new PreloadWebpackPlugin({
    rel: "preload",
    include: "allCuunks",
    }),
    ];
  • 拆分出共用的 Chunks

    • SplitChunksPlugin
    const splitChunksConfigs = {
    …
    prod: {
    chunks: 'all',
    cacheGroups: {
    default: false,
    vendors: false,
    commons: {
    name: 'commons',
    chunks: 'all',
    minChunks: totalPages > 2 ? totalPages * 0.5 : 2,
    },
    react: {
    name: 'commons',
    chunks: 'all',
    test: /[\\/]node_modules[\\/](react|react-dom|scheduler|use-subscription)[\\/]/,
    },
    },
    },

首次輸入延遲(FID)(First input Delay)​

畫面渲染完成之後,瀏覽器可能仍不停的在載入、解析、執行 JS 程式碼,在這過程中主執行序依舊忙碌,此時使用者和網頁互動,則可能無法及時回應。

故 FID 為網頁載入後,使用者第一次與網頁互動~瀏覽器對此互動做出回應的時間差 = 最快可以與畫面互動的時間.

  • 所謂互動的意思代表著會對畫面上元素如 <input>、<select> 或 <a> 等產生事件
  • 瀏覽器上所有可互動的元素都必須等待主執行緒上沒有任務後,才可以進行互動

FID 差的主要原因是 JavaScript 執行繁重。
優化 JavaScript 在您的網頁上解析、編譯和執行的方式將直接減少 FID。
計算使用者第一次與網頁互動(點擊連結、點開下拉選單、填表格…etc)時的延遲時間。
這項指標代表了網頁的回應性,在使用者嘗試與網頁互動時是否能馬上回應。


優化 FID 技巧​

  1. 減少第三方程式的影響
  2. 減少 JavaScript 執行時間
  3. 最小化執行緒工作

減少第三方程式的影響​

第三方腳本包括: 社交分享按鈕、播放器嵌入、廣告內嵌框架 第三方腳本是導致性能下降的主要原因,並且通常是由您無法控制的資源引起的。 (e.g. 對多個服務器發出過多的網絡請求、HTTP 緩存不足...等 )

當第三方 iframe 中的腳本需要很長時間運行時,它們會阻塞主線程以延遲其他任務的運行。

衡量第三方腳本影響

  1. 打開 Chrome DevTools Network Panel,測量頁面加載時間,阻止可能會拖慢速度的第三方腳本並重新測量加載時間,建議進行多次測量以獲得更穩定的數據。 參考來源
  2. 使用 WebPageTest 衡量第三方腳本的影響
  3. 延遲載入 IFrames 參考來源
  4. 延遲加載 Google tag 參考來源 官方原始碼 使用 next.js 官方套件
  5. 延遲載入 Youtube 資源: 參考來源

優化方法

  1. 使用 async 或 defer 屬性加載腳本以避免阻止文檔解析。
  2. 延遲加載第三方資源,僅在必要時加載嵌入式資源 image alt

官方連結

  1. https://developer.chrome.com/docs/lighthouse/performance/third-party-summary/
  2. https://web.dev/third-party-javascript/

減少 JavaScript 執行時間​

延遲未使用的 JavaScript

用 Chrome DevTools 中的 Coverage 選項卡可以告訴您有多少 JavaScript 未在您的網頁上使用
也可以用 Chrome DevTools 的 Performance 選項來錄製效能資訊,找出哪個檔案、哪個 func 長時間佔用值行緒

優化方法

  1. 將 bundle 拆分為多個 chunks 並且將 chunk 動態的載入(dynamic import)
    透過 dynamic import 可以在「真正」需要時才載入相關程式,可以避免 在使用 import from '...' 時直接被 Webpack 打包在一起
// 僅在用戶提交表單時使用動態導入來獲取 module
form.addEventListener("submit", e => {
e.preventDefault();
import('library.moduleA')
.then(module => module.default) // using the default export
.then(() => someFunction())
.catch(handleError());
});

const someFunction = () => {
// uses moduleA
}
  1. 對於 async or defer 非關鍵的 script
<script defer src="…"></script>
<script async src="…"></script>
  1. tree shaking
  2. 最小化(minfy)檔案: 在打包時移除用不到的程式碼,例如: 註解、空白,可以透過 webpack 的 plugin(uglifyjs-webpack-plugin or terser-webpack-plugin)

最小化執行緒工作​

觀念: 分解長任務

把任務切小,避免長時間佔用主執行序可減輕 FID 問題

  • 長任務是 JavaScript 執行週期。任何阻塞主線程 50 毫秒或更長時間的代碼都可以稱為長任務。 拆分長任務可以減少 input 延遲。
  • Lighthouse 會標記在加載期間使主線程忙碌超過 4 秒的頁面,並且顯示了瀏覽器加載頁面時 CPU 時間花費在哪裡的細目分類。
    參考來源
  • 從 chrome perfomance tab 分析頁面加載時主線程正在做什麼工作,並找到推遲或刪除不必要工作的方法。

優化方法

Script evaluation

  1. 優化第三方 JS 腳本,依據 JS 的特性選用適當的 JS 載入方式 (defer, async)
  2. Debounce input handler
  3. 使用 Web worker 在背景將單執行緒->多執行緒 Web Worker 主要用於在 Web 瀏覽器中執行昂貴的任務,例如對大量資料進行排序、CSV 導出、圖像處理等。

rendering

  1. 用 transform and opacity 寫 animations 取代 top

    • top 和 left 的改變會觸發瀏覽器的 reflow(Layout)和 repaint(Paint) 。然後整個動畫過程都在不斷觸發瀏覽器的重新渲染,這個過程是很影響性能的; 而 transform 和 opacity 動畫由 GPU 控制,不會觸發 repaint。 參考資料 image alt

    • 盡可能使用合成動畫(composited animations)的方式繪製和渲染畫面,使用 transform 和 opacity CSS 屬性進行轉場時,會使用獨立的圖層進 行動畫,直到動畫結束後才合成回原來的圖層

  2. 用 will-changeCSS 屬性創造新圖層(will-change: transform) 但是,必須注意不要創建太多層,每個圖層須內存和管理,使用前先用 DevTools 確認這樣做是否為帶來了性能優勢。不要在沒有分析的情況下提升元素。查看更多

教學:

  1. https://developer.chrome.com/docs/lighthouse/performance/mainthread-work-breakdown/#how-to-minimize-main-thread-work
  2. https://dev.to/nilanth/multi-threaded-react-app-using-useworker-gf8
資訊

圖層太多也可能佔用太多記憶體,以及合成時運算時間變長,因此建議有遇到效能問題時才能獨立圖層


累積佈局偏移(CLS) Cumulative Layout Shift​

計算了網頁元件在載入時的非預期移位 佈局偏移分數 = 影響可視範圍比例 * 移動距離比例 若偏移不是網站本身預期的行為,使用者體驗就會受到影響


優化 CLS 技巧​

  • 預先指定圖片或影片的尺寸

    <div class="container">
    <img class="media" src="..." alt="...">
    </div>

    .container {
    width: 100%;
    aspect-ratio: 16 / 9;
    }

    • 提供 width 和 height 在 image 和 video 元素上 參考來源
    <img src="image.jpg" alt="..." width="640" height="360">
    img {
    width: 100%;
    height: auto;
    }
    • 為延遲加載的廣告內容保留空間 加上 min-height 保留空間 image alt
  • 盡量不要在目前畫面的上方插入新的內容

  • 使用 CSS 轉換動畫


其他 Web 指標​

做為核心指標的補充,其他指標可以幫助我們捕捉更大範圍的使用體驗,或是 診斷特定問題

  • 第一個 Byte 載入時間 (TTFB) 和首次內容繪製 (FCP) 和載入體驗有關
    • 這兩個指標可以幫助我們診斷LCP的問題
  • 總阻塞時間 (TBT) 和可互動時間 (TTI) 與互動體驗有關
    • 這兩個指標也會影響到FID的分數

第一個 Byte 載入時間 (Time to first byte)(TTFB)​

從 HTTP 請求開始到回應第一個 byte 的時間

image alt TTFB 包含以下行為的總耗損

  • 網址轉向時間延遲
  • Service Worker 啟動延遲
  • DNS 查詢延遲
  • 建立連線和 TLS 延遲
  • 伺服器接受請求值到回應開始的延遲

減少連接設置時間和後端的延遲將有助於降低 TTFB。

優先使用 Field data 來檢測(受 redirects 的影響),因為 Lab data 通常使用最終 URL 進行測量,因此會錯過這種額外的延遲。

資訊

TTFB 不是 Core Web Vitals 指標,因此網站滿足“良好”TTFB threshold 並不是絕對必要的,前提是它不會妨礙他們在重要指標上取得好成績的能力。


優化 TTFB 技巧​

  • 增加伺服器端處理能力
  • 減少網址轉向
  • 跨網域存取資源使使用 Preconnect
  • 使用 HTTP/2 或 HTTP/3
  • 使用 CDN

首次渲染時間(FCP)(First contentful paint)​

網頁第一個元素渲染發生的時間 image alt


優化 FCP 技巧​

加快 FCP 的前提是,要確保伺服器本身的速度夠快 ;如果伺服器配備太弱或網速太慢,光是連線下載資料的時間就可以把秒數用完了,更不要說渲染了。

  • 減少伺服器回應時間
  • 壓縮 CSS
  • Inline 內聯關鍵 CSS 並延遲 non-critical CSS
  • 減少阻擋渲染的資源:
    • 預先載入關鍵請求: <link rel="preload"> 參考來源
    • 把 <script> 加上 async 或 defer 屬性
  • 使用 font-display: swap 確保載入網站字體時內容依然可見(邊載入字體邊套用,避免一開始網頁整個變白畫面,直到載入完畢才一起顯示)

可互動時間(TTI)(Time to interactive)​

主要畫面渲染及 long tasks 都已經完成,且能可靠地進行互動所需的時間

=> FCP 後,若主執行緒沒有執 long tasks,並且在未來五秒沒有網路請求,這樣的時間點稱為靜窗 (quiet window),而從 FCP 到靜窗時間的時間差即為 TTI。

long task: 超過 50ms 的任務,可能是解析 HTML 建立 DOM Tree、解析 CSS 套用樣式、執行 JS 等。

image alt


優化 TTI 技巧​

目前大多使用 FID 和 TBT 來改善互動性


總阻塞時間(TBT)(Time Blocking time)​

  • 從 FCP 到 TTI 之間造成阻塞的總時間
  • 超過 50ms 的任務 (長任務) 會被視為阻塞,超過 50ms 的部分將會被加總 image alt

優化 TBT 的方法​

  1. 減少第三方程式的影響
  2. 減少 JavaScript 執行時間
  3. 最小化執行緒工作

其他優化 Web vitals 建議​

  • Carousels 圖片輪播 參考來源
    • 靜態加載第一張圖片
  • 使用 CSS transform 屬性 取代 left、top、width 和 marginTop 用來 避免 CLS
  • 自訂字型 (Fonts)
  • 透過開發者工具檢查動畫影響效能相關問題
    • 檢查畫面上的圖層 : DevTools -> More tools -> Layers (圖層)
    • 檢查畫面正在合成的元素 : DevTools -> More tools -> Rendering (算繪) -> Paint flashing (閃動顯示繪製區域)
    • 檢查畫面渲染的 FPS : DevTools -> More tools -> Rendering (算繪) -> Frame Rendering Stats Devtool performance
  • 檢查網頁整體效能狀況
    • 位置: DevTools -> Performance
    • 使用錄製按鈕,可以查看錄製期間程式執行、畫面渲染等花費時間
    • 可以降低 CPU 速度以便更明確 的發現問題癥結點
  • CRUX dashboard
    • CrUX 涵蓋所有以使用者為中心的核心 Web Vitals 指標 (Core Web Vital)
    • 資料蒐集自真實世界中符合資格的瀏覽器,這些資料是由依據各種決定使用者體驗的維度和指標集合而成!
    • 用 filed data 去測
    • 可隨時查閱過去幾年的 CrUX 數據
  • 可使用 web-vitals 即時協助搜尋 FID 或是其他指標的資訊,因 Google 目前所提供的工具在驗證和偵測並不及時,CrUX 甚至必須等待近一個月才能看到更新資訊,透過實地資料的搜集和驗證會更便利和詳盡
  • 使用 workbox 做前端離線支持和緩存策略。

其他參考資料​