Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support worker in worker #119

Merged
merged 8 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/web-worker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ pnpm build
pnpm preview
```

## tbd

- need parallel client/worker build to avoid extra client build for discovering worker references
- only esm supports multi worker entries

## related

- https://github.com/vitejs/vite/discussions/18191
Expand Down
7 changes: 7 additions & 0 deletions examples/web-worker/e2e/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,10 @@ test("erorr stack", async ({ page }) => {
const error = await errorPromise;
expect(error.message).toBe("test-error-stack");
});

test("worker in worker", async ({ page }) => {
await page.goto("/?worker-in-worker");
await expect(page.getByTestId("worker-message")).toContainText(
"Rendered in web worker in web worker",
);
});
6 changes: 6 additions & 0 deletions examples/web-worker/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export function App() {
if (window.location.search.includes("error-stack")) {
worker.postMessage({ type: "error" });
}
if (window.location.search.includes("worker-in-worker")) {
worker.postMessage({ type: "worker-in-worker" });
}
}
if (e.data.type === "worker-in-worker") {
setWorkerMessage(e.data.data);
}
});
return () => {
Expand Down
9 changes: 9 additions & 0 deletions examples/web-worker/src/worker/entry.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ReactDomServer from "react-dom/server";
import dep from "./dep";
import { depThrowError } from "./dep-error";
import workerInWorkerUrl from "./worker-in-worker?worker-runner";

self.addEventListener("message", (e) => {
if (e.data.type === "render") {
Expand All @@ -16,6 +17,14 @@ self.addEventListener("message", (e) => {
if (e.data.type === "error") {
depThrowError();
}
if (e.data.type === "worker-in-worker") {
const worker = new Worker(workerInWorkerUrl, { type: "module" });
worker.addEventListener("message", (e) => {
if (e.data.type === "ready") {
self.postMessage({ type: "worker-in-worker", data: e.data.data });
}
});
}
});

self.postMessage({ type: "ready" });
4 changes: 4 additions & 0 deletions examples/web-worker/src/worker/worker-in-worker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
self.postMessage({
type: "ready",
data: "Rendered in web worker in web worker",
});
30 changes: 23 additions & 7 deletions examples/web-worker/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ export default defineConfig((_env) => ({
},
},
worker: {
// consumer: "client", // TODO: is this desired? this would require explicitly setting `moduleRunnerTransform: true` etc...
webCompatible: true,
resolve: {
conditions: ["worker"],
noExternal: true,
},
dev: {
// moduleRunnerTransform: true,
optimizeDeps: {
include: [
"react",
Expand All @@ -44,6 +46,11 @@ export default defineConfig((_env) => ({
// emit actual worker entries during `buildStart`
_noop: "data:text/javascript,console.log()",
},
output: {
// force false since vite enables it when `consumer: "server"` and `webCompatible: true`
// https://github.com/vitejs/vite/blob/95020ab49e12d143262859e095025cf02423c1d9/packages/vite/src/node/build.ts#L761-L766
inlineDynamicImports: false,
},
},
},
},
Expand Down Expand Up @@ -84,29 +91,37 @@ export function vitePluginWorkerRunner(): Plugin[] {
map: null,
};
}
// build:
// build
if (this.environment.mode === "build") {
const entry = id.replace("?worker-runner", "");
let code: string;
if (manager.workerScan) {
// client -> worker (scan)
manager.workerMap[entry] = {};
// import worker as is to collect worker in worker during scan
code = `
import ${JSON.stringify(entry)};
export default "noop";
`;
} else if (this.environment.name === "worker") {
// worker -> worker (build)
// TODO
const referenceId = manager.workerMap[entry]!.referenceId;
code = `export default import.meta.ROLLUP_FILE_URL_${referenceId}`;
} else if (this.environment.name === "client") {
// client -> worker (build)
const fileName = manager.workerMap[entry]!.fileName;
return {
code: `export default ${JSON.stringify("/" + fileName)}`,
map: null,
};
code = `export default ${JSON.stringify("/" + fileName)}`;
} else {
throw new Error("unreachable");
}
return { code, map: null };
}
return { code: `export default "todo"`, map: null };
}

// rewrite worker entry to import it from runner
if (id.endsWith("?worker-runner-file")) {
console.assert(this.environment.name === "client");
console.assert(this.environment.mode === "dev");
const options = {
root: this.environment.config.root,
environmentName: "worker",
Expand Down Expand Up @@ -146,6 +161,7 @@ export function vitePluginWorkerRunner(): Plugin[] {
meta.fileName = this.getFileName(meta.referenceId!);
}
delete bundle["_noop.js"];
delete bundle["_noop.js.map"];
},
};

Expand Down