題幹與適用場景
一個電商詳情頁同時載入分析、客服、廣告和 A/B 測試腳本。行動裝置真實使用者的 p75 LCP 為 3.8 秒、INP 為 280 毫秒,第三方 JavaScript 傳輸約 1.2 MB,來自 14 個來源;桌面實驗室測試卻看起來正常。你需要在保留必要業務能力的同時,降低第三方程式碼對網路、主執行緒、隱私和頁面可用性的影響。
先釐清四個邊界:哪些腳本必須在首屏前執行,哪些只在使用者操作後需要;腳本是否相互依賴執行順序;使用者同意前是否允許傳送資料;第三方故障時頁面是否仍必須完成購買。第三方腳本是頁面執行環境的一部分,不能只當成普通靜態資源或交給行銷團隊後不再負責。
這道題適合前端、Web 平台和效能工程職位。公開前端面試資料把 async、defer、腳本順序和效能取捨列為常見基礎題;web.dev、MDN 和 W3C 資料可核驗載入時機、長工作、CSP 和腳本來源控制。題目核心是治理與驗證,不是背誦某個框架的元件名稱。
面試官考察點
普通回答會說「全部加 async」或「把腳本放到頁面底部」。強回答會先依使用者價值和關鍵路徑盤點腳本,再根據依賴關係選擇 async、defer、模組、互動後載入或 iframe facade,並定義每個腳本的故障邊界。
面試官重點看五項能力:能否區分下載時間與執行時間;能否解釋 async 的無序執行和 defer 的順序保證;能否把效能預算、同意管理、CSP/SRI 和供應鏈風險放在同一個決策裡;能否隔離第三方故障而不阻塞結帳;能否用 RUM、長工作和分組實驗證明改動有效。
只引用 Lighthouse 分數不夠。實驗室環境不能代表低階手機、慢網路、廣告攔截器或第三方伺服器抖動;還要看到真實使用者分位數、腳本執行耗時和業務完成率。
回答前需要釐清的問題
- 首屏真的需要哪些腳本? 支付按鈕或必要風控可能是關鍵路徑;客服、推薦和回放通常可以等到互動或閒置時。
- 腳本之間有依賴嗎? 獨立分析適合
async;依賴 DOM 或固定順序的應用程式腳本通常用defer;依賴不明時不能並行。 - 使用者同意前能收集什麼? 先定義目的、地區和同意狀態,再決定是否建立腳本、cookie、網路請求或匿名統計。
- 第三方能存取頁面中的什麼資料? 同源腳本可讀取頁面上下文;客服和廣告若只需展示,優先使用 iframe 或伺服器事件,縮小權限。
- 故障時的使用者體驗是什麼? 購買、登入和導覽必須有第一方路徑;第三方逾時不能讓主執行緒或關鍵按鈕永久等待。
- 能否替換或自託管? 自託管減少 DNS 和供應商故障,但要負擔更新、完整性、授權和快取責任,不能無條件視為更安全。
30 秒回答框架
「我會先建立第三方腳本清單,記錄業務價值、依賴、位元組數、網路請求、主執行緒時間、資料目的和故障影響,再把腳本分成關鍵、延後和可刪除三類。獨立腳本用 async,需要 DOM 或順序的腳本用 defer,互動元件用 facade 或 iframe,絕不把所有腳本統一並行。使用者同意前不建立非必要追蹤,CSP 只允許經過審核的來源,固定資源再配合 SRI。每個供應商有位元組、執行時間和錯誤預算;RUM 按裝置和同意狀態比較 LCP、INP、長工作、業務轉換和腳本錯誤。先灰度刪除或延後,再用故障注入和回滾證明頁面仍可完成核心任務。」
分步驟深入解答
1. 建立腳本清單和關鍵路徑
每個腳本記錄供應商、版本、載入觸發器、依賴、請求網域、傳輸位元組、解析與執行時間、長工作、讀取的資料、業務負責人和刪除條件。把收益寫成可驗證結果,例如「識別結帳失敗來源」,不要寫成「提升體驗」。沒有清晰目的、負責人或指標的腳本先列入刪除候選。
再畫出首屏和第一次互動的依賴圖。關鍵路徑只保留渲染首屏、登入、購物車和支付真正需要的第一方程式碼;分析、聊天、推薦、熱圖和行銷標籤大多可以在首屏後或使用者明確觸發後載入。腳本在下載完成後仍會佔用解析、編譯和主執行緒執行時間,所以「非同步下載」不等於「沒有效能成本」。
2. 依依賴選擇載入方式
經典腳本沒有屬性時會阻塞 HTML 解析。async 會並行下載,下載完成就執行,腳本之間沒有順序保證;適合彼此獨立的分析或廣告。defer 也會並行下載,但等文件解析完成後按出現順序執行,適合依賴 DOM 或其他腳本的應用程式啟動。模組腳本預設延後執行,但其依賴圖仍要單獨評估。
一個簡化決策表:
| 方式 | 執行時機 | 依賴保證 | 適合場景 | 主要風險 |
|---|---|---|---|---|
| 普通經典腳本 | 下載後立即執行並阻塞解析 | 依文件順序 | 少數必須同步的引導碼 | 拖慢解析和首屏 |
async | 下載完成即執行 | 無順序保證 | 獨立分析、廣告、簡單 widget | 可能打斷解析,依賴產生競態 |
defer | 解析完成後按順序執行 | 保留順序 | DOM 或應用程式啟動依賴 | 仍會延遲 DOMContentLoaded |
| 互動後載入 | 使用者觸發或閒置後 | 由載入器控制 | 聊天、地圖、影片、回放 | 第一次開啟有額外等待 |
| iframe facade | 先展示靜態外殼,再隔離嵌入 | 跨文件邊界 | 影片、支付外觀、複雜 widget | 互動通信和無障礙更複雜 |
不要給互相依賴的腳本都加 async。如果 plugin.js 需要 vendor.js,應使用有序的 defer、模組依賴或明確的載入器,而不是依賴下載速度碰巧正確。
3. 延後、裁剪或替換第三方功能
對非關鍵功能使用使用者互動、requestIdleCallback(有逾時兜底)或首屏完成後的佇列觸發。聊天按鈕可先顯示第一方靜態入口,點擊後才建立 widget;影片先顯示縮圖和播放按鈕,點擊後才嵌入 iframe。這樣減少首屏網路和主執行緒成本,也避免使用者從未使用的功能佔用資源。
刪除重複的標籤管理器、重複分析 SDK 和未使用的實驗腳本。必要時要求供應商提供精簡建置、按頁面拆分、壓縮和快取策略。自託管可以減少第三方 DNS 或可用性風險,但要建立版本更新、SRI、授權、快取失效和回滾流程;它不會自動消除腳本執行成本。
4. 隱私、安全和故障邊界
在同意狀態明確前,不建立非必要的追蹤腳本,也不要先載入再「停用傳送」。同意改變後,定義是否需要清理 cookie、停止佇列和撤回後續請求。腳本來源透過 CSP script-src 和相關連線指令收斂;固定版本的外部資源可配合 SRI 校驗內容完整性。動態腳本、供應商二次載入和 strict-dynamic 的組合要單獨稽核,不能只看第一層網域。
第三方程式碼與第一方頁面同源執行時,權限邊界很寬。需要展示而不需要讀取頁面資料的元件優先放入 iframe,並用 postMessage 傳遞最小欄位。購買、登入、導覽和錯誤提示保持第一方可用;第三方逾時透過逾時、熔斷和降級佔位結束,不得阻塞主流程。
5. 預算與監控
為每個供應商和頁面類型設定預算:傳輸位元組、請求數、主執行緒執行時間、長工作數量、錯誤率和對 LCP/INP 的貢獻。預算超出時進入評審或自動降級,而不是等全站指標惡化才處理。預算要按低階裝置、慢網路和同意狀態分層,因為平均值會掩蓋長尾。
實驗室用 DevTools Performance、Network、WebPageTest 和故障注入觀察解析、執行、長工作和單點故障。線上用 RUM 記錄腳本來源、資源時序、PerformanceObserver 的 long task、LCP、INP、CLS、轉換和錯誤。比較改動前後的裝置分層、瀏覽器、地區和頁面模板,避免把流量結構變化誤當成優化效果。
6. 灰度、回滾和供應商變更
先在一個頁面模板和小比例行動裝置流量灰度。每個腳本改動帶版本、來源、同意設定和回滾開關;供應商更新也走同一流程。若某個腳本逾時或報錯,預設跳過或降級,不等待無限重試。回滾只恢復上一份經過審核的清單,不能臨時從供應商 URL 拉一個未知版本。
驗證核心不變量:第三方失敗時使用者仍能瀏覽、加入購物車和完成購買;未經同意不會發出受限資料請求;腳本預算未超標;CSP 報告沒有新來源;關鍵互動的 INP 沒有回歸。對每個供應商保留刪除或替代的觸發條件。
7. 可執行的驗證場景
至少測試慢 DNS、第三方 5xx、下載到一半斷網、腳本拋出例外、主執行緒長工作、同意撤回、瀏覽器停用第三方 cookie、廣告攔截器和舊瀏覽器。測試不只看頁面是否顯示,還要斷言購買狀態、錯誤恢復、鍵盤操作、螢幕閱讀器公告和資料傳送邊界。
使用對照組只改變一個載入策略,例如同步改為延後,保持頁面內容和流量規則不變。驗證 p75/p95 LCP、INP、長工作、資源位元組、業務轉換和供應商錯誤;若主指標改善但客服第一次開啟變慢,報告取捨並調整載入觸發器,而不是只報一個漂亮分數。
高品質示範回答
「我不會先給 14 個腳本全部加 async。第一步是建立清單,記錄每個腳本的目的、依賴、請求網域、位元組、主執行緒時間、資料用途、負責人和故障影響,然後把它們分成關鍵、延後和刪除候選。支付和登入保留第一方關鍵路徑,分析可以獨立非同步,依賴 DOM 或順序的腳本用 defer,聊天、地圖和影片用互動後載入或 iframe facade。
使用者同意前不建立非必要追蹤腳本;CSP 只放行審核過的來源,固定資源再用 SRI。需要展示但不應讀取頁面的功能放進 iframe,購買和導覽永遠有第一方降級路徑。每個供應商有位元組、執行時間、長工作和錯誤預算。
我會先對行動裝置小流量灰度,實驗室用 Performance 面板、網路限速和第三方故障注入,線上用 RUM 按裝置、地區和同意狀態觀察 LCP、INP、CLS、long task、資源時序、轉換和錯誤。每個改動都可回滾,供應商更新走同樣的版本審核。如果第三方失敗,頁面仍能完成核心購買;如果未經同意仍發出請求,或護欄超過預算,就停止擴展。」
常見錯誤
- 所有腳本都加
async→ 依賴腳本可能亂序,執行仍會打斷解析 → 先畫依賴圖,獨立腳本用async,有序依賴用defer或模組。 - 只把腳本放到 body 底部 → 下載和執行仍會搶佔主執行緒,關鍵互動仍可能變慢 → 按功能延後、裁剪、分包並測量執行成本。
- 只看 Lighthouse → 實驗室沒有覆蓋低階裝置、慢網路和供應商抖動 → 用 RUM 分層比較真實分位數、長工作和業務指標。
- 同意後再停用追蹤 → 腳本已經執行並可能發出請求 → 在建立腳本和網路請求前就判斷同意狀態。
- 把自託管當成萬能安全方案 → 更新、完整性、授權和腳本執行成本仍需管理 → 配合版本審核、SRI、CSP、預算和回滾。
- 第三方故障時重試到成功 → 關鍵頁面被供應商拖住,單點故障擴大 → 設定逾時、降級佔位和第一方核心路徑。
追問及應對
追問 1:分析腳本必須儘早傳送首屏事件,能否放進關鍵路徑?
先確認事件是否真的需要在首屏繪製前傳送。若只需記錄頁面瀏覽,可在首屏後批量傳送並允許遺失;若合規或歸因要求更早,使用獨立 async、短逾時和小型第一方佇列,不能讓它阻塞渲染。比較事件延遲與 LCP/INP 的業務價值後再定預算。
追問 2:供應商只提供一個動態 URL,如何做 SRI?
無法為內容不斷變化的 URL 固定可靠雜湊。可以要求版本化資源、建立自託管和簽名發布流程,或把功能隔離到 iframe/伺服器端;同時用 CSP、供應商存取稽核和變更監控降低風險。不能偽造雜湊或把 unsafe-inline 當替代方案。
追問 3:第三方腳本使用 defer 後仍產生長工作,下一步做什麼?
defer 只改變執行時機,不會減少解析和執行工作。先按 Performance trace 找到具體腳本和工作,再要求供應商拆分、延後到互動、減少功能或改用 iframe/伺服器端事件。若必須執行,在閒置窗口分批執行並設定逾時,同時用 RUM 驗證長尾是否改善。
追問 4:行銷團隊要求一次加入五個標籤,如何回答?
要求每個標籤給出目的、負責人、預期決策、同意類別、效能預算和刪除條件。先檢查是否重複採集或能由現有事件滿足;必要時在沙盒頁面測量,再小流量灰度。沒有可驗證價值或超過預算的標籤不進入生產清單。