具代表性的面試主題

如何用 firstInterimResponseStart 衡量 Early Hints 的實際收益?

前端中等
Offer.cc 編輯團隊發佈 更新

題幹

請實作一個前端效能觀測器,統計資源收到首個 1xx 回應的時間,並說明如何區分 103 Early Hints、快取、跨來源遮蔽和瀏覽器不支援。

題目與背景

瀏覽器開始支援 PerformanceResourceTiming.firstInterimResponseStart,它記錄收到首個暫時 1xx 回應位元組的時間。請實作觀測邏輯,評估 103 Early Hints 是否縮短資源準備時間,並處理不支援、跨來源和快取場景。

面試官考察什麼

  • 是否理解 requestStartfirstInterimResponseStart 和最終回應標頭時間的關係。
  • 是否知道 0 既可能表示沒有 1xx,也可能來自跨來源時序遮蔽或快取。
  • 是否能用 PerformanceObserver 處理 buffered 項目和上報抽樣。
  • 是否能把協定收益與瀏覽器相容、Timing-Allow-Origin 和業務指標分開。

先問清楚的澄清問題

觀測目標

要衡量收到 1xx 的等待時間、Early Hints 觸發的預載數量,還是最終 LCP、首屏可互動時間?

資源範圍

只觀測同源主導覽,還是包含 CDN、字型和跨來源腳本?跨來源回應是否設定 Timing-Allow-Origin

相容性策略

資料是否用於即時決策?舊瀏覽器和不支援該屬性的瀏覽器是否必須提供同等降級指標?

30 秒回答框架

我會用 PerformanceObserver 讀取資源項目,在屬性存在且值大於零時計算 firstInterimResponseStart - requestStart。零值不能直接判定伺服器沒發 103,因為跨來源時序可能被遮蔽,快取也會給出零。觀測系統要記錄支援能力、資源同源性和最終回應時間,並用 LCP 等使用者指標驗證 Early Hints 是否真的帶來收益。

深入解答步驟

1. 說明時間點語義

requestStart 表示瀏覽器即將發出資源請求的時間;firstInterimResponseStart 表示收到首個 1xx 回應的首位元組時刻;finalResponseHeadersStart 表示最終回應標頭到達。若存在暫時回應,firstInterimResponseStart - requestStart 可近似首個 1xx 的網路等待。

2. 寫出觀測器

js
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    const interim = entry.firstInterimResponseStart;
    if (typeof interim !== "number" || interim <= 0) continue;

    reportTiming({
      name: entry.name,
      interimWait: interim - entry.requestStart,
      finalHeaders: entry.finalResponseHeadersStart - interim,
      initiator: entry.initiatorType,
    });
  }
});

observer.observe({ type: "resource", buffered: true });

生產程式碼應先做屬性偵測,並限制資源名稱、抽樣率和上報欄位,避免把完整 URL 或敏感查詢參數送到分析系統。

3. 解釋零值

值為 0 可能表示沒有暫時回應,也可能表示跨來源資源沒有透過 Timing-Allow-Origin 暴露時序;快取命中和取消請求也可能使相關時刻為 0。因此儀表板應把「未觀測到」與「確認沒有 1xx」分開,不要用零值計算負數或直接標記失敗。

4. 處理跨來源資源

若 CDN 或字型來自其他來源,伺服器需要對允許的網站回傳 Timing-Allow-Origin,瀏覽器才會暴露受保護的計時欄位。該標頭必須按實際部署來源設定,不能對所有來源開放;同時仍要接受部分使用者因策略不同而不可觀測。

5. 區分 103 與最終收益

該屬性告訴你收到某個 1xx 的時間,不直接證明它是 103,也不證明預載資源被使用。結合導覽請求、伺服器日誌或受控實驗確認 103,再比較 finalResponseHeadersStart、資源 responseEnd 和 LCP。若預載過早或命中錯誤資源,首個 1xx 變快也可能讓效能變差。

6. 設計相容降級

不支援屬性的瀏覽器仍可上報 requestStartresponseStartresponseEnd 等基礎指標,但不能偽造 interim 時間。用能力欄位標記瀏覽器是否支援該屬性,並將新舊樣本分開彙總;不要因 API 缺失就阻斷頁面渲染。

7. 建立驗證和治理

在 HTTP/2 或更高協定、同源和跨來源、快取命中與未命中、伺服器傳送與不傳送 103 的環境中做對照。檢查 interimWait >= 0、最終標頭時間不早於首個暫時回應,並限制上報頻率。指標解釋要同時查看 LCP、預載命中率和錯誤率,避免把網路時鐘當作業務結果。

高品質示例回答

我會用 buffered PerformanceObserver 讀取 firstInterimResponseStart,只在屬性存在且非零時報告 1xx 等待時間。零值保留為不可判定狀態,並結合同源性、Timing-Allow-Origin、快取和瀏覽器能力分層。是否採用 Early Hints 要由受控實驗中的 LCP、資源命中率和錯誤率決定,而不是只看首個暫時回應較早。

常見錯誤

  • firstInterimResponseStart 非零當成一定收到 103。
  • 把零值一律解釋為伺服器沒有發 1xx。
  • 忽略跨來源 Timing-Allow-Origin 導致的資料缺口。
  • responseStart 代替最終回應標頭時間,混淆 1xx 與最終回應。
  • 只在頁面載入後呼叫 getEntriesByType,漏掉建立觀察器前的項目。
  • 只看網路時序,不驗證 LCP、預載命中和錯誤率。

追問與回答

firstInterimResponseStart 能確認是 103 嗎?

不能。它記錄首個 1xx 回應位元組,可能是 100 Continue 或其他暫時回應。要確認 103,應結合伺服器日誌、受控請求和資源載入行為。

為什麼跨來源資源經常是零?

Resource Timing 會遮蔽跨來源時序;沒有匹配的 Timing-Allow-Origin 時,相關欄位回傳零。應修正回應策略或把樣本歸為不可觀測,而不是補寫估算值。

responseStartfinalResponseHeadersStart 有何區別?

存在暫時回應時,responseStart 可能反映首個暫時位元組;finalResponseHeadersStart 用於最終回應標頭時間。評估伺服器準備時間應優先使用後者。

舊瀏覽器如何降級?

做能力檢測,繼續採集通用的請求和回應時間,並用欄位標記缺少 interim 指標。舊瀏覽器樣本應與新 API 樣本分開彙總。

如何證明 Early Hints 值得保留?

在相同網路、快取和資源版本下做啟用與停用對照,比較 LCP、預載命中率、最終標頭時間、資源完成時間和錯誤率;首個 1xx 較早只是中間證據。

公開來源

同類題目