@ivogt/rsc-router 0.0.0-experimental.3 → 0.0.0-experimental.5
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 +124 -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,14 @@ 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 also needs esbuild options for version virtual module
|
|
653
|
+
optimizeDeps: {
|
|
654
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
543
655
|
},
|
|
544
656
|
},
|
|
545
657
|
},
|
|
@@ -605,6 +717,7 @@ export async function rscRouter(
|
|
|
605
717
|
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
606
718
|
optimizeDeps: {
|
|
607
719
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
720
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
608
721
|
},
|
|
609
722
|
resolve: {
|
|
610
723
|
alias: {
|
|
@@ -639,6 +752,7 @@ export async function rscRouter(
|
|
|
639
752
|
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
640
753
|
optimizeDeps: {
|
|
641
754
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
755
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
642
756
|
...(useVirtualClient && {
|
|
643
757
|
// Tell Vite to scan the virtual entry for dependencies
|
|
644
758
|
entries: [VIRTUAL_IDS.browser],
|
|
@@ -652,6 +766,7 @@ export async function rscRouter(
|
|
|
652
766
|
// Pre-bundle React for SSR to ensure single instance
|
|
653
767
|
include: ["react", "react-dom/server.edge", "react/jsx-runtime"],
|
|
654
768
|
exclude: RSC_ROUTER_EXCLUDE_DEPS,
|
|
769
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
655
770
|
},
|
|
656
771
|
},
|
|
657
772
|
}),
|
|
@@ -661,6 +776,7 @@ export async function rscRouter(
|
|
|
661
776
|
entries: [VIRTUAL_IDS.rsc],
|
|
662
777
|
// Pre-bundle React for RSC to ensure single instance
|
|
663
778
|
include: ["react", "react/jsx-runtime"],
|
|
779
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
664
780
|
},
|
|
665
781
|
},
|
|
666
782
|
}),
|