使用網路工作站在瀏覽器執行 JavaScript's 主執行緒

主執行緒架構可以大幅改善應用程式的可靠性和使用者體驗。

在過去 20 年間,網路從只有少數樣式和圖片的靜態文件,演變成複雜的動態應用程式。但有一件事並沒有改變:每個瀏覽器分頁只有一個執行緒 (有些例外),這會影響網站轉譯和執行 JavaScript 的作業。

因此,主執行緒已嚴重超載。隨著網頁應用程式日益複雜,主執行緒會成為效能瓶頸。更糟的是,針對特定使用者在主執行緒上執行程式碼所需的時間,幾乎完全無法預測,這是因為裝置功能對效能的重大影響。隨著使用者使用越來越多樣化的裝置組合,從超受限的功能手機到效能高的高刷新率旗艦機,使用者上網時才會越來越難以預測。

如要讓精密的網頁應用程式確實符合效能準則,例如Core Web Vitals (以人類觀念和心理學經驗資料為基礎) 為基礎,就必須在主執行緒 (OMT) 外執行程式碼。

為何選擇 Web Worker?

根據預設,JavaScript 是單一執行緒語言,會在主執行緒上執行工作。然而,網路工作處理程序可讓開發人員建立不同的執行緒處理主執行緒的工作,從主執行緒提供一種應急的替代方案。雖然網路工作處理程序的涵蓋範圍有限,無法直接存取 DOM,但如果仍有重大工作需要完成,導致主執行緒負擔過重,這些工作人員會非常有用。

網站體驗核心指標而言,在主執行緒外執行作業可能會有所助益。特別是,將主要執行緒的工作卸載至網路工作站,可以減少主執行緒的爭用情況,進而改善網頁的「與下一個顯示內容互動 (INP)」回應度指標。如果主執行緒的處理工作較少,就能更快回應使用者互動。

較不重要的主執行緒工作 (尤其是在啟動期間),也對最大內容繪製 (LCP) 可能因為減少長時間工作而受益。轉譯 LCP 元素需要主要執行緒時間 (無論是轉譯文字或圖片時,常常和常見的 LCP 元素),而且減少主執行緒工作量後,您可以確保網頁的 LCP 元素因為網路工作站處理所處理的昂貴工作而遭到封鎖。

網路工作站的執行緒

其他平台通常支援平行工作,可讓您為執行緒提供一個函式,這個函式會與程式的其餘部分平行執行。您可以在兩個執行緒中存取相同的變數,且這些共用資源的存取權可與互斥鎖和賽馬同步處理,以防競爭狀況。

在 JavaScript 中,我們可以取得網路工作站大致相似的功能,這些功能大約自 2007 年起,並於 2012 年開始支援所有主要瀏覽器。Web Worker 會與主執行緒平行執行,但與 OS 執行緒不同,網路工作站無法共用變數。

如要建立網路工作站,請將檔案傳送至工作站建構函式,開始在另一個執行緒中執行該檔案:

const worker = new Worker("./worker.js");

使用 postMessage API 傳送訊息,與網路工作人員通訊。在 postMessage 呼叫中將訊息值做為參數傳遞,然後將訊息事件監聽器新增至 worker:

main.js

const worker = new Worker('./worker.js');
worker.postMessage([40, 2]);

worker.js

addEventListener('message', event => {
  const [a, b] = event.data;

  // Do stuff with the message
  // ...
});

如要將訊息傳回主要執行緒,請在網路工作站中使用相同的 postMessage API,並在主執行緒上設定事件監聽器:

main.js

const worker = new Worker('./worker.js');

worker.postMessage([40, 2]);
worker.addEventListener('message', event => {
  console.log(event.data);
});

worker.js

addEventListener('message', event => {
  const [a, b] = event.data;

  // Do stuff with the message
  postMessage(a + b);
});

這種做法有點限制。過去,網路工作人員主要用於將一件繁重工作移出主執行緒。嘗試以單一網路工作站處理多項作業的速度很快,不僅需要將參數編碼,還要為訊息中的作業進行編碼,而且您必須把回應與要求進行比對。這很複雜可能是因為網路工作人員尚未廣泛採用的原因。

但如果能消除主執行緒與網路工作站之間溝通的一些困難,這個模型就可能非常適合許多用途。幸好,有一套程式庫能夠幫上忙!

Comlink 這個程式庫的目標是讓您使用網路工作站,而無需考慮 postMessage 的細節。Comlink 可讓您在網路工作站和主執行緒之間共用變數,就像其他支援執行緒作業的程式設計語言一樣。

設定 Comlink 的方式如下:將 Comlink 匯入網路工作站,並定義一組要公開給主執行緒的函式。接著,在主執行緒上匯入 Comlink、包裝 worker,然後取得公開的函式:

worker.js

import {expose} from 'comlink';

const api = {
  someMethod() {
    // ...
  }
}

expose(api);

main.js

import {wrap} from 'comlink';

const worker = new Worker('./worker.js');
const api = wrap(worker);

主執行緒上的 api 變數行為與網路工作站中的變數相同,唯一差別在於每個函式都會傳回某個值的承諾,而非值本身。

您應該將什麼程式碼移至網路工作站?

Web Worker 無法存取 DOM 和許多 API (例如 WebUSBWebRTCWeb Audio),因此您無法將需要這類存取權的應用程式放在 worker 中。儘管如此,將一小段程式碼移至 worker 時,也會在主執行緒上購買更多「必須」的項目空間 (例如更新使用者介面)。

對網頁程式開發人員來說,大部分的網頁應用程式都會依靠 Vue 或 React 等 UI 架構來自動化調度管理應用程式中的所有內容。所有項目都是架構的組成部分,因此本質上與 DOM 相關。這樣似乎就難以遷移至 OMT 架構。

不過,如果我們改用模型,將 UI 疑慮與其他問題 (例如狀態管理) 區隔開來,即使採用架構式應用程式,網路工作處理工作也能派上用場。這正是 PROXX 採取的做法。

PROXX:OMT 個案研究

Google Chrome 團隊開發的 PROXX 是符合 Progressive Web App 需求條件的 Minesweeper 本機副本,包括離線工作和提供引人入勝的使用者體驗。不幸的是,早期版遊戲在功能型手機等受限裝置上表現不佳,導致團隊發現主執行緒是瓶頸。

該團隊決定利用網路工作站,將遊戲的視覺狀態與邏輯分開:

  • 主執行緒會處理動畫和轉場的轉譯作業。
  • 網路工作站會處理遊戲邏輯,這只須進行運算。
,瞭解如何調查及移除這項存取權。

OMT 對 PROXX 的功能手機效能帶來有趣的影響,在非 OMT 版本中,使用者介面會在使用者與其互動後凍結 6 秒。系統不會提供意見回饋,而使用者必須等待 6 秒過後才能執行其他操作。

非 OMT PROXX 版本的 UI 回應時間。

但在 OMT 版本中,遊戲需要 12 秒才能完成 UI 更新。這似乎是成效下降,但實際上會讓使用者收到更多意見回饋。之所以發生速度變慢,是因為應用程式所出貨的影格數超出非 OMT 版本,而該版本完全沒有出貨任何影格。因此,使用者知道系統正在運作,而且可以隨著 UI 更新繼續玩遊戲,感覺更棒的遊戲體驗。

OMT PROXX 版本的 UI 回應時間。

這有明顯的取捨:我們為限制裝置的使用者提供親身體驗的優質體驗,而不會對高階裝置使用者造成負面影響。

OMT 架構的影響

如 PROXX 範例所示,OMT 可讓應用程式在更多多種裝置上穩定執行,但不會加快應用程式運作速度:

  • 您只是從主執行緒移動工作,不會減少工作量。
  • 網路工作站之間的額外通訊負擔 但主執行緒有時可能會使作業速度稍微變慢。

考量的優缺點

由於主執行緒可在 JavaScript 執行期間處理捲動等使用者互動,因此捨棄的影格數量較少,即使總等待時間可能略長較長。讓使用者等待一點時間比較適合捨棄影格,因為捨棄影格的誤差範圍較小:捨棄影格後會在毫秒內發生,但使用者有「數百毫秒」後才會察覺到等待時間。

由於各裝置的效能難以預測,因此 OMT 架構的目標在於「降低風險」。也就是說,在面對高度變化的執行階段環境時,應用程式會更可靠,而不是與平行處理的效能優勢有關。隨著韌性和使用者體驗的提升,任何在速度上都有小小的權衡與利弊,不見得能帶來同等的價值。

工具相關注意事項

Web Worker 尚未成為主流,因此大部分的模組工具 (例如 webpackRollup) 都不支援這些工具。(但 Parcel 則是)。幸好,有外掛程式能建立網路工作站,非常適合使用 webpack 和 Rollup 進行工作

總結

為了盡可能確保應用程式穩定可靠且易於使用,特別是在日益國際化的市場中,我們必須支援受限的裝置 — 這些都是全球大多數使用者上網的方式。OMT 可讓開發人員在不影響高階裝置使用者的情況下,提升這類裝置的效能。

此外,OMT 也有次要優點:

網路工作者也不必為此而感到害怕。Comlink 這類工具讓員工不需耗費人力,讓他們能輕鬆使用各式各樣的網頁應用程式。

主頁橫幅由 James Peacock 提供,由 Unsplash 提供。