rwsdk 0.2.0-alpha.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/constants.d.mts +6 -1
- package/dist/lib/constants.mjs +6 -1
- package/dist/lib/smokeTests/browser.mjs +5 -21
- package/dist/lib/smokeTests/codeUpdates.d.mts +1 -1
- package/dist/lib/smokeTests/codeUpdates.mjs +41 -5
- package/dist/lib/smokeTests/development.d.mts +1 -1
- package/dist/lib/smokeTests/development.mjs +4 -10
- package/dist/lib/smokeTests/release.d.mts +1 -1
- package/dist/lib/smokeTests/release.mjs +4 -9
- package/dist/lib/smokeTests/runSmokeTests.mjs +2 -2
- package/dist/lib/smokeTests/templates/SmokeTest.template.js +3 -2
- package/dist/lib/testUtils/stubEnvVars.d.mts +2 -0
- package/dist/lib/testUtils/stubEnvVars.mjs +11 -0
- package/dist/runtime/client/client.d.ts +10 -0
- package/dist/runtime/{client.js → client/client.js} +13 -10
- package/dist/runtime/{clientNavigation.test.js → client/navigation.test.js} +1 -1
- package/dist/runtime/client/setWebpackRequire.d.ts +1 -0
- package/dist/runtime/client/setWebpackRequire.js +2 -0
- package/dist/runtime/{client.d.ts → client/types.d.ts} +4 -10
- package/dist/runtime/client/types.js +1 -0
- package/dist/runtime/entries/client.d.ts +2 -2
- package/dist/runtime/entries/client.js +2 -2
- package/dist/runtime/imports/client.d.ts +3 -3
- package/dist/runtime/imports/client.js +11 -15
- package/dist/runtime/imports/ssr.d.ts +3 -3
- package/dist/runtime/imports/ssr.js +3 -3
- package/dist/runtime/imports/worker.d.ts +3 -3
- package/dist/runtime/imports/worker.js +5 -4
- package/dist/runtime/lib/manifest.d.ts +11 -2
- package/dist/runtime/lib/manifest.js +1 -1
- package/dist/runtime/lib/memoizeOnId.d.ts +1 -0
- package/dist/runtime/lib/memoizeOnId.js +11 -0
- package/dist/runtime/lib/realtime/client.d.ts +1 -1
- package/dist/runtime/lib/realtime/client.js +1 -1
- package/dist/runtime/lib/router.d.ts +3 -3
- package/dist/runtime/lib/router.js +77 -33
- package/dist/runtime/register/ssr.d.ts +1 -1
- package/dist/runtime/register/ssr.js +4 -3
- package/dist/runtime/render/preloads.d.ts +6 -0
- package/dist/runtime/render/preloads.js +40 -0
- package/dist/runtime/render/renderRscThenableToHtmlStream.js +2 -1
- package/dist/runtime/render/stylesheets.js +1 -1
- package/dist/runtime/requestInfo/types.d.ts +3 -1
- package/dist/runtime/requestInfo/worker.js +9 -1
- package/dist/runtime/worker.d.ts +0 -3
- package/dist/runtime/worker.js +2 -11
- package/dist/scripts/debug-sync.mjs +142 -39
- package/dist/scripts/smoke-test.mjs +0 -10
- package/dist/scripts/worker-run.mjs +8 -3
- package/dist/vite/buildApp.d.mts +15 -0
- package/dist/vite/buildApp.mjs +53 -0
- package/dist/vite/configPlugin.d.mts +4 -2
- package/dist/vite/configPlugin.mjs +69 -62
- package/dist/vite/createDirectiveLookupPlugin.d.mts +0 -6
- package/dist/vite/createDirectiveLookupPlugin.mjs +61 -145
- package/dist/vite/directiveModulesDevPlugin.d.mts +8 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +62 -0
- package/dist/vite/directivesFilteringPlugin.d.mts +6 -0
- package/dist/vite/directivesFilteringPlugin.mjs +31 -0
- package/dist/vite/directivesPlugin.mjs +28 -42
- package/dist/vite/getViteEsbuild.d.mts +1 -0
- package/dist/vite/getViteEsbuild.mjs +12 -0
- package/dist/vite/hasOwnReactVitePlugin.d.mts +3 -0
- package/dist/vite/hasOwnReactVitePlugin.mjs +14 -0
- package/dist/vite/injectVitePreamblePlugin.d.mts +3 -2
- package/dist/vite/injectVitePreamblePlugin.mjs +4 -2
- package/dist/vite/linkerPlugin.d.mts +4 -0
- package/dist/vite/linkerPlugin.mjs +41 -0
- package/dist/vite/manifestPlugin.d.mts +2 -2
- package/dist/vite/manifestPlugin.mjs +12 -37
- package/dist/vite/miniflareHMRPlugin.mjs +17 -2
- package/dist/vite/moveStaticAssetsPlugin.mjs +2 -1
- package/dist/vite/prismaPlugin.mjs +1 -1
- package/dist/vite/reactConditionsResolverPlugin.d.mts +3 -4
- package/dist/vite/reactConditionsResolverPlugin.mjs +74 -56
- package/dist/vite/redwoodPlugin.d.mts +1 -1
- package/dist/vite/redwoodPlugin.mjs +36 -12
- package/dist/vite/runDirectivesScan.d.mts +7 -0
- package/dist/vite/runDirectivesScan.mjs +152 -0
- package/dist/vite/ssrBridgePlugin.mjs +13 -14
- package/dist/vite/transformClientComponents.d.mts +0 -1
- package/dist/vite/transformClientComponents.mjs +1 -9
- package/dist/vite/transformJsxScriptTagsPlugin.d.mts +4 -3
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +151 -158
- package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +393 -136
- package/dist/vite/transformServerFunctions.d.mts +1 -1
- package/dist/vite/transformServerFunctions.mjs +11 -12
- package/package.json +28 -4
- /package/dist/runtime/{imports → client}/ClientOnly.d.ts +0 -0
- /package/dist/runtime/{imports → client}/ClientOnly.js +0 -0
- /package/dist/runtime/{clientNavigation.d.ts → client/navigation.d.ts} +0 -0
- /package/dist/runtime/{clientNavigation.js → client/navigation.js} +0 -0
- /package/dist/runtime/{clientNavigation.test.d.ts → client/navigation.test.d.ts} +0 -0
|
@@ -28,36 +28,12 @@ const getLoader = (filePath) => {
|
|
|
28
28
|
export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, }) => {
|
|
29
29
|
let devServer;
|
|
30
30
|
let isAfterFirstResponse = false;
|
|
31
|
-
|
|
32
|
-
const files = kind === "client" ? clientFiles : serverFiles;
|
|
33
|
-
const rawId = id.split("?")[0];
|
|
34
|
-
const resolvedId = normalizeModulePath(rawId, projectRootDir);
|
|
35
|
-
const fullPath = normalizeModulePath(rawId, projectRootDir, {
|
|
36
|
-
absolute: true,
|
|
37
|
-
});
|
|
38
|
-
const isNodeModule = id.includes("node_modules");
|
|
39
|
-
const hadFile = files.has(id);
|
|
40
|
-
log("Adding %s module to %s and invalidating cache: id=%s", kind, files, resolvedId);
|
|
41
|
-
files.add(resolvedId);
|
|
42
|
-
if (devServer && isNodeModule) {
|
|
43
|
-
const lookupModule = kind === "client"
|
|
44
|
-
? "virtual:use-client-lookup"
|
|
45
|
-
: "virtual:use-server-lookup";
|
|
46
|
-
log("Registering missing import for %s module resolvedId=%s in environment %s, fullPath=%s", kind, resolvedId, environment, fullPath);
|
|
47
|
-
devServer.environments[environment].depsOptimizer?.registerMissingImport(resolvedId, fullPath);
|
|
48
|
-
if (isAfterFirstResponse && !hadFile) {
|
|
49
|
-
log("Invalidating cache for lookup module %s after adding module id=%s", lookupModule, id);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const addClientModule = (environment, id) => {
|
|
54
|
-
addModule("client", environment, id);
|
|
55
|
-
};
|
|
56
|
-
const addServerModule = (environment, id) => {
|
|
57
|
-
addModule("server", environment, id);
|
|
58
|
-
};
|
|
31
|
+
let isBuild = false;
|
|
59
32
|
return {
|
|
60
33
|
name: "rwsdk:rsc-directives",
|
|
34
|
+
configResolved(config) {
|
|
35
|
+
isBuild = config.command === "build";
|
|
36
|
+
},
|
|
61
37
|
configureServer(server) {
|
|
62
38
|
devServer = server;
|
|
63
39
|
devServer.middlewares.use((_req, res, next) => {
|
|
@@ -76,33 +52,42 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
|
|
|
76
52
|
});
|
|
77
53
|
},
|
|
78
54
|
async transform(code, id) {
|
|
79
|
-
|
|
80
|
-
|
|
55
|
+
if (isBuild &&
|
|
56
|
+
this.environment?.name === "worker" &&
|
|
57
|
+
process.env.RWSDK_BUILD_PASS !== "worker") {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
81
60
|
const normalizedId = normalizeModulePath(id, projectRootDir);
|
|
82
61
|
const clientResult = await transformClientComponents(code, normalizedId, {
|
|
83
62
|
environmentName: this.environment.name,
|
|
84
63
|
clientFiles,
|
|
85
|
-
addClientModule,
|
|
86
64
|
});
|
|
87
65
|
if (clientResult) {
|
|
88
|
-
|
|
66
|
+
process.env.VERBOSE &&
|
|
67
|
+
log("Client component transformation successful for id=%s", id);
|
|
89
68
|
return {
|
|
90
69
|
code: clientResult.code,
|
|
91
70
|
map: clientResult.map,
|
|
92
71
|
};
|
|
93
72
|
}
|
|
94
|
-
const serverResult = transformServerFunctions(code, normalizedId, this.environment.name, serverFiles
|
|
73
|
+
const serverResult = transformServerFunctions(code, normalizedId, this.environment.name, serverFiles);
|
|
95
74
|
if (serverResult) {
|
|
96
|
-
|
|
75
|
+
process.env.VERBOSE &&
|
|
76
|
+
log("Server function transformation successful for id=%s", id);
|
|
97
77
|
return {
|
|
98
78
|
code: serverResult.code,
|
|
99
79
|
map: serverResult.map,
|
|
100
80
|
};
|
|
101
81
|
}
|
|
102
|
-
|
|
82
|
+
// Removed: too noisy even in verbose mode
|
|
103
83
|
},
|
|
104
84
|
configEnvironment(env, config) {
|
|
105
|
-
|
|
85
|
+
if (isBuild &&
|
|
86
|
+
env === "worker" &&
|
|
87
|
+
process.env.RWSDK_BUILD_PASS !== "worker") {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
process.env.VERBOSE && log("Configuring environment: env=%s", env);
|
|
106
91
|
config.optimizeDeps ??= {};
|
|
107
92
|
config.optimizeDeps.esbuildOptions ??= {};
|
|
108
93
|
config.optimizeDeps.esbuildOptions.plugins ??= [];
|
|
@@ -120,7 +105,6 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
|
|
|
120
105
|
// dependency discovery, so we can skip transform work
|
|
121
106
|
// and use heuristics instead - see below inside if block
|
|
122
107
|
if (!args.path.includes("node_modules")) {
|
|
123
|
-
log("Esbuild onLoad found app code, path=%s", args.path);
|
|
124
108
|
if (clientFiles.has(normalizedPath)) {
|
|
125
109
|
// context(justinvdm,2025-06-15): If this is a client file:
|
|
126
110
|
// * for ssr and client envs we can skip so esbuild looks at the
|
|
@@ -171,10 +155,10 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
|
|
|
171
155
|
environmentName: env,
|
|
172
156
|
clientFiles,
|
|
173
157
|
isEsbuild: true,
|
|
174
|
-
addClientModule,
|
|
175
158
|
});
|
|
176
159
|
if (clientResult) {
|
|
177
|
-
|
|
160
|
+
process.env.VERBOSE &&
|
|
161
|
+
log("Esbuild client component transformation successful for environment=%s, path=%s", env, args.path);
|
|
178
162
|
process.env.VERBOSE &&
|
|
179
163
|
log("Esbuild client component transformation for environment=%s, path=%s, code: %j", env, args.path, clientResult.code);
|
|
180
164
|
return {
|
|
@@ -182,9 +166,10 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
|
|
|
182
166
|
loader: getLoader(args.path),
|
|
183
167
|
};
|
|
184
168
|
}
|
|
185
|
-
const serverResult = transformServerFunctions(code, normalizedPath, env, serverFiles
|
|
169
|
+
const serverResult = transformServerFunctions(code, normalizedPath, env, serverFiles);
|
|
186
170
|
if (serverResult) {
|
|
187
|
-
|
|
171
|
+
process.env.VERBOSE &&
|
|
172
|
+
log("Esbuild server function transformation successful for environment=%s, path=%s", env, args.path);
|
|
188
173
|
return {
|
|
189
174
|
contents: serverResult.code,
|
|
190
175
|
loader: getLoader(args.path),
|
|
@@ -195,7 +180,8 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
|
|
|
195
180
|
});
|
|
196
181
|
},
|
|
197
182
|
});
|
|
198
|
-
|
|
183
|
+
process.env.VERBOSE &&
|
|
184
|
+
log("Environment configuration complete for env=%s", env);
|
|
199
185
|
},
|
|
200
186
|
};
|
|
201
187
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getViteEsbuild(projectRootDir: string): Promise<any>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
export async function getViteEsbuild(projectRootDir) {
|
|
5
|
+
const vitePath = require.resolve("vite/package.json", {
|
|
6
|
+
paths: [projectRootDir],
|
|
7
|
+
});
|
|
8
|
+
const viteDir = path.dirname(vitePath);
|
|
9
|
+
const esbuildPath = require.resolve("esbuild", { paths: [viteDir] });
|
|
10
|
+
const esbuildModule = await import(esbuildPath);
|
|
11
|
+
return esbuildModule.default || esbuildModule;
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { readFile } from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export async function hasOwnReactVitePlugin({ rootProjectDir, }) {
|
|
4
|
+
const packageJsonPath = path.join(rootProjectDir, "package.json");
|
|
5
|
+
try {
|
|
6
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
|
|
7
|
+
return !!(packageJson.dependencies?.["@vitejs/plugin-react"] ||
|
|
8
|
+
packageJson.devDependencies?.["@vitejs/plugin-react"]);
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
console.error("Error reading package.json:", error);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Plugin } from "vite";
|
|
2
|
-
export declare const injectVitePreamble: ({
|
|
3
|
-
|
|
2
|
+
export declare const injectVitePreamble: ({ clientEntryPoints, projectRootDir, }: {
|
|
3
|
+
clientEntryPoints: Set<string>;
|
|
4
|
+
projectRootDir: string;
|
|
4
5
|
}) => Plugin;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import MagicString from "magic-string";
|
|
2
|
-
|
|
2
|
+
import { normalizeModulePath } from "../lib/normalizeModulePath.mjs";
|
|
3
|
+
export const injectVitePreamble = ({ clientEntryPoints, projectRootDir, }) => ({
|
|
3
4
|
name: "rwsdk:inject-vite-preamble",
|
|
4
5
|
apply: "serve",
|
|
5
6
|
transform(code, id) {
|
|
6
7
|
if (this.environment.name !== "client") {
|
|
7
8
|
return;
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
+
const normalizedId = normalizeModulePath(id, projectRootDir);
|
|
11
|
+
if (!clientEntryPoints.has(normalizedId)) {
|
|
10
12
|
return;
|
|
11
13
|
}
|
|
12
14
|
// Only inject preamble in development mode
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fsp from "node:fs/promises";
|
|
3
|
+
import { CLIENT_MANIFEST_RELATIVE_PATH } from "../lib/constants.mjs";
|
|
4
|
+
import debug from "debug";
|
|
5
|
+
import { normalizeModulePath } from "../lib/normalizeModulePath.mjs";
|
|
6
|
+
const log = debug("rwsdk:vite:linker-plugin");
|
|
7
|
+
export const linkerPlugin = ({ projectRootDir, }) => {
|
|
8
|
+
return {
|
|
9
|
+
name: "rwsdk:linker",
|
|
10
|
+
async renderChunk(code) {
|
|
11
|
+
if (this.environment.name !== "worker" ||
|
|
12
|
+
process.env.RWSDK_BUILD_PASS !== "linker") {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
log("Rendering final worker chunk");
|
|
16
|
+
let newCode = code;
|
|
17
|
+
// Read the manifest from the filesystem.
|
|
18
|
+
const manifestContent = await fsp.readFile(path.resolve(projectRootDir, CLIENT_MANIFEST_RELATIVE_PATH), "utf-8");
|
|
19
|
+
const manifest = JSON.parse(manifestContent);
|
|
20
|
+
// 1. Replace the manifest placeholder with the actual manifest content.
|
|
21
|
+
log("Injecting manifest into worker bundle");
|
|
22
|
+
newCode = newCode.replace('"__RWSDK_MANIFEST_PLACEHOLDER__"', manifestContent);
|
|
23
|
+
// 2. Replace asset placeholders with their final hashed paths.
|
|
24
|
+
log("Replacing asset placeholders in final worker bundle");
|
|
25
|
+
for (const [key, value] of Object.entries(manifest)) {
|
|
26
|
+
const normalizedKey = normalizeModulePath(key, projectRootDir, {
|
|
27
|
+
isViteStyle: false,
|
|
28
|
+
});
|
|
29
|
+
newCode = newCode.replaceAll(`rwsdk_asset:${normalizedKey}`, `/${value.file}`);
|
|
30
|
+
}
|
|
31
|
+
// 3. Deprefix any remaining placeholders that were not in the manifest.
|
|
32
|
+
// This handles public assets that don't go through the bundler.
|
|
33
|
+
log("Deprefixing remaining asset placeholders");
|
|
34
|
+
newCode = newCode.replaceAll("rwsdk_asset:", "");
|
|
35
|
+
return {
|
|
36
|
+
code: newCode,
|
|
37
|
+
map: null,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -1,57 +1,32 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
1
|
import debug from "debug";
|
|
3
|
-
import { normalizeModulePath } from "../lib/normalizeModulePath.mjs";
|
|
4
2
|
const log = debug("rwsdk:vite:manifest-plugin");
|
|
5
3
|
const virtualModuleId = "virtual:rwsdk:manifest.js";
|
|
6
4
|
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
7
|
-
export const manifestPlugin = ({
|
|
5
|
+
export const manifestPlugin = ({ projectRootDir, }) => {
|
|
8
6
|
let isBuild = false;
|
|
9
|
-
let root;
|
|
10
7
|
return {
|
|
11
|
-
name: "rwsdk:manifest",
|
|
8
|
+
name: "rwsdk:vite:manifest-plugin",
|
|
9
|
+
enforce: "pre",
|
|
12
10
|
configResolved(config) {
|
|
13
|
-
log("Config resolved, command=%s", config.command);
|
|
14
11
|
isBuild = config.command === "build";
|
|
15
|
-
root = config.root;
|
|
16
12
|
},
|
|
17
13
|
resolveId(id) {
|
|
18
14
|
if (id === virtualModuleId) {
|
|
19
|
-
process.env.VERBOSE && log("Resolving virtual module id=%s", id);
|
|
20
15
|
return resolvedVirtualModuleId;
|
|
21
16
|
}
|
|
22
17
|
},
|
|
23
18
|
async load(id) {
|
|
24
19
|
if (id === resolvedVirtualModuleId) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
if (isBuild) {
|
|
21
|
+
// context(justinvdm, 28 Aug 2025): During the build, we don't have
|
|
22
|
+
// the manifest yet. We insert a placeholder that the linker plugin
|
|
23
|
+
// will replace in the final phase.
|
|
24
|
+
log("Returning manifest placeholder for build");
|
|
25
|
+
return `export default "__RWSDK_MANIFEST_PLACEHOLDER__"`;
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const normalizedManifest = {};
|
|
34
|
-
for (const key in manifest) {
|
|
35
|
-
const normalizedKey = normalizeModulePath(key, root, {
|
|
36
|
-
isViteStyle: false,
|
|
37
|
-
});
|
|
38
|
-
const entry = manifest[key];
|
|
39
|
-
delete manifest[key];
|
|
40
|
-
normalizedManifest[normalizedKey] = entry;
|
|
41
|
-
entry.file = normalizeModulePath(entry.file, root, {
|
|
42
|
-
isViteStyle: false,
|
|
43
|
-
});
|
|
44
|
-
const normalizedCss = [];
|
|
45
|
-
if (entry.css) {
|
|
46
|
-
for (const css of entry.css) {
|
|
47
|
-
normalizedCss.push(normalizeModulePath(css, root, {
|
|
48
|
-
isViteStyle: false,
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
entry.css = normalizedCss;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return `export default ${JSON.stringify(normalizedManifest)}`;
|
|
27
|
+
// In dev, we can return an empty object.
|
|
28
|
+
log("Not a build, returning empty manifest");
|
|
29
|
+
return `export default {}`;
|
|
55
30
|
}
|
|
56
31
|
},
|
|
57
32
|
configEnvironment(name, config) {
|
|
@@ -66,6 +66,9 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
66
66
|
};
|
|
67
67
|
},
|
|
68
68
|
async hotUpdate(ctx) {
|
|
69
|
+
if (ctx.file.includes(".wrangler")) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
69
72
|
if (hasErrored) {
|
|
70
73
|
const shortName = getShortName(ctx.file, ctx.server.config.root);
|
|
71
74
|
this.environment.logger.info(`${colors.cyan(`attempting to recover from error`)}: update to ${colors.dim(shortName)}`, {
|
|
@@ -77,6 +80,7 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
77
80
|
type: "full-reload",
|
|
78
81
|
path: "*",
|
|
79
82
|
});
|
|
83
|
+
log("hmr: Full reload after error");
|
|
80
84
|
return [];
|
|
81
85
|
}
|
|
82
86
|
const { clientFiles, serverFiles, viteEnvironment: { name: environment }, workerEntryPathname: entry, } = givenOptions;
|
|
@@ -84,6 +88,7 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
84
88
|
log(`Hot update: (env=${this.environment.name}) ${ctx.file}\nModule graph:\n\n${dumpFullModuleGraph(ctx.server, this.environment.name)}`);
|
|
85
89
|
}
|
|
86
90
|
if (!isJsFile(ctx.file) && !ctx.file.endsWith(".css")) {
|
|
91
|
+
log(`hmr: not a js file, skipping`);
|
|
87
92
|
return;
|
|
88
93
|
}
|
|
89
94
|
if (this.environment.name === "ssr") {
|
|
@@ -94,14 +99,17 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
94
99
|
server: ctx.server,
|
|
95
100
|
});
|
|
96
101
|
if (!isUseClientUpdate) {
|
|
102
|
+
log("hmr: not a use client update, short circuiting");
|
|
97
103
|
return [];
|
|
98
104
|
}
|
|
99
105
|
invalidateModule(ctx.server, "ssr", ctx.file);
|
|
100
106
|
invalidateModule(ctx.server, environment, VIRTUAL_SSR_PREFIX +
|
|
101
107
|
normalizeModulePath(ctx.file, givenOptions.rootDir));
|
|
108
|
+
log("hmr: invalidated ssr module");
|
|
102
109
|
return [];
|
|
103
110
|
}
|
|
104
111
|
if (!["client", environment].includes(this.environment.name)) {
|
|
112
|
+
log(`hmr: incorrect env, skipping (env=${this.environment.name}, worker env=${environment})`);
|
|
105
113
|
return [];
|
|
106
114
|
}
|
|
107
115
|
const hasClientDirective = await hasDirective(ctx.file, "use client");
|
|
@@ -165,8 +173,10 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
165
173
|
server: ctx.server,
|
|
166
174
|
});
|
|
167
175
|
if (!isUseClientUpdate && !ctx.file.endsWith(".css")) {
|
|
176
|
+
log("hmr: not a use client update and not css, short circuiting");
|
|
168
177
|
return [];
|
|
169
178
|
}
|
|
179
|
+
log("hmr: returning client modules for hmr");
|
|
170
180
|
return ctx.modules;
|
|
171
181
|
}
|
|
172
182
|
// The worker needs an update, and the hot check is for the worker environment
|
|
@@ -184,8 +194,12 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
184
194
|
if (m) {
|
|
185
195
|
invalidateModule(ctx.server, environment, m);
|
|
186
196
|
}
|
|
187
|
-
|
|
188
|
-
normalizeModulePath(ctx.file, givenOptions.rootDir)
|
|
197
|
+
let virtualSSRModuleId = VIRTUAL_SSR_PREFIX +
|
|
198
|
+
normalizeModulePath(ctx.file, givenOptions.rootDir);
|
|
199
|
+
if (ctx.file.endsWith(".css")) {
|
|
200
|
+
virtualSSRModuleId += ".js";
|
|
201
|
+
}
|
|
202
|
+
const virtualSSRModule = ctx.server.environments[environment].moduleGraph.idToModuleMap.get(virtualSSRModuleId);
|
|
189
203
|
if (virtualSSRModule) {
|
|
190
204
|
invalidateModule(ctx.server, environment, virtualSSRModule);
|
|
191
205
|
}
|
|
@@ -196,6 +210,7 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
196
210
|
file: ctx.file,
|
|
197
211
|
},
|
|
198
212
|
});
|
|
213
|
+
log("hmr: sent rsc update");
|
|
199
214
|
return [];
|
|
200
215
|
}
|
|
201
216
|
},
|
|
@@ -3,7 +3,8 @@ export const moveStaticAssetsPlugin = ({ rootDir, }) => ({
|
|
|
3
3
|
name: "rwsdk:move-static-assets",
|
|
4
4
|
apply: "build",
|
|
5
5
|
async closeBundle() {
|
|
6
|
-
if (this.environment.name === "worker"
|
|
6
|
+
if (this.environment.name === "worker" &&
|
|
7
|
+
process.env.RWSDK_BUILD_PASS === "linker") {
|
|
7
8
|
await $sh({
|
|
8
9
|
cwd: rootDir,
|
|
9
10
|
}) `mv dist/worker/assets/*.css dist/client/assets/ || true`;
|
|
@@ -17,7 +17,7 @@ export const prismaPlugin = async ({ projectRootDir, }) => {
|
|
|
17
17
|
return {
|
|
18
18
|
name: "rwsdk:prisma",
|
|
19
19
|
configEnvironment(name, config) {
|
|
20
|
-
if (name !== "worker") {
|
|
20
|
+
if (name !== "worker" || !process.env.VITE_IS_DEV_SERVER) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
const wasmPath = resolve(projectRootDir, "node_modules/.prisma/client/wasm.js");
|
|
@@ -10,7 +10,6 @@ export declare const ENV_RESOLVERS: {
|
|
|
10
10
|
worker: enhancedResolve.ResolveFunction;
|
|
11
11
|
client: enhancedResolve.ResolveFunction;
|
|
12
12
|
};
|
|
13
|
-
export declare const
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
export declare const reactConditionsResolverPlugin: () => Plugin[];
|
|
13
|
+
export declare const reactConditionsResolverPlugin: ({ projectRootDir, }: {
|
|
14
|
+
projectRootDir: string;
|
|
15
|
+
}) => Plugin[];
|
|
@@ -3,6 +3,7 @@ import { ROOT_DIR } from "../lib/constants.mjs";
|
|
|
3
3
|
import enhancedResolve from "enhanced-resolve";
|
|
4
4
|
import { ensureAliasArray } from "./ensureAliasArray.mjs";
|
|
5
5
|
const log = debug("rwsdk:vite:react-conditions-resolver-plugin");
|
|
6
|
+
const REACT_PREFIXES = ["react", "react-dom", "react-server-dom-webpack"];
|
|
6
7
|
export const ENV_REACT_IMPORTS = {
|
|
7
8
|
worker: [
|
|
8
9
|
"react",
|
|
@@ -41,69 +42,85 @@ export const ENV_RESOLVERS = {
|
|
|
41
42
|
conditionNames: ["browser", "default"],
|
|
42
43
|
}),
|
|
43
44
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
function resolveReactImport(id, envName, projectRootDir, isReactImportKnown = false) {
|
|
46
|
+
if (!isReactImportKnown) {
|
|
47
|
+
const isReactImport = REACT_PREFIXES.some((prefix) => id === prefix || id.startsWith(`${prefix}/`));
|
|
48
|
+
if (!isReactImport) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let resolved;
|
|
53
|
+
try {
|
|
54
|
+
resolved = ENV_RESOLVERS[envName](projectRootDir, id) || undefined;
|
|
55
|
+
process.env.VERBOSE &&
|
|
56
|
+
log("Successfully resolved %s to %s for env=%s from project root", id, resolved, envName);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
54
59
|
process.env.VERBOSE &&
|
|
55
|
-
log("
|
|
56
|
-
let resolved = false;
|
|
60
|
+
log("Failed to resolve %s for env=%s from project root, trying ROOT_DIR", id, envName);
|
|
57
61
|
try {
|
|
58
|
-
resolved = ENV_RESOLVERS[
|
|
62
|
+
resolved = ENV_RESOLVERS[envName](ROOT_DIR, id) || undefined;
|
|
59
63
|
process.env.VERBOSE &&
|
|
60
|
-
log("Successfully resolved %s to %s for env=%s",
|
|
64
|
+
log("Successfully resolved %s to %s for env=%s from rwsdk root", id, resolved, envName);
|
|
61
65
|
}
|
|
62
66
|
catch {
|
|
63
67
|
process.env.VERBOSE &&
|
|
64
|
-
log("Failed to resolve %s for env=%s",
|
|
68
|
+
log("Failed to resolve %s for env=%s", id, envName);
|
|
65
69
|
}
|
|
70
|
+
}
|
|
71
|
+
return resolved;
|
|
72
|
+
}
|
|
73
|
+
function resolveEnvImportMappings(env, projectRootDir) {
|
|
74
|
+
process.env.VERBOSE &&
|
|
75
|
+
log("Resolving environment import mappings for env=%s", env);
|
|
76
|
+
const mappings = new Map();
|
|
77
|
+
const reactImports = ENV_REACT_IMPORTS[env];
|
|
78
|
+
for (const importRequest of reactImports) {
|
|
79
|
+
const resolved = resolveReactImport(importRequest, env, projectRootDir, true);
|
|
66
80
|
if (resolved) {
|
|
67
81
|
mappings.set(importRequest, resolved);
|
|
68
|
-
|
|
82
|
+
process.env.VERBOSE &&
|
|
83
|
+
log("Added mapping for %s -> %s in env=%s", importRequest, resolved, env);
|
|
69
84
|
}
|
|
70
85
|
}
|
|
71
|
-
|
|
86
|
+
process.env.VERBOSE &&
|
|
87
|
+
log("Environment import mappings complete for env=%s: %d mappings", env, mappings.size);
|
|
72
88
|
return mappings;
|
|
73
89
|
}
|
|
74
|
-
|
|
75
|
-
const mappings = ENV_IMPORT_MAPPINGS[envName];
|
|
76
|
-
if (!mappings) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
name: `rwsdk:react-conditions-resolver-esbuild-${envName}`,
|
|
81
|
-
setup(build) {
|
|
82
|
-
build.onResolve({ filter: /.*/ }, (args) => {
|
|
83
|
-
process.env.VERBOSE &&
|
|
84
|
-
log("ESBuild resolving %s for env=%s, args=%O", args.path, envName, args);
|
|
85
|
-
const resolved = mappings.get(args.path);
|
|
86
|
-
if (resolved && args.importer !== "") {
|
|
87
|
-
process.env.VERBOSE &&
|
|
88
|
-
log("ESBuild resolving %s -> %s for env=%s", args.path, resolved, envName);
|
|
89
|
-
if (args.path === "react-server-dom-webpack/client.edge") {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
path: resolved,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
process.env.VERBOSE &&
|
|
98
|
-
log("ESBuild no resolution found for %s for env=%s", args.path, envName);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
export const reactConditionsResolverPlugin = () => {
|
|
90
|
+
export const reactConditionsResolverPlugin = ({ projectRootDir, }) => {
|
|
105
91
|
log("Initializing react conditions resolver plugin");
|
|
106
92
|
let isBuild = false;
|
|
93
|
+
const ENV_IMPORT_MAPPINGS = Object.fromEntries(Object.keys(ENV_RESOLVERS).map((env) => [
|
|
94
|
+
env,
|
|
95
|
+
resolveEnvImportMappings(env, projectRootDir),
|
|
96
|
+
]));
|
|
97
|
+
// Log a clean summary instead of all the individual mappings
|
|
98
|
+
const totalMappings = Object.values(ENV_IMPORT_MAPPINGS).reduce((sum, mappings) => sum + mappings.size, 0);
|
|
99
|
+
log("React conditions resolver configured with %d total mappings across %d environments", totalMappings, Object.keys(ENV_IMPORT_MAPPINGS).length);
|
|
100
|
+
function createEsbuildResolverPlugin(envName, mappings) {
|
|
101
|
+
if (!mappings) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
name: `rwsdk:react-conditions-resolver-esbuild-${envName}`,
|
|
106
|
+
setup(build) {
|
|
107
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
|
108
|
+
let resolved = mappings.get(args.path);
|
|
109
|
+
if (!resolved) {
|
|
110
|
+
resolved = resolveReactImport(args.path, envName, projectRootDir);
|
|
111
|
+
}
|
|
112
|
+
if (resolved && args.importer !== "") {
|
|
113
|
+
if (args.path === "react-server-dom-webpack/client.edge") {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
path: resolved,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
107
124
|
return [
|
|
108
125
|
{
|
|
109
126
|
name: "rwsdk:react-conditions-resolver:config",
|
|
@@ -125,7 +142,7 @@ export const reactConditionsResolverPlugin = () => {
|
|
|
125
142
|
config.environments[envName] = {};
|
|
126
143
|
}
|
|
127
144
|
const envConfig = config.environments[envName];
|
|
128
|
-
const esbuildPlugin = createEsbuildResolverPlugin(envName);
|
|
145
|
+
const esbuildPlugin = createEsbuildResolverPlugin(envName, mappings);
|
|
129
146
|
if (esbuildPlugin && mappings) {
|
|
130
147
|
envConfig.optimizeDeps ??= {};
|
|
131
148
|
envConfig.optimizeDeps.esbuildOptions ??= {};
|
|
@@ -141,7 +158,8 @@ export const reactConditionsResolverPlugin = () => {
|
|
|
141
158
|
for (const [find, replacement] of mappings) {
|
|
142
159
|
const findRegex = new RegExp(`^${find.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&")}$`);
|
|
143
160
|
aliases.push({ find: findRegex, replacement });
|
|
144
|
-
|
|
161
|
+
process.env.VERBOSE &&
|
|
162
|
+
log("Added alias for env=%s: %s -> %s", envName, find, replacement);
|
|
145
163
|
}
|
|
146
164
|
log("Environment %s configured with %d aliases and %d optimizeDeps includes", envName, mappings.size, reactImports.length);
|
|
147
165
|
}
|
|
@@ -158,21 +176,21 @@ export const reactConditionsResolverPlugin = () => {
|
|
|
158
176
|
if (!envName) {
|
|
159
177
|
return;
|
|
160
178
|
}
|
|
161
|
-
process.env.VERBOSE &&
|
|
162
|
-
log("Resolving id=%s, environment=%s, importer=%s", id, envName, importer);
|
|
163
179
|
const mappings = ENV_IMPORT_MAPPINGS[envName];
|
|
164
180
|
if (!mappings) {
|
|
165
181
|
process.env.VERBOSE &&
|
|
166
182
|
log("No mappings found for environment: %s", envName);
|
|
167
183
|
return;
|
|
168
184
|
}
|
|
169
|
-
|
|
185
|
+
let resolved = mappings.get(id);
|
|
186
|
+
if (!resolved) {
|
|
187
|
+
resolved = resolveReactImport(id, envName, projectRootDir);
|
|
188
|
+
}
|
|
170
189
|
if (resolved) {
|
|
171
|
-
|
|
190
|
+
process.env.VERBOSE &&
|
|
191
|
+
log("Resolved %s -> %s for env=%s", id, resolved, envName);
|
|
172
192
|
return resolved;
|
|
173
193
|
}
|
|
174
|
-
process.env.VERBOSE &&
|
|
175
|
-
log("No resolution found for id=%s in env=%s", id, envName);
|
|
176
194
|
},
|
|
177
195
|
},
|
|
178
196
|
];
|