← Cloudflare Workers / workers / reference
Migrace ze Service Workers na ES Modules
Tento průvodce vám ukáže, jak migrovat vaše Workers z Service Worker ↗ formát do ES moduly ↗ formát.
Výhody migrace
Existuje několik důvodů, proč migrovat vaše Workers na formát ES modulů:
- Váš Worker poběží rychleji. U service workers jsou bindings vystaveny jako globální proměnné. To znamená, že runtime Workers musí pro každý požadavek vytvořit nový spouštěcí kontext JavaScriptu, což přidává režii a čas navíc. Workery napsané pomocí ES modulů mohou stejný spouštěcí kontext znovu využít napříč více požadavky.
- Implementace Durable Objects vyžaduje Workers, které používají ES moduly.
- Bindings pro D1, Workers AI, Vectorize, Workflows, a Obrázky lze použít pouze z Workerů, které využívají ES modules.
- Můžete postupně nasazovat změny do svého Workeru při použití formátu ES modulů.
- Workery využívající ES moduly můžete snadno publikovat do
npm, což vám umožní importovat a znovu používat Workers ve vaší kódové základně.
Migrace Workeru
Následující příklad ukazuje Worker, který přesměruje všechny příchozí požadavky na adresu URL s 301 stavový kód.
Se syntaxí Service Worker vypadá ukázkový Worker takto:
async function handler(request) {
const base = 'https://example.com';
const statusCode = 301;
const destination = new URL(request.url, base);
return Response.redirect(destination.toString(), statusCode);
}
// Initialize Worker
addEventListener('fetch', event => {
event.respondWith(handler(event.request));
});Workers ve formátu ES modules nahrazují addEventListener syntax s definicí objektu, která musí být výchozím exportem souboru (přes export default). Předchozí ukázkový kód se změní na:
export default {
fetch(request) {
const base = "https://example.com";
const statusCode = 301;
const source = new URL(request.url);
const destination = new URL(source.pathname, base);
return Response.redirect(destination.toString(), statusCode);
},
};Bindings
Bindings umožňují vašim Workers interagovat se zdroji na Cloudflare developer platform.
Workers ve formátu ES modules se nespoléhají na žádné globální bindings. Syntaxe Service Worker naopak přistupuje k bindings v globálním rozsahu.
Chcete-li porozumět bindings, přečtěte si následující TODO příklad KV namespace bindingu. Pro vytvoření TODO KV namespace binding provedete následující:
- Vytvořte KV namespace s názvem
My Tasksa získáte ID, které použijete ve svém bindingu. - Vytvořte Worker.
- Najděte svého Workeru Konfigurační soubor Wrangler a přidejte binding KV namespace:
{
"kv_namespaces": [
{
"binding": "TODO",
"id": "<ID>"
}
]
}[[kv_namespaces]]
binding = "TODO"
id = "<ID>"V následujících částech použijete svůj binding ve formátu Service Worker i ES modules.
Bindings ve formátu Service Worker
V syntaxi Service Worker váš TODO KV namespace binding je definován v globálním rozsahu vašeho Workeru. Váš TODO KV namespace binding lze použít kdekoli v kódu vaší aplikace Worker.
addEventListener("fetch", async (event) => {
return await getTodos()
});
async function getTodos() {
// Get the value for the "to-do:123" key
// NOTE: Relies on the TODO KV binding that maps to the "My Tasks" namespace.
let value = await TODO.get("to-do:123");
// Return the value, as is, for the Response
event.respondWith(new Response(value));
}Bindings ve formátu ES modulů
Ve formátu ES modulů jsou bindings dostupné pouze uvnitř env parametru poskytnutého ve vstupním bodu vašeho Workeru.
Chcete-li získat přístup k TODO KV namespace binding ve vašem kódu Workeru, env parametr musí být předán z fetch handler ve vašem Workeru na getTodos .
import { getTodos } from './todos'
export default {
async fetch(request, env, ctx) {
// Passing the env parameter so other functions
// can reference the bindings available in the Workers application
return await getTodos(env)
},
};Následující kód představuje getTodos funkce, která volá get funkce na TODO KV binding.
async function getTodos(env) {
// NOTE: Relies on the TODO KV binding which has been provided inside of
// the env parameter of the `getTodos` function
let value = await env.TODO.get("to-do:123");
return new Response(value);
}
export { getTodos }Proměnné prostředí
Proměnné prostředí se v kódu psaném ve formátu ES modules přistupuje jinak než ve formátu Service Worker.
Prohlédněte si následující ukázkovou konfiguraci proměnné prostředí v Konfigurační soubor Wrangler:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "my-worker-dev",
// Define top-level environment variables
// using the {"vars": "key": "value"} format
"vars": {
"API_ACCOUNT_ID": "<EXAMPLE-ACCOUNT-ID>"
}
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "my-worker-dev"
[vars]
API_ACCOUNT_ID = "<EXAMPLE-ACCOUNT-ID>"Proměnné prostředí ve formátu Service Worker
Ve formátu Service Worker API_ACCOUNT_ID je definována v globálním rozsahu vaší aplikace Worker. Váš API_ACCOUNT_ID proměnná prostředí je k dispozici kdekoli v kódu vaší aplikace Worker.
addEventListener("fetch", async (event) => {
console.log(API_ACCOUNT_ID) // Logs "<EXAMPLE-ACCOUNT-ID>"
return new Response("Hello, world!")
})Proměnné prostředí ve formátu ES modulů
Ve formátu ES modulů jsou proměnné prostředí dostupné prostřednictvím env parametru poskytnutého ve vstupním bodu vaší aplikace Worker:
export default {
async fetch(request, env, ctx) {
console.log(env.API_ACCOUNT_ID) // Logs "<EXAMPLE-ACCOUNT-ID>"
return new Response("Hello, world!")
},
};Můžete také importovat env z cloudflare:workers pro přístup k proměnným prostředí odkudkoli ve vašem kódu, včetně nejvyššího rozsahu (top-level scope):
import { env } from "cloudflare:workers";
// Access environment variables at the top level
const accountId = env.API_ACCOUNT_ID;
export default {
async fetch(request) {
console.log(accountId); // Logs "<EXAMPLE-ACCOUNT-ID>"
return new Response("Hello, world!");
},
};import { env } from "cloudflare:workers";
// Access environment variables at the top level
const accountId = env.API_ACCOUNT_ID;
export default {
async fetch(request: Request): Promise<Response> {
console.log(accountId) // Logs "<EXAMPLE-ACCOUNT-ID>"
return new Response("Hello, world!")
},
};Tento přístup je užitečný pro inicializaci konfigurace nebo přístup k proměnným prostředí z hluboce vnořených funkcí, aniž byste je museli předávat env při každém volání funkce. Další podrobnosti najdete v Import env jako globální.
Cron Triggers
Chcete-li zpracovat Cron Trigger událost ve Workeru napsaném v syntaxi ES modulů, implementujte scheduled() obslužná rutina události, což je ekvivalent naslouchání na scheduled událost v syntaxi Service Worker.
Tento ukázkový kód:
addEventListener("scheduled", (event) => {
// ...
});Poté se stane:
export default {
async scheduled(event, env, ctx) {
// ...
},
};Přístup event nebo context data
Workers často potřebují přístup k datům, která nejsou v request objekt. Workers například někdy používají waitUntil pro zpoždění spuštění. Workery používající formát ES modulů mají přístup k waitUntil prostřednictvím context parametru. Viz parametry ES modulů kde najdete další informace.
Tento ukázkový kód:
async function triggerEvent(event) {
// Fetch some data
console.log('cron processed', event.scheduledTime);
}
// Initialize Worker
addEventListener('scheduled', event => {
event.waitUntil(triggerEvent(event));
});Poté se stane:
async function triggerEvent(event) {
// Fetch some data
console.log('cron processed', event.scheduledTime);
}
export default {
async scheduled(event, env, ctx) {
ctx.waitUntil(triggerEvent(event));
},
};Syntaxe Service Worker
Worker napsaný v syntaxi Service Worker se skládá ze dvou částí:
- Event listener, který naslouchá
FetchEvents. - Obslužná rutina události, která vrací Odpověď objekt, který se předává do vlastnosti události
.respondWith()metoda.
Když některý z globálních síťových serverů Cloudflare přijme požadavek na URL odpovídající Workeru, server Cloudflare předá požadavek runtime prostředí Workers. To odešle FetchEvent v izolát kde Worker běží.
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
return new Response('Hello worker!', {
headers: { 'content-type': 'text/plain' },
});
}Níže je příklad pracovního postupu zpracování požadavku a odpovědi:
-
Event listener pro
FetchEventříká skriptu, aby naslouchal všem požadavkům přicházejícím do vašeho Workeru. Event handleru se předáváeventobjekt, který zahrnujeevent.request,Requestobjekt, což je reprezentace HTTP požadavku, který spustilFetchEvent. -
Volání
.respondWith()umožňuje běhovému prostředí Workers zachytit požadavek a vrátit vlastní odpověď (v tomto příkladu prostý text'Hello worker!').-
FetchEventhandler obvykle vyvrcholí voláním metody.respondWith()buď sResponseneboPromise<Response>která určuje odpověď. -
FetchEventobjekt také poskytuje dvě další metody ke zpracování neočekávaných výjimek a operací, které se mohou dokončit až po vrácení odpovědi.
-
Další informace o metody životního cyklu fetch() handler.
Podporováno FetchEvent vlastnosti
-
event.typestring- Typ události. Vždy vrací
"fetch".
- Typ události. Vždy vrací
-
event.requestRequest- Příchozí HTTP požadavek.
-
event.respondWith(responseResponse|Promise): void- Viz
respondWith.
- Viz
-
event.waitUntil(promisePromise): void- Viz
waitUntil.
- Viz
-
event.passThroughOnException(): void
respondWith
Zachytí požadavek a umožní Workeru odeslat vlastní odpověď.
Pokud fetch obslužná rutina události nevolá respondWith, runtime doručí událost dalšímu registrovanému fetch obslužná rutina události. Jinými slovy, i když se to nedoporučuje, je možné přidat více fetch obslužné rutiny událostí ve Workeru.
Pokud žádný fetch obslužná rutina události volá respondWith, pak runtime přesměruje požadavek na origin, jako by Worker neexistoval. Pokud ale origin neexistuje, nebo pokud je vaším origin serverem samotný Worker, což platí vždy pro *.workers.dev domén, pak musíte volat respondWith pro platnou odpověď.
// Format: Service Worker
addEventListener('fetch', event => {
let { pathname } = new URL(event.request.url);
// Allow "/ignore/*" URLs to hit origin
if (pathname.startsWith('/ignore/')) return;
// Otherwise, respond with something
event.respondWith(handler(event));
});waitUntil
waitUntil příkaz prodlužuje životnost "fetch" událost. Přijímá Promise-ovou úlohu, kterou runtime Workers spustí předtím, než handler skončí, ale bez blokování odpovědi. To je ideální například pro cachování odpovědí nebo zpracování logování.
Ve formátu Service Worker waitUntil je dostupná v rámci event protože se jedná o nativní FetchEvent vlastnost.
Ve formátu ES modules waitUntil je přesunuto a dostupné v context objekt parametrů.
// Format: Service Worker
addEventListener('fetch', event => {
event.respondWith(handler(event));
});
async function handler(event) {
// Forward / Proxy original request
let res = await fetch(event.request);
// Add custom header(s)
res = new Response(res.body, res);
res.headers.set('x-foo', 'bar');
// Cache the response
// NOTE: Does NOT block / wait
event.waitUntil(caches.default.put(event.request, res.clone()));
// Done
return res;
}passThroughOnException
passThroughOnException metoda zabraňuje chybové odpovědi za běhu, když Worker vyvolá neošetřenou výjimku. Skript místo toho fail open ↗, který přesměruje požadavek na origin server, jako kdyby Worker vůbec nebyl vyvolán.
Aby chyby JavaScriptu nezpůsobily selhání celých požadavků kvůli nezachyceným výjimkám, passThroughOnException() způsobí, že Workers runtime předá řízení origin serveru.
Ve formátu Service Worker passThroughOnException se přidá do FetchEvent rozhraní, čímž je zpřístupní v rámci event.
Ve formátu ES modules passThroughOnException je dostupná na context objekt parametrů.
// Format: Service Worker
addEventListener('fetch', event => {
// Proxy to origin on unhandled/uncaught exceptions
event.passThroughOnException();
throw new Error('Oops');
});