跳至主要内容

網站使用體驗核心指標 (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 技巧


其他 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 StatsDevtool performance
  • 檢查網頁整體效能狀況
    • 位置: DevTools -> Performance
    • 使用錄製按鈕,可以查看錄製期間程式執行、畫面渲染等花費時間
    • 可以降低 CPU 速度以便更明確 的發現問題癥結點
  • CRUX dashboard
    • CrUX 涵蓋所有以使用者為中心的核心 Web Vitals 指標 (Core Web Vital)
    • 資料蒐集自真實世界中符合資格的瀏覽器,這些資料是由依據各種決定使用者體驗的維度和指標集合而成!
    • 用 filed data 去測
    • 可隨時查閱過去幾年的 CrUX 數據
  • 可使用 web-vitals 即時協助搜尋 FID 或是其他指標的資訊,因 Google 目前所提供的工具在驗證和偵測並不及時,CrUX 甚至必須等待近一個月才能看到更新資訊,透過實地資料的搜集和驗證會更便利和詳盡
  • 使用 workbox 做前端離線支持和緩存策略。

其他參考資料