使用 JavaScript 轉譯 HTML 與轉譯伺服器傳送的 HTML 不同,可能會影響效能。請參閱本指南,瞭解兩者差異,以及如何維持網站的算繪效能,特別是互動方面。
對於使用瀏覽器內建導覽邏輯的網站 (有時稱為「傳統網頁載入」或「硬式導覽」),瀏覽器預設會妥善剖析及算繪 HTML。這類網站有時稱為多頁面應用程式 (MPA)。
不過,開發人員可以繞過瀏覽器預設值,以符合應用程式需求。使用單頁應用程式 (SPA) 模式的網站就是如此,這類網站會使用 JavaScript 在用戶端動態建立大量 HTML/DOM。這種設計模式稱為用戶端算繪,如果涉及的工作過多,可能會影響網站的下次繪製互動 (INP)。
本指南將協助您評估使用伺服器傳送至瀏覽器的 HTML,與使用 JavaScript 在用戶端建立 HTML 之間的差異,以及後者如何在重要時刻導致互動延遲時間過長。
瀏覽器如何轉譯伺服器提供的 HTML
傳統網頁載入所用的導覽模式,是在每次導覽時從伺服器接收 HTML。如果您在瀏覽器的網址列中輸入網址,或點選 MPA 中的連結,系統會依序執行下列事件:
- 瀏覽器會傳送所提供網址的導覽要求。
- 伺服器會以區塊形式傳回 HTML。
最後一個步驟至關重要。這也是伺服器/瀏覽器交換中最基本的效能最佳化方法之一,稱為「串流」。如果伺服器能盡快開始傳送 HTML,且瀏覽器不必等待完整的回應送達,瀏覽器就能在 HTML 送達時分批處理。

與瀏覽器中發生的多數事件一樣,剖析 HTML 會在工作內發生。當 HTML 從伺服器串流至瀏覽器時,瀏覽器會分批接收串流資料,並逐步剖析 HTML,藉此進行最佳化。因此,瀏覽器會在處理每個區塊後,定期將控制權交給主執行緒,避免長時間工作。也就是說,在剖析 HTML 時,可以執行其他工作,包括向使用者顯示網頁所需的增量轉譯工作,以及處理網頁重要啟動期間可能發生的使用者互動。這種做法可提高網頁的 Interaction to Next Paint (INP) 分數。
想知道我們有哪些重要發現嗎?從伺服器串流 HTML 時,您可免費取得 HTML 的遞增剖析和算繪,並自動產生主執行緒。但用戶端轉譯無法提供這項功能。
瀏覽器如何轉譯 JavaScript 提供的 HTML
雖然每個網頁的導覽要求都需要伺服器提供一定量的 HTML,但部分網站會使用 SPA 模式。這種做法通常是伺服器提供最少的初始 HTML 酬載,但隨後用戶端會從伺服器擷取的資料組裝 HTML,並填入網頁的主要內容區域。後續的導覽 (在此情況下有時稱為「軟性導覽」) 完全由 JavaScript 處理,以新的 HTML 填入網頁。
在非 SPA 中,如果透過 JavaScript 將 HTML 動態新增至 DOM,也可能發生用戶端轉譯,但這類情況較為少見。
透過 JavaScript 建立 HTML 或新增至 DOM 的常見方式如下:
innerHTML
屬性可讓您透過字串在現有元素上設定內容,瀏覽器會將該字串剖析為 DOM。document.createElement
方法可讓您建立要新增至 DOM 的新元素,而不必使用任何瀏覽器 HTML 剖析。document.write
方法可讓您將 HTML 寫入文件 (瀏覽器會剖析 HTML,就像方法 1 一樣)。但由於多種原因,我們強烈建議不要使用document.write
。

透過用戶端 JavaScript 建立 HTML/DOM 可能會造成重大影響:
- 與伺服器為回應導覽要求而串流的 HTML 不同,用戶端上的 JavaScript 工作不會自動分塊,因此可能會產生長時間的工作,導致主執行緒遭到封鎖。也就是說,如果在用戶端一次建立過多 HTML/DOM,網頁的 INP 可能會受到負面影響。
- 如果在啟動期間於用戶端建立 HTML,瀏覽器預先載入掃描器「不會」探索其中參照的資源。這肯定會對網頁的最大內容繪製 (LCP) 造成負面影響。雖然這不是執行階段效能問題 (而是擷取重要資源時的網路延遲問題),但您不會希望網站的 LCP 受到影響,因此請務必進行這項基本的瀏覽器效能最佳化。
如何因應用戶端算繪對效能的影響
如果您的網站高度依賴用戶端算繪,且您發現實際資料中的 INP 值不佳,您可能會想知道用戶端算繪是否與問題有關。舉例來說,如果您的網站是 SPA,欄位資料可能會顯示導致大量算繪作業的互動。
無論原因為何,以下列出一些可能原因,供你參考,協助解決問題。
盡可能提供伺服器中的 HTML
如先前所述,瀏覽器預設會以非常有效率的方式處理伺服器傳來的 HTML。這項功能會將 HTML 的剖析和算繪作業拆開,避免長時間工作,並盡量縮短主執行緒的總時間。這會導致總封鎖時間 (TBT) 縮短,而 TBT 與 INP 有很強的關聯性。
您可能使用前端架構來建構網站。如果是,請務必在伺服器上算繪元件 HTML。這樣可減少網站所需的初始用戶端算繪量,進而提升瀏覽體驗。
- 如果是 React,您會想使用 Server DOM API 在伺服器上轉譯 HTML。但請注意,傳統的伺服器端算繪方法採用同步處理方式,可能會導致首位元組時間 (TTFB) 較長,以及後續指標 (例如首次顯示內容所需時間 (FCP) 和 LCP) 較差。請盡可能使用 Node.js 或其他 JavaScript 執行階段的串流 API,讓伺服器盡快開始將 HTML 串流至瀏覽器。Next.js 是以 React 為基礎的架構,預設提供許多最佳做法。除了在伺服器上自動算繪 HTML,這項功能還能為不會根據使用者環境 (例如驗證) 變更的網頁,靜態產生 HTML。
- Vue 也會預設執行用戶端轉譯。不過,與 React 類似,Vue 也可以在伺服器上轉譯元件 HTML。請盡可能善用這些伺服器端 API,或考慮為 Vue 專案採用更高層級的抽象化,以便更輕鬆地實作最佳做法。
- Svelte 預設會在伺服器上轉譯 HTML,但如果元件程式碼需要存取瀏覽器專屬的命名空間 (例如
window
),您可能無法在伺服器上轉譯該元件的 HTML。盡可能探索替代方法,以免造成不必要的用戶端算繪。SvelteKit 與 Svelte 的關係,就像 Next.js 與 React 的關係一樣,盡可能將許多最佳做法嵌入 Svelte 專案,因此您可以避免在單獨使用 Svelte 的專案中遇到潛在陷阱。
限制在用戶端建立的 DOM 節點數量
DOM 越大,顯示所需的處理作業就越多。無論您的網站是完整的 SPA,還是因為 MPA 的互動而將新節點插入現有 DOM,都請盡可能縮小這些 DOM。這樣有助於減少用戶端算繪期間顯示該 HTML 所需的工作,希望有助於降低網站的 INP。
考慮使用串流服務工作人員架構
這項進階技術可能無法輕鬆套用至所有用途,但可將 MPA 變成網站,讓使用者在網頁間瀏覽時,感覺網頁是立即載入。您可以使用 Service Worker,在 CacheStorage
中預先快取網站的靜態部分,同時使用 ReadableStream
API 從伺服器擷取網頁其餘的 HTML。
成功使用這項技術後,您不會在用戶端建立 HTML,但從快取即時載入部分內容,會讓使用者覺得網站載入速度很快。採用這種做法的網站幾乎就像 SPA,但不會有用戶端算繪的缺點。這項功能也能減少從伺服器要求 HTML 的數量。
簡而言之,串流服務工作站架構並不會取代瀏覽器的內建導覽邏輯,而是新增至其中。如要進一步瞭解如何使用 Workbox 達成此目標,請參閱「Faster multipage applications with streams」。
結論
網站接收及算繪 HTML 的方式會影響效能。如果依賴伺服器傳送網站運作所需的所有 (或大部分) HTML,您就能免費獲得許多好處:增量剖析和算繪,以及自動讓給主執行緒,避免長時間工作。
用戶端 HTML 算繪會導致許多潛在效能問題,但通常可以避免。不過,由於每個網站的需求不同,因此無法完全避免這種情況。為減少過度用戶端算繪可能導致的長時間工作,請盡可能從伺服器傳送網站的 HTML,並將必須在用戶端算繪的 HTML 的 DOM 大小縮到最小,同時考慮採用替代架構,加快將 HTML 傳送至用戶端的速度,並充分利用瀏覽器提供的 HTML 增量剖析和算繪功能 (適用於從伺服器載入的 HTML)。
如果能盡量減少網站的用戶端算繪作業,不僅能改善網站的 INP,還能提升 LCP、TBT 等指標,甚至在某些情況下改善 TTFB。
主頁橫幅圖片來自 Unsplash,由 Maik Jonietz 拍攝。