rwsdk 0.2.0-alpha.15 → 0.2.0-alpha.16

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.
@@ -0,0 +1,3 @@
1
+ export declare function hasOwnReactVitePlugin({ rootProjectDir, }: {
2
+ rootProjectDir: string;
3
+ }): Promise<boolean>;
@@ -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
+ }
@@ -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 ENV_IMPORT_MAPPINGS: {
14
- [k: string]: Map<string, string>;
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,28 +42,41 @@ export const ENV_RESOLVERS = {
41
42
  conditionNames: ["browser", "default"],
42
43
  }),
43
44
  };
44
- export const ENV_IMPORT_MAPPINGS = Object.fromEntries(Object.keys(ENV_RESOLVERS).map((env) => [
45
- env,
46
- resolveEnvImportMappings(env),
47
- ]));
48
- function resolveEnvImportMappings(env) {
49
- process.env.VERBOSE &&
50
- log("Resolving environment import mappings for env=%s", env);
51
- const mappings = new Map();
52
- const reactImports = ENV_REACT_IMPORTS[env];
53
- for (const importRequest of reactImports) {
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("Resolving import request=%s for env=%s", importRequest, env);
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[env](ROOT_DIR, importRequest);
62
+ resolved = ENV_RESOLVERS[envName](ROOT_DIR, id) || undefined;
59
63
  process.env.VERBOSE &&
60
- log("Successfully resolved %s to %s for env=%s", importRequest, resolved, env);
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", importRequest, env);
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
  log("Added mapping for %s -> %s in env=%s", importRequest, resolved, env);
@@ -71,39 +85,45 @@ function resolveEnvImportMappings(env) {
71
85
  log("Environment import mappings complete for env=%s: %d mappings", env, mappings.size);
72
86
  return mappings;
73
87
  }
74
- function createEsbuildResolverPlugin(envName) {
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 = () => {
88
+ export const reactConditionsResolverPlugin = ({ projectRootDir, }) => {
105
89
  log("Initializing react conditions resolver plugin");
106
90
  let isBuild = false;
91
+ const ENV_IMPORT_MAPPINGS = Object.fromEntries(Object.keys(ENV_RESOLVERS).map((env) => [
92
+ env,
93
+ resolveEnvImportMappings(env, projectRootDir),
94
+ ]));
95
+ function createEsbuildResolverPlugin(envName, mappings) {
96
+ if (!mappings) {
97
+ return null;
98
+ }
99
+ return {
100
+ name: `rwsdk:react-conditions-resolver-esbuild-${envName}`,
101
+ setup(build) {
102
+ build.onResolve({ filter: /.*/ }, (args) => {
103
+ process.env.VERBOSE &&
104
+ log("ESBuild resolving %s for env=%s, args=%O", args.path, envName, args);
105
+ let resolved = mappings.get(args.path);
106
+ if (!resolved) {
107
+ resolved = resolveReactImport(args.path, envName, projectRootDir);
108
+ }
109
+ if (resolved && args.importer !== "") {
110
+ process.env.VERBOSE &&
111
+ log("ESBuild resolving %s -> %s for env=%s", args.path, resolved, envName);
112
+ if (args.path === "react-server-dom-webpack/client.edge") {
113
+ return;
114
+ }
115
+ return {
116
+ path: resolved,
117
+ };
118
+ }
119
+ else {
120
+ process.env.VERBOSE &&
121
+ log("ESBuild no resolution found for %s for env=%s", args.path, envName);
122
+ }
123
+ });
124
+ },
125
+ };
126
+ }
107
127
  return [
108
128
  {
109
129
  name: "rwsdk:react-conditions-resolver:config",
@@ -125,7 +145,7 @@ export const reactConditionsResolverPlugin = () => {
125
145
  config.environments[envName] = {};
126
146
  }
127
147
  const envConfig = config.environments[envName];
128
- const esbuildPlugin = createEsbuildResolverPlugin(envName);
148
+ const esbuildPlugin = createEsbuildResolverPlugin(envName, mappings);
129
149
  if (esbuildPlugin && mappings) {
130
150
  envConfig.optimizeDeps ??= {};
131
151
  envConfig.optimizeDeps.esbuildOptions ??= {};
@@ -166,7 +186,10 @@ export const reactConditionsResolverPlugin = () => {
166
186
  log("No mappings found for environment: %s", envName);
167
187
  return;
168
188
  }
169
- const resolved = mappings.get(id);
189
+ let resolved = mappings.get(id);
190
+ if (!resolved) {
191
+ resolved = resolveReactImport(id, envName, projectRootDir);
192
+ }
170
193
  if (resolved) {
171
194
  log("Resolved %s -> %s for env=%s", id, resolved, envName);
172
195
  return resolved;
@@ -3,6 +3,7 @@ export type RedwoodPluginOptions = {
3
3
  silent?: boolean;
4
4
  rootDir?: string;
5
5
  includeCloudflarePlugin?: boolean;
6
+ includeReactPlugin?: boolean;
6
7
  configPath?: string;
7
8
  entry?: {
8
9
  client?: string | string[];
@@ -3,6 +3,7 @@ import { unstable_readConfig } from "wrangler";
3
3
  import { cloudflare } from "@cloudflare/vite-plugin";
4
4
  import { devServerConstantPlugin } from "./devServerConstant.mjs";
5
5
  import { hasOwnCloudflareVitePlugin } from "./hasOwnCloudflareVitePlugin.mjs";
6
+ import { hasOwnReactVitePlugin } from "./hasOwnReactVitePlugin.mjs";
6
7
  import reactPlugin from "@vitejs/plugin-react";
7
8
  import tsconfigPaths from "vite-tsconfig-paths";
8
9
  import { transformJsxScriptTagsPlugin } from "./transformJsxScriptTagsPlugin.mjs";
@@ -41,6 +42,8 @@ export const redwoodPlugin = async (options = {}) => {
41
42
  const serverFiles = new Set();
42
43
  const shouldIncludeCloudflarePlugin = options.includeCloudflarePlugin ??
43
44
  !(await hasOwnCloudflareVitePlugin({ rootProjectDir: projectRootDir }));
45
+ const shouldIncludeReactPlugin = options.includeReactPlugin ??
46
+ !(await hasOwnReactVitePlugin({ rootProjectDir: projectRootDir }));
44
47
  // context(justinvdm, 31 Mar 2025): We assume that if there is no .wrangler directory,
45
48
  // then this is fresh install, and we run `npm run dev:init` here.
46
49
  if (process.env.RWSDK_WORKER_RUN !== "1" &&
@@ -68,7 +71,7 @@ export const redwoodPlugin = async (options = {}) => {
68
71
  serverFiles,
69
72
  projectRootDir,
70
73
  }),
71
- reactConditionsResolverPlugin(),
74
+ reactConditionsResolverPlugin({ projectRootDir }),
72
75
  tsconfigPaths({ root: projectRootDir }),
73
76
  shouldIncludeCloudflarePlugin
74
77
  ? cloudflare({
@@ -83,7 +86,7 @@ export const redwoodPlugin = async (options = {}) => {
83
86
  viteEnvironment: { name: "worker" },
84
87
  workerEntryPathname,
85
88
  }),
86
- reactPlugin(),
89
+ shouldIncludeReactPlugin ? reactPlugin() : [],
87
90
  directivesPlugin({
88
91
  projectRootDir,
89
92
  clientFiles,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rwsdk",
3
- "version": "0.2.0-alpha.15",
3
+ "version": "0.2.0-alpha.16",
4
4
  "description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
5
5
  "type": "module",
6
6
  "bin": {
@@ -144,10 +144,7 @@
144
144
  "picocolors": "^1.1.1",
145
145
  "proper-lockfile": "^4.1.2",
146
146
  "puppeteer-core": "^22.8.1",
147
- "react": "19.2.0-canary-39cad7af-20250411",
148
- "react-dom": "19.2.0-canary-39cad7af-20250411",
149
147
  "react-is": "^19.0.0",
150
- "react-server-dom-webpack": "19.2.0-canary-39cad7af-20250411",
151
148
  "rsc-html-stream": "^0.0.6",
152
149
  "tmp-promise": "^3.0.3",
153
150
  "ts-morph": "^25.0.1",
@@ -157,7 +154,26 @@
157
154
  "wrangler": "^4.20.5"
158
155
  },
159
156
  "peerDependencies": {
160
- "vite": "^6.2.6"
157
+ "vite": "^6.2.6",
158
+ "react": ">=19.2.0-0 <20",
159
+ "react-dom": ">=19.2.0-0 <20",
160
+ "react-server-dom-webpack": ">=19.2.0-0 <20"
161
+ },
162
+ "optionalDependencies": {
163
+ "react": "19.2.0-canary-39cad7af-20250411",
164
+ "react-dom": "19.2.0-canary-39cad7af-20250411",
165
+ "react-server-dom-webpack": "19.2.0-canary-39cad7af-20250411"
166
+ },
167
+ "peerDependenciesMeta": {
168
+ "react": {
169
+ "optional": true
170
+ },
171
+ "react-dom": {
172
+ "optional": true
173
+ },
174
+ "react-server-dom-webpack": {
175
+ "optional": true
176
+ }
161
177
  },
162
178
  "packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab",
163
179
  "devDependencies": {