@reckona/mreact-router 0.0.55 → 0.0.57
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/README.md +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +10 -0
- package/dist/build.js.map +1 -1
- package/dist/client.d.ts +9 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +233 -20
- package/dist/client.js.map +1 -1
- package/dist/render.d.ts +4 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +48 -5
- package/dist/render.js.map +1 -1
- package/dist/vite.d.ts +3 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +10 -2
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
package/dist/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import { builtinModules } from "node:module";
|
|
4
|
-
import { dirname, join, relative, sep } from "node:path";
|
|
4
|
+
import { dirname, extname, join, relative, sep } from "node:path";
|
|
5
5
|
import { collectClientRouteModuleAnalysis, formatDiagnostic, } from "@reckona/mreact-compiler";
|
|
6
6
|
import { collectClientRouteModuleAnalysisFromContext, createCompilerModuleContext, transformCompilerModuleContext, } from "@reckona/mreact-compiler/internal";
|
|
7
7
|
import { assetPath } from "./assets.js";
|
|
@@ -40,6 +40,7 @@ export function createClientRouteInferenceCache() {
|
|
|
40
40
|
moduleContextByFile: new Map(),
|
|
41
41
|
resolvedByImport: new Map(),
|
|
42
42
|
sourceByFile: new Map(),
|
|
43
|
+
transformedSourceByFile: new Map(),
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
export async function isClientRouteModule(options) {
|
|
@@ -47,14 +48,21 @@ export async function isClientRouteModule(options) {
|
|
|
47
48
|
}
|
|
48
49
|
export async function inferClientRouteModule(options) {
|
|
49
50
|
const cache = options.cache ?? createClientRouteInferenceCache();
|
|
51
|
+
const sourceTransform = clientRouteSourceTransformForVitePlugins(options.vitePlugins);
|
|
52
|
+
const code = await transformClientRouteSource({
|
|
53
|
+
code: options.code,
|
|
54
|
+
filename: options.filename,
|
|
55
|
+
sourceTransform,
|
|
56
|
+
});
|
|
50
57
|
try {
|
|
51
58
|
const routeInference = await inferClientRouteModuleSource({
|
|
52
59
|
cache,
|
|
53
|
-
code
|
|
60
|
+
code,
|
|
54
61
|
filename: options.filename,
|
|
55
|
-
moduleContext: options.moduleContext,
|
|
62
|
+
...(sourceTransform === undefined ? { moduleContext: options.moduleContext } : {}),
|
|
56
63
|
root: true,
|
|
57
64
|
seen: new Set(),
|
|
65
|
+
sourceTransform,
|
|
58
66
|
});
|
|
59
67
|
if (options.appDir === undefined) {
|
|
60
68
|
return routeInference;
|
|
@@ -63,6 +71,7 @@ export async function inferClientRouteModule(options) {
|
|
|
63
71
|
appDir: options.appDir,
|
|
64
72
|
cache,
|
|
65
73
|
filename: options.filename,
|
|
74
|
+
sourceTransform,
|
|
66
75
|
});
|
|
67
76
|
return {
|
|
68
77
|
client: routeInference.client || shellInferences.some((inference) => inference.client),
|
|
@@ -79,18 +88,25 @@ export async function inferClientRouteModule(options) {
|
|
|
79
88
|
}
|
|
80
89
|
export async function collectClientRouteReferences(options) {
|
|
81
90
|
const cache = options.cache ?? createClientRouteInferenceCache();
|
|
91
|
+
const sourceTransform = clientRouteSourceTransformForVitePlugins(options.vitePlugins);
|
|
92
|
+
const code = await transformClientRouteSource({
|
|
93
|
+
code: options.code,
|
|
94
|
+
filename: options.filename,
|
|
95
|
+
sourceTransform,
|
|
96
|
+
});
|
|
82
97
|
const routeModuleContext = await compilerModuleContextForSource({
|
|
83
98
|
cache,
|
|
84
|
-
code
|
|
99
|
+
code,
|
|
85
100
|
filename: options.filename,
|
|
86
101
|
});
|
|
87
102
|
const routeInference = await inferClientRouteModuleSource({
|
|
88
103
|
cache,
|
|
89
|
-
code
|
|
104
|
+
code,
|
|
90
105
|
filename: options.filename,
|
|
91
106
|
moduleContext: routeModuleContext,
|
|
92
107
|
root: true,
|
|
93
108
|
seen: new Set(),
|
|
109
|
+
sourceTransform,
|
|
94
110
|
});
|
|
95
111
|
const sources = [];
|
|
96
112
|
const seenSourceFiles = new Set();
|
|
@@ -113,6 +129,7 @@ export async function collectClientRouteReferences(options) {
|
|
|
113
129
|
moduleContext,
|
|
114
130
|
root: true,
|
|
115
131
|
seen: new Set(),
|
|
132
|
+
sourceTransform,
|
|
116
133
|
}));
|
|
117
134
|
sources.push({
|
|
118
135
|
code: sourceOptions.code,
|
|
@@ -121,19 +138,19 @@ export async function collectClientRouteReferences(options) {
|
|
|
121
138
|
moduleContext,
|
|
122
139
|
});
|
|
123
140
|
for (const referenceFile of inference.clientReferenceSourceFiles) {
|
|
124
|
-
const code = stripRouteClientOnlyExports(await
|
|
141
|
+
const code = stripRouteClientOnlyExports(await readClientRouteSource({ cache, filename: referenceFile, sourceTransform }));
|
|
125
142
|
await addSource({ code, filename: referenceFile });
|
|
126
143
|
}
|
|
127
144
|
};
|
|
128
145
|
await addSource({
|
|
129
|
-
code
|
|
146
|
+
code,
|
|
130
147
|
filename: options.filename,
|
|
131
148
|
inference: routeInference,
|
|
132
149
|
moduleContext: routeModuleContext,
|
|
133
150
|
});
|
|
134
151
|
if (options.appDir !== undefined) {
|
|
135
152
|
for (const shell of await clientShellFilesForPage(options.appDir, options.filename)) {
|
|
136
|
-
const code = stripRouteClientOnlyExports(await
|
|
153
|
+
const code = stripRouteClientOnlyExports(await readClientRouteSource({ cache, filename: shell, sourceTransform }));
|
|
137
154
|
const moduleContext = await compilerModuleContextForSource({
|
|
138
155
|
cache,
|
|
139
156
|
code,
|
|
@@ -149,6 +166,7 @@ export async function collectClientRouteReferences(options) {
|
|
|
149
166
|
moduleContext,
|
|
150
167
|
root: true,
|
|
151
168
|
seen: new Set(),
|
|
169
|
+
sourceTransform,
|
|
152
170
|
}),
|
|
153
171
|
moduleContext,
|
|
154
172
|
});
|
|
@@ -202,13 +220,18 @@ export async function collectClientRouteReferences(options) {
|
|
|
202
220
|
}
|
|
203
221
|
async function inferClientRouteShellModules(options) {
|
|
204
222
|
return Promise.all((await clientShellFilesForPage(options.appDir, options.filename)).map(async (shell) => {
|
|
205
|
-
const code = stripRouteClientOnlyExports(await
|
|
223
|
+
const code = stripRouteClientOnlyExports(await readClientRouteSource({
|
|
224
|
+
cache: options.cache,
|
|
225
|
+
filename: shell,
|
|
226
|
+
sourceTransform: options.sourceTransform,
|
|
227
|
+
}));
|
|
206
228
|
return await inferClientRouteModuleSource({
|
|
207
229
|
cache: options.cache,
|
|
208
230
|
code,
|
|
209
231
|
filename: shell,
|
|
210
232
|
root: true,
|
|
211
233
|
seen: new Set(),
|
|
234
|
+
sourceTransform: options.sourceTransform,
|
|
212
235
|
});
|
|
213
236
|
}));
|
|
214
237
|
}
|
|
@@ -232,7 +255,7 @@ function isExplicitClientRouteSource(analysis, filename) {
|
|
|
232
255
|
return analysis.hasUseClientDirective || isClientBoundaryFilename(filename);
|
|
233
256
|
}
|
|
234
257
|
function isClientBoundaryFilename(filename) {
|
|
235
|
-
return /\.client(?:\.mreact)?\.[cm]?[jt]sx?$/.test(filename);
|
|
258
|
+
return /\.(?:client|compat)(?:\.mreact)?\.[cm]?[jt]sx?$/.test(filename);
|
|
236
259
|
}
|
|
237
260
|
function isServerOnlyClientRouteSource(analysis) {
|
|
238
261
|
return analysis.hasUseServerDirective;
|
|
@@ -296,7 +319,11 @@ async function inferClientRouteModuleSource(options) {
|
|
|
296
319
|
(!referenced || !hasPotentialClientBoundaryReference(reference, identifierReferences))) {
|
|
297
320
|
continue;
|
|
298
321
|
}
|
|
322
|
+
if (reference.sideEffect && isStyleModuleSpecifier(reference.source)) {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
299
325
|
const resolved = await resolveAppLocalModule({
|
|
326
|
+
allowExplicitNonSource: options.sourceTransform !== undefined,
|
|
300
327
|
cache: options.cache,
|
|
301
328
|
importer: options.filename,
|
|
302
329
|
specifier: reference.source,
|
|
@@ -304,7 +331,11 @@ async function inferClientRouteModuleSource(options) {
|
|
|
304
331
|
if (resolved === undefined) {
|
|
305
332
|
continue;
|
|
306
333
|
}
|
|
307
|
-
const source = await
|
|
334
|
+
const source = await readClientRouteSource({
|
|
335
|
+
cache: options.cache,
|
|
336
|
+
filename: resolved,
|
|
337
|
+
sourceTransform: options.sourceTransform,
|
|
338
|
+
});
|
|
308
339
|
const imported = await inferClientRouteModuleSource({
|
|
309
340
|
cache: options.cache,
|
|
310
341
|
code: source,
|
|
@@ -316,6 +347,7 @@ async function inferClientRouteModuleSource(options) {
|
|
|
316
347
|
}),
|
|
317
348
|
root: false,
|
|
318
349
|
seen: options.seen,
|
|
350
|
+
sourceTransform: options.sourceTransform,
|
|
319
351
|
});
|
|
320
352
|
diagnostics.push(...imported.diagnostics);
|
|
321
353
|
if (!imported.client) {
|
|
@@ -364,6 +396,7 @@ async function inferClientRouteModuleSource(options) {
|
|
|
364
396
|
if (!options.root) {
|
|
365
397
|
for (const reference of analysis.staticExports) {
|
|
366
398
|
const resolved = await resolveAppLocalModule({
|
|
399
|
+
allowExplicitNonSource: options.sourceTransform !== undefined,
|
|
367
400
|
cache: options.cache,
|
|
368
401
|
importer: options.filename,
|
|
369
402
|
specifier: reference.source,
|
|
@@ -371,7 +404,11 @@ async function inferClientRouteModuleSource(options) {
|
|
|
371
404
|
if (resolved === undefined) {
|
|
372
405
|
continue;
|
|
373
406
|
}
|
|
374
|
-
const source = await
|
|
407
|
+
const source = await readClientRouteSource({
|
|
408
|
+
cache: options.cache,
|
|
409
|
+
filename: resolved,
|
|
410
|
+
sourceTransform: options.sourceTransform,
|
|
411
|
+
});
|
|
375
412
|
const exported = await inferClientRouteModuleSource({
|
|
376
413
|
cache: options.cache,
|
|
377
414
|
code: source,
|
|
@@ -383,6 +420,7 @@ async function inferClientRouteModuleSource(options) {
|
|
|
383
420
|
}),
|
|
384
421
|
root: false,
|
|
385
422
|
seen: options.seen,
|
|
423
|
+
sourceTransform: options.sourceTransform,
|
|
386
424
|
});
|
|
387
425
|
diagnostics.push(...exported.diagnostics);
|
|
388
426
|
if (exported.clientBoundaryModule) {
|
|
@@ -481,6 +519,18 @@ function hasPotentialClientBoundaryReference(reference, identifierReferences) {
|
|
|
481
519
|
reference.specifiers.some((specifier) => specifier.kind === "namespace" && identifierReferences.has(specifier.localName)) ||
|
|
482
520
|
reference.localNames.some((localName) => identifierReferences.has(localName) && startsUppercase(localName)));
|
|
483
521
|
}
|
|
522
|
+
function isStyleModuleSpecifier(source) {
|
|
523
|
+
const pathname = source.split(/[?#]/u, 1)[0] ?? source;
|
|
524
|
+
return styleModuleExtensions.has(extname(pathname));
|
|
525
|
+
}
|
|
526
|
+
const styleModuleExtensions = new Set([
|
|
527
|
+
".css",
|
|
528
|
+
".less",
|
|
529
|
+
".sass",
|
|
530
|
+
".scss",
|
|
531
|
+
".styl",
|
|
532
|
+
".stylus",
|
|
533
|
+
]);
|
|
484
534
|
function renderedImportedExportNames(reference, componentRoots) {
|
|
485
535
|
if (reference.sideEffect) {
|
|
486
536
|
return undefined;
|
|
@@ -562,19 +612,27 @@ async function resolveAppLocalModule(options) {
|
|
|
562
612
|
if (!options.specifier.startsWith(".")) {
|
|
563
613
|
return undefined;
|
|
564
614
|
}
|
|
565
|
-
const cacheKey = `${options.importer}\0${options.specifier}`;
|
|
615
|
+
const cacheKey = `${options.importer}\0${options.specifier}\0${options.allowExplicitNonSource === true ? "explicit" : "source"}`;
|
|
566
616
|
const cached = options.cache.resolvedByImport.get(cacheKey);
|
|
567
617
|
if (cached !== undefined) {
|
|
568
618
|
return cached;
|
|
569
619
|
}
|
|
570
|
-
const resolved = resolveAppLocalModuleUncached(
|
|
620
|
+
const resolved = resolveAppLocalModuleUncached({
|
|
621
|
+
allowExplicitNonSource: options.allowExplicitNonSource === true,
|
|
622
|
+
importer: options.importer,
|
|
623
|
+
specifier: options.specifier,
|
|
624
|
+
});
|
|
571
625
|
options.cache.resolvedByImport.set(cacheKey, resolved);
|
|
572
626
|
return resolved;
|
|
573
627
|
}
|
|
574
|
-
async function resolveAppLocalModuleUncached(
|
|
628
|
+
async function resolveAppLocalModuleUncached(options) {
|
|
629
|
+
const { importer, specifier } = options;
|
|
575
630
|
const base = join(dirname(importer), specifier);
|
|
576
631
|
const candidates = sourceModuleCandidates(base);
|
|
577
632
|
if (candidates.length === 0) {
|
|
633
|
+
if (options.allowExplicitNonSource && extname(base) !== "" && (await isFile(base))) {
|
|
634
|
+
return base;
|
|
635
|
+
}
|
|
578
636
|
return undefined;
|
|
579
637
|
}
|
|
580
638
|
for (const candidate of candidates) {
|
|
@@ -608,6 +666,126 @@ async function readCachedFile(cache, filename) {
|
|
|
608
666
|
cache.sourceByFile.set(filename, source);
|
|
609
667
|
return (await source).source;
|
|
610
668
|
}
|
|
669
|
+
async function readClientRouteSource(options) {
|
|
670
|
+
if (options.sourceTransform === undefined) {
|
|
671
|
+
return readCachedFile(options.cache, options.filename);
|
|
672
|
+
}
|
|
673
|
+
const signature = await sourceFileSignature(options.filename);
|
|
674
|
+
const cacheKey = `${options.filename}\0${options.sourceTransform.cacheKey}`;
|
|
675
|
+
const cached = options.cache.transformedSourceByFile.get(cacheKey);
|
|
676
|
+
if (cached !== undefined) {
|
|
677
|
+
const source = await cached;
|
|
678
|
+
if (source.signature === signature) {
|
|
679
|
+
return source.source;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
const source = readCachedFile(options.cache, options.filename).then(async (code) => ({
|
|
683
|
+
signature,
|
|
684
|
+
source: await options.sourceTransform.transform(options.filename, code),
|
|
685
|
+
}));
|
|
686
|
+
options.cache.transformedSourceByFile.set(cacheKey, source);
|
|
687
|
+
return (await source).source;
|
|
688
|
+
}
|
|
689
|
+
async function transformClientRouteSource(options) {
|
|
690
|
+
return options.sourceTransform === undefined
|
|
691
|
+
? options.code
|
|
692
|
+
: await options.sourceTransform.transform(options.filename, options.code);
|
|
693
|
+
}
|
|
694
|
+
function clientRouteSourceTransformForVitePlugins(pluginOptions) {
|
|
695
|
+
const plugins = orderVitePlugins(flattenVitePlugins(pluginOptions)).filter((plugin) => hasViteTransformHook(plugin));
|
|
696
|
+
if (plugins.length === 0) {
|
|
697
|
+
return undefined;
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
cacheKey: plugins.map((plugin, index) => `${index}:${plugin.name}`).join("\0"),
|
|
701
|
+
async transform(filename, code) {
|
|
702
|
+
let nextCode = code;
|
|
703
|
+
for (const plugin of plugins) {
|
|
704
|
+
const handler = viteTransformHookHandler(plugin);
|
|
705
|
+
if (handler === undefined) {
|
|
706
|
+
continue;
|
|
707
|
+
}
|
|
708
|
+
const result = await handler.call(createClientRouteViteTransformContext(plugin.name), nextCode, filename, { ssr: false });
|
|
709
|
+
if (typeof result === "string") {
|
|
710
|
+
nextCode = result;
|
|
711
|
+
}
|
|
712
|
+
else if (result !== null && result !== undefined && typeof result === "object") {
|
|
713
|
+
const codeResult = result.code;
|
|
714
|
+
if (typeof codeResult === "string") {
|
|
715
|
+
nextCode = codeResult;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return nextCode;
|
|
720
|
+
},
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
function flattenVitePlugins(pluginOptions) {
|
|
724
|
+
const plugins = [];
|
|
725
|
+
const visit = (option) => {
|
|
726
|
+
if (option === false || option === null || option === undefined) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
if (Array.isArray(option)) {
|
|
730
|
+
for (const child of option) {
|
|
731
|
+
visit(child);
|
|
732
|
+
}
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (typeof option === "object" && "then" in option) {
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
plugins.push(option);
|
|
739
|
+
};
|
|
740
|
+
for (const option of pluginOptions ?? []) {
|
|
741
|
+
visit(option);
|
|
742
|
+
}
|
|
743
|
+
return plugins;
|
|
744
|
+
}
|
|
745
|
+
function orderVitePlugins(plugins) {
|
|
746
|
+
return [
|
|
747
|
+
...plugins.filter((plugin) => plugin.enforce === "pre"),
|
|
748
|
+
...plugins.filter((plugin) => plugin.enforce !== "pre" && plugin.enforce !== "post"),
|
|
749
|
+
...plugins.filter((plugin) => plugin.enforce === "post"),
|
|
750
|
+
];
|
|
751
|
+
}
|
|
752
|
+
function hasViteTransformHook(plugin) {
|
|
753
|
+
return viteTransformHookHandler(plugin) !== undefined;
|
|
754
|
+
}
|
|
755
|
+
function viteTransformHookHandler(plugin) {
|
|
756
|
+
const transform = plugin.transform;
|
|
757
|
+
if (typeof transform === "function") {
|
|
758
|
+
return transform;
|
|
759
|
+
}
|
|
760
|
+
if (transform !== null && typeof transform === "object") {
|
|
761
|
+
const handler = transform.handler;
|
|
762
|
+
if (typeof handler === "function") {
|
|
763
|
+
return handler;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return undefined;
|
|
767
|
+
}
|
|
768
|
+
function createClientRouteViteTransformContext(pluginName) {
|
|
769
|
+
return {
|
|
770
|
+
addWatchFile() { },
|
|
771
|
+
async resolve() {
|
|
772
|
+
return null;
|
|
773
|
+
},
|
|
774
|
+
error(error) {
|
|
775
|
+
if (error instanceof Error) {
|
|
776
|
+
throw error;
|
|
777
|
+
}
|
|
778
|
+
throw new Error(String(error));
|
|
779
|
+
},
|
|
780
|
+
warn() { },
|
|
781
|
+
getCombinedSourcemap() {
|
|
782
|
+
return null;
|
|
783
|
+
},
|
|
784
|
+
parse() {
|
|
785
|
+
throw new Error(`${pluginName}: client route import analysis cannot provide Rollup parser context.`);
|
|
786
|
+
},
|
|
787
|
+
};
|
|
788
|
+
}
|
|
611
789
|
async function sourceFileSignature(filename) {
|
|
612
790
|
const stats = await stat(filename);
|
|
613
791
|
return `${stats.mtimeMs}\0${stats.size}`;
|
|
@@ -685,6 +863,7 @@ export async function buildClientRouteOutput(options) {
|
|
|
685
863
|
});
|
|
686
864
|
const compiled = transformCompilerModuleContext({
|
|
687
865
|
code: options.code,
|
|
866
|
+
clientBoundaryImports: options.clientBoundaryImports ?? [],
|
|
688
867
|
filename: options.filename,
|
|
689
868
|
moduleContext,
|
|
690
869
|
target: "client",
|
|
@@ -697,8 +876,9 @@ export async function buildClientRouteOutput(options) {
|
|
|
697
876
|
}
|
|
698
877
|
const clientNavigation = options.clientNavigation ?? detectClientNavigationHint(options.code);
|
|
699
878
|
const clientReferenceManifest = options.clientReferenceManifest ?? (await inferClientReferenceManifestForBundle(options));
|
|
879
|
+
const compatClientReferenceNames = compatClientReferenceComponentNames(clientReferenceManifest);
|
|
700
880
|
const clientReferenceImportBlock = emitClientReferenceImportBlock(options.clientReferenceImports ?? []);
|
|
701
|
-
const clientReferenceRegistry = emitClientReferenceRegistry(clientReferenceManifest, options.clientReferenceImports ?? []);
|
|
881
|
+
const clientReferenceRegistry = emitClientReferenceRegistry(clientReferenceManifest, options.clientReferenceImports ?? [], compatClientReferenceNames);
|
|
702
882
|
const routeComponentExpression = routeComponentExpressionForComponents(compiled.metadata.components);
|
|
703
883
|
const routeId = routeIdForPath(options.routePath);
|
|
704
884
|
const routeUsesCells = detectRouteCellStateHint(compiled.code);
|
|
@@ -892,7 +1072,7 @@ ${routeCellHydrationIndent}}
|
|
|
892
1072
|
${routeCellHydrationIndent} return;
|
|
893
1073
|
${routeCellHydrationIndent}}
|
|
894
1074
|
`;
|
|
895
|
-
const entry = `${routeCellEffectImport}${routeCleanupScopeImport}${clientReferenceImportBlock}${routeHydrationCode}
|
|
1075
|
+
const entry = `${routeCellEffectImport}${routeCleanupScopeImport}${emitCompatClientReferenceImportBlock(compatClientReferenceNames)}${clientReferenceImportBlock}${routeHydrationCode}
|
|
896
1076
|
|
|
897
1077
|
const __mreactRouteId = ${JSON.stringify(routeId)};
|
|
898
1078
|
const __mreactRouteStateSignature = ${JSON.stringify(routeStateSignature)};
|
|
@@ -924,6 +1104,7 @@ export function __mreactHydrateRoute() {
|
|
|
924
1104
|
}
|
|
925
1105
|
${routeCellHydrationStart}${routeCleanupHydrationStart}${boundaryOnlyHydrationBlock}${routeComponentGuard}${routeCellHydrationIndent}const __mreactNode = ${routeNodeExpression};
|
|
926
1106
|
${routeCellHydrationIndent}__mreactResumeRoute(__mreactMarker, __mreactNode);
|
|
1107
|
+
${routeCellHydrationIndent}__mreactHydrateClientBoundaries(__mreactMarker, __mreactClientReferences, __mreactClientReferenceComponents);
|
|
927
1108
|
${routeCellHydrationIndent}__mreactMarker.setAttribute("data-mreact-hydrated", "true");
|
|
928
1109
|
${routeCellHydrationEnd}}
|
|
929
1110
|
${routeCellDropFunction}
|
|
@@ -1798,7 +1979,9 @@ function __mreactHydrateClientBoundaries(marker, references, components) {
|
|
|
1798
1979
|
|
|
1799
1980
|
for (const placeholder of placeholders) {
|
|
1800
1981
|
const name = placeholder.getAttribute("data-mreact-client-boundary");
|
|
1801
|
-
const
|
|
1982
|
+
const entry = name === null ? undefined : components.get(name);
|
|
1983
|
+
const component = typeof entry === "function" ? entry : entry?.component;
|
|
1984
|
+
const compat = entry?.compat === true;
|
|
1802
1985
|
|
|
1803
1986
|
if (typeof component !== "function") {
|
|
1804
1987
|
return false;
|
|
@@ -1808,6 +1991,17 @@ function __mreactHydrateClientBoundaries(marker, references, components) {
|
|
|
1808
1991
|
const props = propsElement?.textContent === undefined || propsElement.textContent === ""
|
|
1809
1992
|
? {}
|
|
1810
1993
|
: JSON.parse(propsElement.textContent);
|
|
1994
|
+
|
|
1995
|
+
if (compat) {
|
|
1996
|
+
const container = document.createElement("span");
|
|
1997
|
+
container.setAttribute("data-mreact-compat-boundary", name ?? "");
|
|
1998
|
+
container.style.display = "contents";
|
|
1999
|
+
placeholder.replaceWith(container);
|
|
2000
|
+
__mreactCompatCreateRoot(container).render(__mreactCompatCreateElement(component, props));
|
|
2001
|
+
propsElement?.remove();
|
|
2002
|
+
continue;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
1811
2005
|
const node = component(props);
|
|
1812
2006
|
|
|
1813
2007
|
placeholder.replaceWith(node);
|
|
@@ -2230,6 +2424,7 @@ function __mreactResumeChildren(current, next) {
|
|
|
2230
2424
|
preserveExports: true,
|
|
2231
2425
|
plugins: [workspaceRuntimePlugin({ routeFile: options.filename })],
|
|
2232
2426
|
sourceMap: options.sourceMap,
|
|
2427
|
+
vitePlugins: options.vitePlugins,
|
|
2233
2428
|
});
|
|
2234
2429
|
return {
|
|
2235
2430
|
code: bundled.code,
|
|
@@ -2325,6 +2520,7 @@ export function currentDevtoolsEmitter() { return undefined; }`,
|
|
|
2325
2520
|
code: source,
|
|
2326
2521
|
dev: true,
|
|
2327
2522
|
filename: args.path,
|
|
2523
|
+
mode: isCompatSourcePath(args.path) ? "compat" : "reactive",
|
|
2328
2524
|
moduleContext,
|
|
2329
2525
|
target: "client",
|
|
2330
2526
|
});
|
|
@@ -2345,6 +2541,9 @@ export function currentDevtoolsEmitter() { return undefined; }`,
|
|
|
2345
2541
|
function isRouteClientDependencySourcePath(path, routeFile) {
|
|
2346
2542
|
return path !== routeFile && !path.includes(`${sep}node_modules${sep}`);
|
|
2347
2543
|
}
|
|
2544
|
+
function isCompatSourcePath(path) {
|
|
2545
|
+
return /\.compat(?:\.mreact)?(?:\.[cm]?[jt]sx?)?$/.test(path);
|
|
2546
|
+
}
|
|
2348
2547
|
/**
|
|
2349
2548
|
* Detects the `export const clientNavigation = false` hint in a page module
|
|
2350
2549
|
* source. Returns the hinted value, or `true` when no hint is present (i.e.,
|
|
@@ -2414,7 +2613,7 @@ function emitClientReferenceImportBlock(imports) {
|
|
|
2414
2613
|
})
|
|
2415
2614
|
.join("\n")}\n`;
|
|
2416
2615
|
}
|
|
2417
|
-
function emitClientReferenceRegistry(manifest, imports) {
|
|
2616
|
+
function emitClientReferenceRegistry(manifest, imports, compatNames) {
|
|
2418
2617
|
const importedExpressions = new Map(imports.map((reference, index) => [
|
|
2419
2618
|
reference.name,
|
|
2420
2619
|
isIdentifierName(reference.exportName)
|
|
@@ -2425,10 +2624,24 @@ function emitClientReferenceRegistry(manifest, imports) {
|
|
|
2425
2624
|
const expression = importedExpressions.get(reference.name) ?? clientReferenceExpression(reference.name);
|
|
2426
2625
|
return expression === undefined
|
|
2427
2626
|
? []
|
|
2428
|
-
: [
|
|
2627
|
+
: [
|
|
2628
|
+
compatNames.has(reference.name)
|
|
2629
|
+
? ` [${JSON.stringify(reference.name)}, { component: ${expression}, compat: true }],`
|
|
2630
|
+
: ` [${JSON.stringify(reference.name)}, ${expression}],`,
|
|
2631
|
+
];
|
|
2429
2632
|
});
|
|
2430
2633
|
return ["const __mreactClientReferenceComponents = new Map([", ...entries, "]);"].join("\n");
|
|
2431
2634
|
}
|
|
2635
|
+
function compatClientReferenceComponentNames(manifest) {
|
|
2636
|
+
return new Set(manifest
|
|
2637
|
+
.filter((reference) => isCompatSourcePath(reference.moduleId))
|
|
2638
|
+
.map((reference) => reference.name));
|
|
2639
|
+
}
|
|
2640
|
+
function emitCompatClientReferenceImportBlock(compatNames) {
|
|
2641
|
+
return compatNames.size === 0
|
|
2642
|
+
? ""
|
|
2643
|
+
: 'import { createElement as __mreactCompatCreateElement, createRoot as __mreactCompatCreateRoot } from "@reckona/mreact-compat";\n';
|
|
2644
|
+
}
|
|
2432
2645
|
function clientReferenceLocalName(index) {
|
|
2433
2646
|
return `__mreactClientReference${index}`;
|
|
2434
2647
|
}
|