使用模組工作站串連網路

使用網頁工作站中的 JavaScript 模組,現在可以更輕鬆地將繁重的工作移至背景執行緒。

JavaScript 採用單一執行緒,因此一次只能執行一項作業。這是 操作直覺且適用於許多網路案例,但如果需要 處理資料處理、剖析、運算或分析等繁重工作。越來越多觀眾使用 透過網路傳遞複雜的應用程式,因此多執行緒的需求也越來越高 和資料處理之間

在網路平台,執行緒和平行處理的主要基本功能是網路平台 Workers API。 工作站是位於作業系統上的輕量抽象化機制 執行緒,以便公開訊息傳遞 API 進行執行緒之間的通訊這項功能在執行昂貴的運算或成本時 在大型資料集中運作時,主執行緒在執行 在一或多個背景執行緒上耗費大量資源的作業

以下是工作站的典型使用情況範例,工作站指令碼會監聽主機中的訊息 呼叫自己的執行緒,並傳回自己的訊息來回應:

page.js:

const worker = new Worker('worker.js');
worker.addEventListener('message', e => {
  console.log(e.data);
});
worker.postMessage('hello');

worker.js:

addEventListener('message', e => {
  if (e.data === 'hello') {
    postMessage('world');
  }
});

十年來,Web Worker API 已在大多數瀏覽器中推出。雖然這樣 這表示工作人員擁有優異的瀏覽器支援,並且經過妥善最佳化,這也意味著 舊版 JavaScript 模組。由於在設計 worker 時並沒有模組系統,因此 API 將程式碼載入工作站以及撰寫指令碼仍與同步指令碼類似 。

記錄:傳統版 worker

Worker 建構函式會擷取傳統版 指令碼網址,也就是 相對於文件網址的值並立即傳回新工作站執行個體的參照。 顯示訊息介面和 terminate() 方法,該方法可立即停止 就會刪除工作站。

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

importScripts() 函式可用於網路工作站中,以載入其他程式碼 會暫停 worker ,以便擷取和評估每個指令碼。這個 API 也會執行 建立全域範圍 (例如傳統 <script> 標記),代表單一指令碼中的變數可 卻遭到其他變數覆寫

worker.js:

importScripts('greet.js');
// ^ could block for seconds
addEventListener('message', e => {
  postMessage(sayHello());
});

greet.js:

// global to the whole worker
function sayHello() {
  return 'world';
}

因此,網路工作人員向來就模型的架構而言存在巨大影響 應用程式。開發人員必須打造巧妙的工具和解決方法 不使用網路工作站,卻不採用現代化的開發做法。舉例來說,套裝組合者喜歡 webpack 在使用 importScripts() 產生的程式碼中嵌入小型模組載入器實作項目 將模組納入函式中,以免發生變數衝突,並模擬程式碼載入情形 依附元件匯入及匯出功能

進入模組 worker

專為網路工作人員設計的全新模式,具備人體工學和 JavaScript 的效能優勢 模組在 Chrome 第 80 版中出貨,稱為模組 worker。 Worker 建構函式現已接受新的 {type:"module"} 選項,可變更指令碼載入和 以便比對 <script type="module">

const worker = new Worker('worker.js', {
  type: 'module'
});

由於模組工作站為標準的 JavaScript 模組,因此可以使用匯入和匯出陳述式。阿斯 與所有 JavaScript 模組的共通點,依附元件只在特定結構定義中執行一次 (主執行緒、 工作站等),而且未來的所有匯入作業都會參照已經執行的模組執行個體。載入中 且 JavaScript 模組的執行也會由瀏覽器最佳化。模組的依附元件可 是在模組執行之前載入,以便載入整個模組樹狀結構 平行。模組載入也會快取剖析的程式碼,也就是主要用於 執行緒和工作站中只需剖析一次。

改用 JavaScript 模組後,您還可以使用動態程式碼 匯入延遲載入程式碼時,不會禁止執行 工作站的工作。動態匯入比使用 importScripts() 載入依附元件更明確。 因為系統會傳回匯入模組的匯出資料,而非依賴全域變數。

worker.js:

import { sayHello } from './greet.js';
addEventListener('message', e => {
  postMessage(sayHello());
});

greet.js:

import greetings from './data.js';
export function sayHello() {
  return greetings.hello;
}

為了確保效能良好,模組中無法使用舊的 importScripts() 方法 工作站將工作站改為使用 JavaScript 模組,表示所有程式碼都會以嚴格標準 模式。其他 重大變更是 JavaScript 模組頂層範圍內的 this 值為 undefined,在傳統版工作站中,值則是工作站的全域範圍。幸運的是 一直都是 self 全域範圍,提供全域範圍的參照。服務語言 所有類型的工作站,包括 Service Worker 以及 DOM。

使用 modulepreload 預先載入工作站

模組 worker 可提供顯著的效能改善措施,那就是預先載入功能 及其依附元件透過模組工作站,指令碼會以標準形式載入和執行 JavaScript 模組,表示這些模組可以使用 modulepreload 預先載入,甚至預先剖析:

<!-- preloads worker.js and its dependencies: -->
<link rel="modulepreload" href="worker.js">

<script>
  addEventListener('load', () => {
    // our worker code is likely already parsed and ready to execute!
    const worker = new Worker('worker.js', { type: 'module' });
  });
</script>

預先載入的模組也可以由主執行緒和模組工作站使用。這對於使用者 同時在這兩種情況下匯入的模組,或無法事先得知情況 是否會在主執行緒或 worker 中使用模組。

過去,預先載入網路工作站指令碼的選項有限, 而非可靠性傳統工作者有自己的「工作者」預先載入的資源類型,但沒有 瀏覽器實作了 <link rel="preload" as="worker">。因此 可以使用 <link rel="prefetch">,完全依賴 HTTP 快取如果與正確的快取標頭搭配使用,就能 ,這樣可以避免工作站執行個體化,就不用等待下載工作站指令碼。但是,這與 modulepreload 這項技巧不支援預先載入依附元件或預先剖析。

共用員工呢?

共用工作站 已更新,且自 Chrome 83 版起支援 JavaScript 模組。就像專屬員工一樣 建構使用 {type:"module"} 選項共用的工作站時,現在會將工作站指令碼載入為 而非傳統指令碼:

const worker = new SharedWorker('/worker.js', {
  type: 'module'
});

在支援 JavaScript 模組之前,SharedWorker() 建構函式應該只會出現 網址和選用的 name 引數。這將繼續適用於傳統版共用工作站;不過 建立模組共用工作站時,需要使用新的 options 引數。可用 選項 與專屬 worker 相同,包括取代的 name 選項 前一個 name 引數。

Service Worker 呢?

Service Worker 規格已 更新,支援接受 JavaScript 模組做為進入點,並使用與模組 worker 相同的 {type:"module"} 選項。 但這項變更並未導入瀏覽器。之後 使用下列程式碼,透過 JavaScript 模組將 Service Worker 執行個體化:

navigator.serviceWorker.register('/sw.js', {
  type: 'module'
});

由於規格已更新,瀏覽器現在可以開始實作新行為。 這需要花時間,因為導入 JavaScript 會有一些額外複雜問題。 Service WorkerService Worker 註冊需要比較匯入的指令碼 與舊版快取版本整合 判斷是否要觸發更新,而且必須針對 JavaScript 模組實作。 如為服務工作站此外,服務工作處理程序也必須能將 將指令碼寫入 正在檢查更新。

其他資源和延伸閱讀