Articles

A web Threading with module workers

A JavaScript egyszálú, ami azt jelenti, hogy egyszerre csak egy műveletet hajthat végre. Ez intuitív és jól működik sok esetben az interneten, de problémássá válhat, ha meg kell csinálni nehéz emelési feladatok, mint az adatfeldolgozás, elemzés, számítás, vagy elemzés. Mivel egyre összetettebb alkalmazásokat szállítanak az interneten, egyre nagyobb szükség van a többszálú feldolgozásra.

a webplatformon a menetelés és a párhuzamosság fő primitívje a Web Workers API. A munkavállalók egy könnyű absztrakció az operációs rendszer szálain, amelyek egy üzenetátadó API-t mutatnak be a szálak közötti kommunikációhoz. Ez rendkívül hasznos lehet költséges számítások végrehajtásakor vagy nagy adatkészleteken történő működéskor, lehetővé téve a fő szál zökkenőmentes működését, miközben a drága műveleteket egy vagy több háttérszálon hajtja végre.

itt van egy tipikus példa a munkáshasználatra, ahol egy munkás szkript a fő szálból érkező üzeneteket hallgatja, és a saját üzeneteinek visszaküldésével válaszol:

oldal.js:

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

munkás.js:

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

a Web Worker API már több mint tíz éve elérhető a legtöbb böngészőben. Bár ez azt jelenti, hogy a munkavállalók kiváló böngészőtámogatással rendelkeznek, és jól optimalizáltak, ez azt is jelenti, hogy régóta megelőzik a JavaScript modulokat. Mivel a dolgozók tervezésekor nem volt modulrendszer, a kód betöltésére és szkriptek készítésére szolgáló API hasonló maradt a 2009-ben megszokott szinkron szkriptbetöltési megközelítésekhez.

előzmények: classic workers #

a Worker constructor egy klasszikus szkript URL-t vesz fel, amely a dokumentum URL-címéhez viszonyítva van. Azonnal visszaad egy hivatkozást az új munkavállalói példányra, amely egy üzenetküldő felületet, valamint egy terminate() módszert tesz közzé, amely azonnal leállítja és elpusztítja a munkavállalót.

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

An importScripts() funkció elérhető a webmunkások számára további kód betöltéséhez, de szünetelteti a munkavállaló végrehajtását az egyes szkriptek letöltéséhez és értékeléséhez. Azt is végrehajtja szkriptek a globális hatálya, mint egy klasszikus <script> tag, ami azt jelenti, a változók egy script lehet felülírni a változók egy másik.

munkás.js:

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

js:

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

ezért a webmunkások történelmileg túlméretezett hatást gyakoroltak egy alkalmazás architektúrájára. A fejlesztőknek okos szerszámokat és megoldásokat kellett létrehozniuk, hogy lehetővé tegyék a webmunkások használatát anélkül, hogy feladnák a modern fejlesztési gyakorlatokat. Például, bundlers, mint webpack beágyazása egy kis module loader végrehajtása a generált kódot hogy használja a importScripts() kód betöltése, de pakolások modulok, funkciók, hogy elkerüljék a változó ütközések, majd szimulálni függőségét az import-export.

Enter modul dolgozók #

egy új mód a web dolgozók az ergonómia és a teljesítmény előnyeit JavaScript modulok hajózás Chrome 80, úgynevezett modul dolgozók. AWorker Kivitelező most elfogadja az új {type:"module"} opciót, amely megváltoztatja a szkript betöltését és végrehajtását a <script type="module"> – hoz.

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

mivel a modulmunkások szabványos JavaScript modulok, importálási és exportálási nyilatkozatokat használhatnak. Mint minden JavaScript modul esetében, a függőségek csak egyszer kerülnek végrehajtásra egy adott kontextusban (fő szál, munkás stb.), és minden jövőbeli import a már végrehajtott modulpéldányra utal. A JavaScript modulok betöltését és végrehajtását a böngészők is optimalizálják. A modul függőségei betölthetők a modul végrehajtása előtt, ami lehetővé teszi a teljes modul fák párhuzamos betöltését. Modul betöltése is gyorsítótárak elemzett kódot, ami azt jelenti, modulokat használnak a fő menet, valamint a munkavállaló csak akkor kell elemezni egyszer.

a JavaScript modulokra való áttérés lehetővé teszi a dinamikus importálást a lusta betöltő kódhoz a munkavállaló végrehajtásának blokkolása nélkül. A dinamikus import sokkal explicitebb, mint aimportScripts() használata a függőségek betöltéséhez, mivel az importált modul exportja visszatér, nem pedig a globális változókra támaszkodik.

munkás.js:

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

js:

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

a nagy teljesítmény biztosítása érdekében a régi importScripts() módszer nem érhető el a modulmunkásokon belül. A munkavállalók JavaScript modulok használatára való váltása azt jelenti, hogy az összes kód szigorú módban van betöltve. Egy másik figyelemre méltó változás, hogy a this értéke a JavaScript modul felső szintű hatókörében undefined, míg a klasszikus munkavállalóknál az érték a munkavállaló globális hatóköre. Szerencsére mindig volt egyself globális, amely utal a globális hatókörre. Ez elérhető minden típusú munkavállalók, beleértve a Szolgáltató munkavállalók, valamint a DOM.

a Modulmunkások szintén eltávolítják a HTML-stílusú megjegyzések támogatását. Tudta, hogy HTML megjegyzéseket használhat a web munkás szkriptekben?

Modulepreload #

a modulmunkásokkal járó jelentős teljesítményjavítás a munkavállalók előterhelésének képessége és függősége. A modulmunkásokkal a szkriptek szabványos JavaScript modulokként kerülnek betöltésre és végrehajtásra, ami azt jelenti, hogy előtelepíthetők, sőt előelemezhetők a 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>

előtelepített modulok mind a fő szál, mind a modulmunkások számára használhatók. Ez olyan moduloknál hasznos, amelyeket mindkét kontextusban importálnak, vagy olyan esetekben, amikor nem lehet előre tudni, hogy egy modult használnak-e a fő szálon vagy a munkavállalóban.

korábban a webes dolgozói szkriptek előbetöltésére rendelkezésre álló lehetőségek korlátozottak voltak, és nem feltétlenül megbízhatóak. A klasszikus munkásoknak saját” munkás ” erőforrás típusa volt az előtelepítéshez, de egyetlen böngésző sem hajtotta végre <link rel="preload" as="worker">. Ennek eredményeként a webes dolgozók előtelepítéséhez rendelkezésre álló elsődleges technika a <link rel="prefetch"> használata volt, amely teljes mértékben a HTTP gyorsítótárra támaszkodott. Ha együtt használják a megfelelő gyorsítótár fejlécek, ez lehetővé tette, hogy elkerüljék a munkavállaló instantiation kelljen várni, hogy töltse le a munkavállaló script. Azonban, ellentétben a modulepreload ez a technika nem támogatta az előtelepítési függőségeket vagy az előelemzést.

mi a helyzet a megosztott munkavállalókkal? #

a megosztott dolgozókat a Chrome 83-tól kezdve frissítették a JavaScript modulok támogatásával. A dedikált munkásokhoz hasonlóan a {type:"module"} opcióval rendelkező megosztott munkavállaló a klasszikus szkript helyett modulként tölti be a munkás szkriptet:

a JavaScript modulok támogatása előtt a SharedWorker() Kivitelező csak URL-t és opcionális name argumentum. Ez továbbra is működni fog a klasszikus megosztott munkavállalói használat; azonban létre modul megosztott munkavállalók használatát igényli az új options argumentum. A rendelkezésre álló lehetőségek megegyeznek a dedikált munkavállaló opcióival, beleértve a nameopciót, amely felváltja az előző name argumentumot.

mi a helyzet a szolgálati munkással? #

A szolgáltatási munkás specifikáció már frissített támogatás elfogadása JavaScript modul, mint a belépési pont, ugyanazt a {type:"module"} lehetőséget, mivel a modul a munkavállalók, azonban ez a változás még nem alkalmazták a böngészők. Ha ez megtörténik, akkor lehet létrehozni egy szolgáltatás munkás segítségével a JavaScript modul segítségével a következő kódot:

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

Most, hogy a specifikáció frissült, böngésző elején, hogy hajtsák végre az új viselkedés. Ez időt vesz igénybe, mert van néhány extra komplikáció, amely a JavaScript modulokat a szervizmunkáshoz hozza. A szervizmunkások regisztrációjának össze kell hasonlítania az importált szkripteket a korábbi gyorsítótárazott verziókkal annak meghatározásakor, hogy indítson-e frissítést, ezt pedig a JavaScript modulokhoz kell végrehajtani, ha a szervizmunkások használják. A szervizmunkásoknak bizonyos esetekben meg kell tudniuk kerülni a szkriptek gyorsítótárát a frissítések ellenőrzésekor.