/worker

Use Web Workers in Astro

Primary LanguageJavaScript

Astro Worker

Astro Worker lets you use Web Workers in Astro, with server-side workers polyfilled by web-worker.

NPM Version NPM Downloads Open in StackBlitz

npm install @astropub/worker

Usage

Import @astropub/worker in your Astro configuration.

import worker from "@astropub/worker"
import { defineConfig } from "astro/config"

export default defineConfig({
  integrations: [
    worker(),
  ],
})

Creating a Worker

Create a worker in any Astro project.

---
/** @file /src/scripts/worker.ts */

addEventListener("message", (event) => {
  console.log("client said:", event.data)

  postMessage(event.data)
})

Using a Worker

Import the worker into Astro frontmatter.

---
/** @file /src/pages/index.astro */

const worker = new Worker("../scripts/worker.ts", { type: "module" })

worker.addEventListener("message", (event) => {
  console.log("worker said:", event.data)
})

worker.postMessage("Hello")
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Example</title>
  </head>
  <body>
    <h1>Example</h1>
  </body>
</html>

Alternatively, import the worker into a client-side script.

---
/** @file /src/pages/index.astro */
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Example</title>
  </head>
  <body>
    <h1>Example</h1>
  </body>
</html>
<script>
  const worker = new Worker("../scripts/worker.ts", { type: "module" })

  worker.addEventListener("message", (event) => {
    console.log("worker said:", event.data)
  })

  worker.postMessage("Hello")
</script>

How it works

This integration works by noticing when Worker or SharedWorker are used in scripts. If they are, this integration corrects any string references to files.

/* before (does not work in Astro) */
const worker = new Worker('../path/to/worker.js')

/* after (does work in Astro) */
const worker = new Worker(new URL('../path/to/worker.js', import.meta.url))

If the integration detects a server-side Worker then a polyfill is applied.

---
/* before (does not work in Astro) */
const worker = new Worker('../path/to/worker.js')
---
---
/* after (does work in Astro) */
import "@astropub/worker/polyfill"

const worker = new Worker(new URL('../path/to/worker.js', import.meta.url))
---

Enjoy!


Code original to this project is licensed under the MIT No Attribution License.

Code from web-worker is licensed under the Apache License (Apache-2.0), copyright Jason Miller.