Skip to content

Commit 5c8ff05

Browse files
authored
Add support for child environments (#11879)
* Add child-environment playground * Support multiple module runners in a single Worker * Add environmentNameToChildEnvironmentNamesMap * Create child environments in config * Update initRunner and initRunners * Use environment name from header in __VITE_INVOKE_MODULE__ * Apply internal plugins to child environments * Add changeset
1 parent c17e971 commit 5c8ff05

File tree

22 files changed

+545
-136
lines changed

22 files changed

+545
-136
lines changed

.changeset/major-snails-post.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
"@cloudflare/vite-plugin": minor
3+
---
4+
5+
Add support for child environments.
6+
7+
This is to support React Server Components via [@vitejs/plugin-rsc](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc) and frameworks that build on top of it. A `childEnvironments` option is now added to the plugin config to enable using multiple environments within a single Worker. The parent environment can import modules from a child environment in order to access a separate module graph. For a typical RSC use case, the plugin might be configured as in the following example:
8+
9+
```ts
10+
export default defineConfig({
11+
plugins: [
12+
cloudflare({
13+
viteEnvironment: {
14+
name: "rsc",
15+
childEnvironments: ["ssr"],
16+
},
17+
}),
18+
],
19+
});
20+
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { expect, test } from "vitest";
2+
import { getTextResponse, isBuild } from "../../__test-utils__";
3+
4+
test.runIf(!isBuild)("can import module from child environment", async () => {
5+
const response = await getTextResponse();
6+
expect(response).toBe("Hello from the child environment");
7+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "@playground/child-environment",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"build": "vite build",
7+
"check:type": "tsc --build",
8+
"dev": "vite dev",
9+
"preview": "vite preview"
10+
},
11+
"devDependencies": {
12+
"@cloudflare/vite-plugin": "workspace:*",
13+
"@cloudflare/workers-tsconfig": "workspace:*",
14+
"@cloudflare/workers-types": "catalog:default",
15+
"typescript": "catalog:default",
16+
"vite": "catalog:vite-plugin",
17+
"wrangler": "workspace:*"
18+
}
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// @ts-expect-error - no types
2+
import { getEnvironmentName } from "virtual:environment-name";
3+
4+
export function getMessage() {
5+
return `Hello from the ${getEnvironmentName()} environment`;
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
declare global {
2+
// In real world usage, this is accessed by `@vitejs/plugin-rsc`
3+
function __VITE_ENVIRONMENT_RUNNER_IMPORT__(
4+
environmentName: string,
5+
id: string
6+
): Promise<unknown>;
7+
}
8+
9+
export default {
10+
async fetch() {
11+
const childEnvironmentModule = (await __VITE_ENVIRONMENT_RUNNER_IMPORT__(
12+
"child",
13+
"./src/child-environment-module"
14+
)) as { getMessage: () => string };
15+
16+
return new Response(childEnvironmentModule.getMessage());
17+
},
18+
} satisfies ExportedHandler;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"files": [],
3+
"references": [
4+
{ "path": "./tsconfig.node.json" },
5+
{ "path": "./tsconfig.worker.json" }
6+
]
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": ["@cloudflare/workers-tsconfig/base.json"],
3+
"include": ["vite.config.ts", "__tests__"]
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": ["@cloudflare/workers-tsconfig/worker.json"],
3+
"include": ["src"]
4+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"$schema": "http://turbo.build/schema.json",
3+
"extends": ["//"],
4+
"tasks": {
5+
"build": {
6+
"outputs": ["dist/**"]
7+
}
8+
}
9+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { cloudflare } from "@cloudflare/vite-plugin";
2+
import { defineConfig } from "vite";
3+
4+
export default defineConfig({
5+
plugins: [
6+
cloudflare({
7+
inspectorPort: false,
8+
persistState: false,
9+
viteEnvironment: {
10+
name: "parent",
11+
childEnvironments: ["child"],
12+
},
13+
}),
14+
{
15+
name: "virtual-module-plugin",
16+
resolveId(source) {
17+
if (source === "virtual:environment-name") {
18+
return "\0virtual:environment-name";
19+
}
20+
},
21+
load(id) {
22+
if (id === "\0virtual:environment-name") {
23+
return `export function getEnvironmentName() { return ${JSON.stringify(this.environment.name)} }`;
24+
}
25+
},
26+
},
27+
],
28+
});

0 commit comments

Comments
 (0)