@ivogt/rsc-router 0.0.0-experimental.3 → 0.0.0-experimental.6
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/package.json +1 -1
- package/src/vite/index.ts +126 -8
package/package.json
CHANGED
package/src/vite/index.ts
CHANGED
|
@@ -37,33 +37,80 @@ export { exposeLocationStateId } from "./expose-location-state-id.ts";
|
|
|
37
37
|
* exists in the tree.
|
|
38
38
|
*
|
|
39
39
|
* By excluding these modules, we ensure a single module instance is used everywhere.
|
|
40
|
+
*
|
|
41
|
+
* We include both the scoped package name (@ivogt/rsc-router) and the aliased paths
|
|
42
|
+
* (rsc-router) because Vite's optimizer runs before alias resolution.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* esbuild plugin to provide rsc-router:version virtual module during optimization.
|
|
46
|
+
* This is needed because esbuild runs during Vite's dependency optimization phase,
|
|
47
|
+
* before Vite's plugin system can handle virtual modules.
|
|
40
48
|
*/
|
|
49
|
+
const versionEsbuildPlugin = {
|
|
50
|
+
name: "rsc-router-version",
|
|
51
|
+
setup(build: any) {
|
|
52
|
+
build.onResolve({ filter: /^rsc-router:version$/ }, (args: any) => ({
|
|
53
|
+
path: args.path,
|
|
54
|
+
namespace: "rsc-router-virtual",
|
|
55
|
+
}));
|
|
56
|
+
build.onLoad({ filter: /.*/, namespace: "rsc-router-virtual" }, () => ({
|
|
57
|
+
contents: `export const VERSION = "dev";`,
|
|
58
|
+
loader: "js",
|
|
59
|
+
}));
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Shared esbuild options for dependency optimization.
|
|
65
|
+
* Includes the version stub plugin for all environments.
|
|
66
|
+
*/
|
|
67
|
+
const sharedEsbuildOptions = {
|
|
68
|
+
plugins: [versionEsbuildPlugin],
|
|
69
|
+
};
|
|
70
|
+
|
|
41
71
|
const RSC_ROUTER_EXCLUDE_DEPS = [
|
|
72
|
+
// Scoped package paths
|
|
42
73
|
"@ivogt/rsc-router",
|
|
43
74
|
"@ivogt/rsc-router/browser",
|
|
44
75
|
"@ivogt/rsc-router/client",
|
|
76
|
+
"@ivogt/rsc-router/server",
|
|
77
|
+
"@ivogt/rsc-router/rsc",
|
|
78
|
+
"@ivogt/rsc-router/ssr",
|
|
45
79
|
"@ivogt/rsc-router/internal/deps/browser",
|
|
46
80
|
"@ivogt/rsc-router/internal/deps/html-stream-client",
|
|
81
|
+
"@ivogt/rsc-router/internal/deps/ssr",
|
|
82
|
+
"@ivogt/rsc-router/internal/deps/rsc",
|
|
83
|
+
// Aliased paths (before alias resolution)
|
|
84
|
+
"rsc-router/browser",
|
|
85
|
+
"rsc-router/client",
|
|
86
|
+
"rsc-router/server",
|
|
87
|
+
"rsc-router/rsc",
|
|
88
|
+
"rsc-router/ssr",
|
|
89
|
+
"rsc-router/internal/deps/browser",
|
|
90
|
+
"rsc-router/internal/deps/html-stream-client",
|
|
91
|
+
"rsc-router/internal/deps/ssr",
|
|
92
|
+
"rsc-router/internal/deps/rsc",
|
|
47
93
|
];
|
|
48
94
|
|
|
49
95
|
/**
|
|
50
|
-
* Plugin to transform CJS react-server-dom vendor
|
|
96
|
+
* Plugin to transform CJS react-server-dom vendor files to ESM.
|
|
51
97
|
* The @vitejs/plugin-rsc package ships client.browser.js as CommonJS
|
|
52
|
-
* which doesn't work in the browser. This transforms
|
|
98
|
+
* which doesn't work in the browser. This transforms both:
|
|
99
|
+
* 1. The entry point (client.browser.js) to re-export from the CJS file
|
|
100
|
+
* 2. The actual CJS file content to ESM syntax
|
|
53
101
|
*/
|
|
54
102
|
function createCjsToEsmPlugin(): Plugin {
|
|
55
103
|
return {
|
|
56
104
|
name: "rsc-router:cjs-to-esm",
|
|
57
105
|
enforce: "pre",
|
|
58
106
|
transform(code, id) {
|
|
59
|
-
|
|
60
|
-
|
|
107
|
+
const cleanId = id.split("?")[0];
|
|
108
|
+
|
|
109
|
+
// Transform the client.browser.js entry point to re-export from CJS
|
|
61
110
|
if (
|
|
62
|
-
|
|
63
|
-
|
|
111
|
+
cleanId.includes("vendor/react-server-dom/client.browser.js") ||
|
|
112
|
+
cleanId.includes("vendor\\react-server-dom\\client.browser.js")
|
|
64
113
|
) {
|
|
65
|
-
// The original file uses: module.exports = require('./cjs/...')
|
|
66
|
-
// Transform to ESM re-export from the development or production CJS file
|
|
67
114
|
const isProd = process.env.NODE_ENV === "production";
|
|
68
115
|
const cjsFile = isProd
|
|
69
116
|
? "./cjs/react-server-dom-webpack-client.browser.production.js"
|
|
@@ -74,6 +121,60 @@ function createCjsToEsmPlugin(): Plugin {
|
|
|
74
121
|
map: null,
|
|
75
122
|
};
|
|
76
123
|
}
|
|
124
|
+
|
|
125
|
+
// Transform the actual CJS files to ESM
|
|
126
|
+
if (
|
|
127
|
+
(cleanId.includes("vendor/react-server-dom/cjs/") ||
|
|
128
|
+
cleanId.includes("vendor\\react-server-dom\\cjs\\")) &&
|
|
129
|
+
cleanId.includes("client.browser")
|
|
130
|
+
) {
|
|
131
|
+
let transformed = code;
|
|
132
|
+
|
|
133
|
+
// Extract the license comment to preserve it
|
|
134
|
+
const licenseMatch = transformed.match(/^\/\*\*[\s\S]*?\*\//);
|
|
135
|
+
const license = licenseMatch ? licenseMatch[0] : "";
|
|
136
|
+
if (license) {
|
|
137
|
+
transformed = transformed.slice(license.length);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Remove "use strict" and the conditional IIFE wrapper
|
|
141
|
+
// Pattern: "use strict"; "production" !== process.env.NODE_ENV && (function() { ... })();
|
|
142
|
+
transformed = transformed.replace(
|
|
143
|
+
/^\s*["']use strict["'];\s*["']production["']\s*!==\s*process\.env\.NODE_ENV\s*&&\s*\(function\s*\(\)\s*\{/,
|
|
144
|
+
""
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
// Remove the closing of the conditional IIFE at the end: })();
|
|
148
|
+
transformed = transformed.replace(/\}\)\(\);?\s*$/, "");
|
|
149
|
+
|
|
150
|
+
// Replace require('react') and require('react-dom') with imports
|
|
151
|
+
// The pattern spans multiple lines with whitespace
|
|
152
|
+
transformed = transformed.replace(
|
|
153
|
+
/var\s+React\s*=\s*require\s*\(\s*["']react["']\s*\)\s*,[\s\n]+ReactDOM\s*=\s*require\s*\(\s*["']react-dom["']\s*\)\s*,/g,
|
|
154
|
+
'import React from "react";\nimport ReactDOM from "react-dom";\nvar '
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Transform exports.xyz = function() to export function xyz()
|
|
158
|
+
transformed = transformed.replace(
|
|
159
|
+
/exports\.(\w+)\s*=\s*function\s*\(/g,
|
|
160
|
+
"export function $1("
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Transform exports.xyz = value to export const xyz = value
|
|
164
|
+
transformed = transformed.replace(
|
|
165
|
+
/exports\.(\w+)\s*=/g,
|
|
166
|
+
"export const $1 ="
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Reconstruct with license at the top
|
|
170
|
+
transformed = license + "\n" + transformed;
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
code: transformed,
|
|
174
|
+
map: null,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
77
178
|
return null;
|
|
78
179
|
},
|
|
79
180
|
};
|
|
@@ -484,6 +585,7 @@ export async function rscRouter(
|
|
|
484
585
|
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
485
586
|
optimizeDeps: {
|
|
486
587
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
588
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
487
589
|
},
|
|
488
590
|
resolve: {
|
|
489
591
|
alias: {
|
|
@@ -520,6 +622,7 @@ export async function rscRouter(
|
|
|
520
622
|
optimizeDeps: {
|
|
521
623
|
include: ["rsc-html-stream/client"],
|
|
522
624
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
625
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
523
626
|
},
|
|
524
627
|
},
|
|
525
628
|
ssr: {
|
|
@@ -532,6 +635,7 @@ export async function rscRouter(
|
|
|
532
635
|
dedupe: ["react", "react-dom"],
|
|
533
636
|
},
|
|
534
637
|
// Pre-bundle SSR entry and React for proper module linking with childEnvironments
|
|
638
|
+
// Exclude rsc-router modules to ensure same Context instance
|
|
535
639
|
optimizeDeps: {
|
|
536
640
|
entries: [finalEntries.ssr],
|
|
537
641
|
include: [
|
|
@@ -540,6 +644,16 @@ export async function rscRouter(
|
|
|
540
644
|
"react/jsx-runtime",
|
|
541
645
|
"rsc-html-stream/server",
|
|
542
646
|
],
|
|
647
|
+
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
648
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
rsc: {
|
|
652
|
+
// RSC environment needs exclude list and esbuild options
|
|
653
|
+
// Exclude rsc-router modules to prevent createContext in RSC environment
|
|
654
|
+
optimizeDeps: {
|
|
655
|
+
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
656
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
543
657
|
},
|
|
544
658
|
},
|
|
545
659
|
},
|
|
@@ -605,6 +719,7 @@ export async function rscRouter(
|
|
|
605
719
|
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
606
720
|
optimizeDeps: {
|
|
607
721
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
722
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
608
723
|
},
|
|
609
724
|
resolve: {
|
|
610
725
|
alias: {
|
|
@@ -639,6 +754,7 @@ export async function rscRouter(
|
|
|
639
754
|
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
640
755
|
optimizeDeps: {
|
|
641
756
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
757
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
642
758
|
...(useVirtualClient && {
|
|
643
759
|
// Tell Vite to scan the virtual entry for dependencies
|
|
644
760
|
entries: [VIRTUAL_IDS.browser],
|
|
@@ -652,6 +768,7 @@ export async function rscRouter(
|
|
|
652
768
|
// Pre-bundle React for SSR to ensure single instance
|
|
653
769
|
include: ["react", "react-dom/server.edge", "react/jsx-runtime"],
|
|
654
770
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
771
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
655
772
|
},
|
|
656
773
|
},
|
|
657
774
|
}),
|
|
@@ -661,6 +778,7 @@ export async function rscRouter(
|
|
|
661
778
|
entries: [VIRTUAL_IDS.rsc],
|
|
662
779
|
// Pre-bundle React for RSC to ensure single instance
|
|
663
780
|
include: ["react", "react/jsx-runtime"],
|
|
781
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
664
782
|
},
|
|
665
783
|
},
|
|
666
784
|
}),
|