Articles

Závitování webu pomocí pracovníků modulu

JavaScript je jednovláknový, což znamená, že může provádět pouze jednu operaci najednou. To je intuitivní a funguje dobře pro mnoho případů na webu, ale může být problematické, když musíme udělat, zvedání těžkých úkolů, jako je zpracování dat, analýzy, výpočty nebo analýzy. Vzhledem k tomu, že na webu jsou dodávány stále složitější aplikace, zvyšuje se potřeba vícevláknového zpracování.

na webové platformě je hlavním primitivem pro threading a paralelismus API Web Workers. Pracovníci jsou lehká abstrakce nad vlákny operačního systému, které vystavují API pro předávání zpráv pro komunikaci mezi vlákny. To může být nesmírně užitečné při provádění nákladné výpočty, nebo působí na velké soubory dat, což umožňuje hlavní vlákno tak, aby hladce při provádění nákladných operací na jednom nebo více pozadí.

Zde je typický příklad pracovníka využití, kde pracovník skript poslouchá zprávy z hlavního vlákna, a reaguje zasláním zprávy na své vlastní:

stránka.js:

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

worker.js:

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

Web Worker API je k dispozici ve většině prohlížečů již více než deset let. I když to znamená, že pracovníci mají vynikající podporu prohlížeče a jsou dobře optimalizováni, znamená to také, že dlouho předcházejí modulům JavaScript. Protože tam byl žádný modul systému, kdy pracovníků byly navrženy tak, API pro načítání kódu na pracovníka a psaní skriptů zůstal podobný synchronní script načítání přístupy běžné v roce 2009.

historie: classic workers #

Konstruktor Worker má adresu URL klasického skriptu, která je relativní k adrese URL dokumentu. Okamžitě vrátí odkaz na novou instanci pracovníka, která odhalí rozhraní pro zasílání zpráv a metodu terminate(), která okamžitě zastaví a zničí pracovníka.

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

importScripts() funkce je k dispozici ve web workers pro načítání další kód, ale zastaví se výkonu pracovníka za účelem získat a vyhodnotit každý scénář. Také provádí skripty v globálním rozsahu jako klasický <script> tag, což znamená, že proměnné v jednom skriptu mohou být přepsány proměnnými v jiném.

pracovník.js:

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

greet.js:

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

z tohoto důvodu, web workers historicky uložené velký vliv na architekturu aplikace. Vývojáři museli vytvořit chytré nástroje a řešení, aby bylo možné používat webové pracovníky, aniž by se vzdali moderních vývojových postupů. Jako příklad, přispěvatelů, jako webpack vložte si malý modul loader implementace do vygenerovaný kód, který používá importScripts() kód pro načítání, ale zábaly moduly funkcí, aby se zabránilo variabilní srážek a simulovat závislost na dovozu a vývozu.

Zadejte modul pracovníků #

nový režim pro web workers s ergonomii a výkon výhody modulů JavaScript je lodní doprava v Chrome 80, nazývá modul pracovníků. Worker konstruktor nyní přijímá nové {type:"module"} možnost, která se mění script načítání a provedení, aby odpovídaly <script type="module">.

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

protože pracovníci modulů jsou standardní moduly JavaScript, mohou používat příkazy importu a exportu. Stejně jako u všech modulů JavaScriptu jsou závislosti prováděny pouze jednou v daném kontextu (hlavní vlákno, pracovník atd.) a všechny budoucí importy odkazují na již provedenou instanci modulu. Načítání a provádění modulů JavaScript je také Optimalizováno prohlížeči. Závislosti modulu lze načíst před spuštěním modulu, což umožňuje paralelní načítání celých stromů modulů. Načítání modulů také ukládá analyzovaný kód do mezipaměti, což znamená, že moduly, které se používají na hlavním vlákně a v pracovníkovi, musí být analyzovány pouze jednou.

přechod na Moduly JavaScript také umožňuje použití dynamického importu pro líné načítání kódu bez blokování provádění pracovníka. Dynamický import je mnohem explicitnější než použití importScripts() k načtení závislostí, protože export importovaného modulu je vrácen spíše než spoléhat se na globální proměnné.

pracovník.js:

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

greet.js:

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

zajistit skvělý výkon, staré importScripts() metoda není k dispozici v modulu pracovníci. Přepnutí pracovníků na používání modulů JavaScript znamená, že veškerý kód je načten v přísném režimu. Další pozoruhodnou změnou je, že hodnota this v nejvyšším rozsahu modulu JavaScript je undefined, zatímco u klasických pracovníků je hodnota globálním rozsahem pracovníka. Naštěstí vždy existoval self Globální, který poskytuje odkaz na globální rozsah. Je k dispozici ve všech typech pracovníků, včetně servisních pracovníků, stejně jako v DOM.

pracovníci modulu také odstraňují podporu komentářů ve stylu HTML. Věděli jste, že můžete použít HTML komentáře ve skriptech web worker?

Předpětí pracovníků s modulepreload #

Jeden podstatné zlepšení výkonu, který je dodáván s modulem pracovníků je schopnost předpětí pracovníků a jejich závislostí. S modulem pracovníků, skripty jsou načten a proveden jako standardní JavaScript moduly, což znamená, že může být předinstalovaný a dokonce i pre-analyzovány pomocí 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>

Předinstalované moduly mohou být také použity jak pro hlavní vlákno a modul pracovníků. To je užitečné pro moduly, které jsou importovány v obou kontextech, nebo v případech, kdy není možné předem vědět, zda bude modul použit v hlavním vlákně nebo v pracovníkovi.

dříve byly dostupné možnosti předběžného načítání skriptů web worker omezené a ne nutně spolehlivé. Klasické pracovníci měli své vlastní „pracovník“ typ zdroje pro zavedení, ale ne prohlížečích implementovány <link rel="preload" as="worker">. Jako výsledek, primární technikou dostupnou pro předběžné načítání webových pracovníků bylo použití <link rel="prefetch">, které se spoléhalo výhradně na mezipaměť HTTP. Při použití v kombinaci se správnými hlavičkami ukládání do mezipaměti to umožnilo vyhnout se instanci pracovníka, která musí čekat na stažení skriptu pracovníka. Nicméně, na rozdíl od modulepreload tato technika nepodporovala Předběžné načítání závislostí nebo předběžnou analýzu.

a co sdílené pracovníky? #

sdílené pracovníky byly aktualizovány s podporou modulů JavaScript od Chrome 83. Jako specializované pracovníky, vytvoření sdíleného pracovník s {type:"module"} možnost zatížení pracovníka scénář jako modul, spíše než klasický scénář:

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

Před podporou JavaScript moduly, SharedWorker() konstruktoru očekává pouze URL a volitelnou name argument. To bude i nadále fungovat pro klasické sdílené využití pracovníků; vytvoření modulu shared workers však vyžaduje použití nového argumentu options. Dostupné možnosti jsou stejné jako u vyhrazeného pracovníka, včetně možnosti name, která nahrazuje předchozí argument name.

a co servisní pracovník? #

service worker specifikace již byly aktualizovány na podporu přijetí JavaScript modulu jako vstupní bod, pomocí stejné {type:"module"} možnost jako modul pracovníků, nicméně tato změna musí být ještě implementovány v prohlížečích. Jakmile se tak stane, bude možné vytvořit instanci služby pracovník pomocí JavaScript modul pomocí následující kód:

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

Nyní, že specifikace byly aktualizovány, prohlížeče začínají realizovat nové chování. To vyžaduje čas, protože existují některé další komplikace spojené s přinášením modulů JavaScript servisnímu pracovníkovi. Servisní pracovník registrace musí porovnat importované skripty s jejich předchozí mezipaměti verze při určování, zda ke spuštění aktualizace, a to musí být realizovány pro JavaScript moduly, pokud se používají pro servisní pracovníky. Servisní pracovníci musí být také schopni obejít mezipaměť skriptů v určitých případech při kontrole aktualizací.