Skip to content

Web Worker support for esbuild flow#1103

Merged
cristiano-belloni merged 25 commits intomainfrom
feature/web-worker-plugin
Dec 1, 2021
Merged

Web Worker support for esbuild flow#1103
cristiano-belloni merged 25 commits intomainfrom
feature/web-worker-plugin

Conversation

@cristiano-belloni
Copy link
Contributor

@cristiano-belloni cristiano-belloni commented Nov 26, 2021

This PR introduces an esbuild plugin which:

  • Builds workers on the fly, matching them with the worker.[jt]sx?$ pattern
  • Trampolines them to work with CORS (thanks @LukeSheard)
  • Emits them as separate files
  • Exports a class that needs to be instantiated to start the worker
  • Allow only js, ts, jsx and tsx extensions to be loaded from a worker

This plugin works similarly to worker-loader for Webpack 4 (see below). It will probably superseded when Esbuild supports new Worker as an import, but we will still need trampolining.

Example

// index.ts
import HelloWorkerCls from './worker/hello.worker.ts';

const worker = new HelloWorkerCls();
workerRef.current.onmessage = (message) => console.log("Message from worker", message.data);
worker.postMessage(new Date.now());
// ./worker/hello.worker.ts
import { wait, format } from '../utils/date-locale';

globalThis.self.onmessage = async (message: { data: number }) => {
  postMessage(`Hello there. Processing date...`);
  // Simulate work
  await wait(500);
  postMessage(`Date is: ${format(message.data)}`);
};

Caveats

  • If workers don't import from other files, they need to export {} to not be considered global files by isolatedModules.

@changeset-bot
Copy link

changeset-bot bot commented Nov 26, 2021

⚠️ No Changeset found

Latest commit: f5b49d6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coveralls
Copy link
Collaborator

coveralls commented Nov 26, 2021

Coverage Status

Coverage increased (+0.9%) to 29.919% when pulling f5b49d6 on feature/web-worker-plugin into 8a1bf92 on main.

@cristiano-belloni cristiano-belloni changed the title Worker support in esbuild Web Worker support for esbuild flow Nov 26, 2021
@LukeSheard
Copy link
Contributor

Few initial thoughts:

  1. Maybe the regex should be /\.worker\.(js|ts|tsx)$/ to ensure it's only files which end with worker?
  2. We should probably write a plugin which disallows importing anything which is not .js .ts or .tsx files in the web worker otherwise we'll end up with asset files generated from the sub-build.
  3. You'll probably want to trampoline to the web-worker file WebWorker support? evanw/esbuild#312 (comment)
  4. You should also use file-loader to generate the emitted file for the worker so it's included in the build stats. You can probably do this by emitting to in-memory and then using a onLoad plugin to read the contents of the build out at the deferred time.

@cristiano-belloni
Copy link
Contributor Author

cristiano-belloni commented Nov 29, 2021

  1. You should also use file-loader to generate the emitted file for the worker so it's included in the build stats. You can probably do this by emitting to in-memory and then using a onLoad plugin to read the contents of the build out at the deferred time.

This is easily done if we want a flow like:

import myWorker from './myworker.worker.ts'; // imports the hashed filename
// ...
const workerInstance = new Worker(myWorker);

Where myWorker is simply an emitted hashed worker filename like myworker.worker-HXDOFRRO.js
But I guess we want a flow that's identical to Webpack 4 atm, to facilitate ports, correct, @LukeSheard (hence the trampolining)?

@LukeSheard
Copy link
Contributor

Where myWorker is simply an emitted hashed worker filename like myworker.worker-HXDOFRRO.js

Sounds perfect to e

But I guess we want a flow that's identical to Webpack 4 atm, to facilitate ports, correct, @LukeSheard (hence the trampolining)?

I think this is just more about supporting existing patterns and future proofing ourselves against problems we know we'll have. e.g cross-domain CDN asset support is going to be a blocker immediately.

@cristiano-belloni
Copy link
Contributor Author

cristiano-belloni commented Nov 30, 2021

  1. Maybe the regex should be /\.worker\.(js|ts|tsx)$/ to ensure it's only files which end with worker?

Done, loader URL not needed, regex is /.*\.worker.[jt]sx?$/

  1. We should probably write a plugin which disallows importing anything which is not .js .ts or .tsx files in the web worker otherwise we'll end up with asset files generated from the sub-build.

Done

  1. You'll probably want to trampoline to the web-worker file WebWorker support? evanw/esbuild#312 (comment)

Done

  1. You should also use file-loader to generate the emitted file for the worker so it's included in the build stats. You can probably do this by emitting to in-memory and then using a onLoad plugin to read the contents of the build out at the deferred time.

Done

@cristiano-belloni cristiano-belloni marked this pull request as ready for review November 30, 2021 16:15
@cristiano-belloni cristiano-belloni marked this pull request as draft December 1, 2021 09:42
@cristiano-belloni cristiano-belloni marked this pull request as ready for review December 1, 2021 09:55
Copy link
Contributor

@LukeSheard LukeSheard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing!! 🚀

@cristiano-belloni cristiano-belloni merged commit 7b2df4b into main Dec 1, 2021
@cristiano-belloni cristiano-belloni deleted the feature/web-worker-plugin branch December 1, 2021 16:02
@github-actions github-actions bot mentioned this pull request Dec 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants