@reckona/mreact-router 0.0.207 → 0.0.209
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 +2 -2
- package/dist/adapters/cloudflare.d.ts +3 -3
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +11 -4
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/boundaries.d.ts +37 -1
- package/dist/boundaries.d.ts.map +1 -1
- package/dist/boundaries.js +125 -4
- package/dist/boundaries.js.map +1 -1
- package/dist/build.d.ts +6 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +269 -24
- package/dist/build.js.map +1 -1
- package/dist/bundle-pipeline.d.ts +1 -0
- package/dist/bundle-pipeline.d.ts.map +1 -1
- package/dist/bundle-pipeline.js +4 -1
- package/dist/bundle-pipeline.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +67 -7
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/module-runner.js +9 -1
- package/dist/module-runner.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +23 -23
- package/dist/render.js.map +1 -1
- package/dist/request-header-tracking.d.ts +19 -0
- package/dist/request-header-tracking.d.ts.map +1 -1
- package/dist/request-header-tracking.js +48 -0
- package/dist/request-header-tracking.js.map +1 -1
- package/dist/tailwind-source.d.ts.map +1 -1
- package/dist/tailwind-source.js +147 -1
- package/dist/tailwind-source.js.map +1 -1
- package/dist/types.d.ts +14 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +4 -0
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/cloudflare.ts +14 -5
- package/src/boundaries.ts +224 -4
- package/src/build.ts +383 -24
- package/src/bundle-pipeline.ts +9 -4
- package/src/client.ts +104 -10
- package/src/config.ts +32 -0
- package/src/index.ts +10 -0
- package/src/module-runner.ts +9 -1
- package/src/render.ts +30 -16
- package/src/request-header-tracking.ts +61 -0
- package/src/tailwind-source.ts +164 -1
- package/src/types.ts +15 -2
- package/src/vite.ts +5 -0
package/dist/build.js
CHANGED
|
@@ -5,10 +5,11 @@ import { builtinModules } from "node:module";
|
|
|
5
5
|
import { availableParallelism } from "node:os";
|
|
6
6
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { gzipSync } from "node:zlib";
|
|
8
9
|
import { collectStaticImportReferences, collectTopLevelValueExportNames, formatDiagnostic, hasModuleDirective, transform, } from "@reckona/mreact-compiler";
|
|
9
10
|
import { transformCompilerModuleContext } from "@reckona/mreact-compiler/internal";
|
|
10
11
|
import { compilerModuleContextForSource, collectClientRouteReferences, createClientRouteInferenceCache, detectAnchorElementUsage, detectClientNavigationOverride, formatClientRouteInferenceDiagnostic, inferClientRouteModule, navigationRuntimeLinkDisabledDiagnostic, resolveNavigationRuntime, } from "./client-route-inference.js";
|
|
11
|
-
import { createBoundaryReport } from "./boundaries.js";
|
|
12
|
+
import { createBoundaryReport, validateBoundaryExecutionContracts, } from "./boundaries.js";
|
|
12
13
|
import { buildClientRouteBatchOutput, buildNavigationRuntimeBundle, clientScriptForPath, routeIdForPath, routeMarkerParts, } from "./navigation-runtime.js";
|
|
13
14
|
import { COMPAT_VENDOR_PLACEHOLDER_PREFIX, bundleAppRouterSourceModule, fileImportMetaUrlPlugin, importAppRouterSourceModule, resolveCompatVendorEntryFiles, sourceReferencesCompatVendorSpecifier, } from "./module-runner.js";
|
|
14
15
|
import { dehydrateOptionsFromModule } from "./dehydrate-policy.js";
|
|
@@ -127,7 +128,7 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
127
128
|
routes,
|
|
128
129
|
vitePlugins,
|
|
129
130
|
}));
|
|
130
|
-
|
|
131
|
+
validateBoundaryExecutionContracts(sourceAnalysis.boundaryReport, project.executionContracts);
|
|
131
132
|
if (shouldTrackBuildPhases === false) {
|
|
132
133
|
await validateProductionRoutes({
|
|
133
134
|
clientRouteInferenceCache: serverClientRouteInferenceCache,
|
|
@@ -158,6 +159,15 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
158
159
|
fingerprint: incrementalBuildFingerprint,
|
|
159
160
|
outDir: options.outDir,
|
|
160
161
|
}))) {
|
|
162
|
+
if (options.onBoundaryReport !== undefined) {
|
|
163
|
+
const clientManifest = await readJsonBuildOutput(join(options.outDir, "client", "manifest.json"));
|
|
164
|
+
options.onBoundaryReport(await boundaryReportWithArtifactCosts({
|
|
165
|
+
boundaryCost: options.boundaryCost,
|
|
166
|
+
clientDir,
|
|
167
|
+
manifest: clientManifest,
|
|
168
|
+
report: sourceAnalysis.boundaryReport,
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
161
171
|
return { routes };
|
|
162
172
|
}
|
|
163
173
|
if (shouldTrackBuildPhases === false) {
|
|
@@ -404,6 +414,7 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
404
414
|
};
|
|
405
415
|
const clientManifest = {
|
|
406
416
|
...(clientManifestAssets.length === 0 ? {} : { assets: clientManifestAssets }),
|
|
417
|
+
...(clientBundle.chunks.length === 0 ? {} : { chunks: clientBundle.chunks }),
|
|
407
418
|
...(publicAssets.length === 0 ? {} : { publicAssets }),
|
|
408
419
|
routes: clientManifestRoutes,
|
|
409
420
|
...(clientBundle.styles.length === 0 ? {} : { styles: clientBundle.styles }),
|
|
@@ -467,8 +478,216 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
467
478
|
if (incrementalBuildFingerprint !== undefined) {
|
|
468
479
|
await writeIncrementalBuildCacheManifest(options.outDir, incrementalBuildFingerprint);
|
|
469
480
|
}
|
|
481
|
+
if (options.onBoundaryReport !== undefined) {
|
|
482
|
+
options.onBoundaryReport(await boundaryReportWithArtifactCosts({
|
|
483
|
+
boundaryCost: options.boundaryCost,
|
|
484
|
+
clientDir,
|
|
485
|
+
manifest: clientManifest,
|
|
486
|
+
report: sourceAnalysis.boundaryReport,
|
|
487
|
+
}));
|
|
488
|
+
}
|
|
470
489
|
return { routes };
|
|
471
490
|
}
|
|
491
|
+
async function boundaryReportWithArtifactCosts(options) {
|
|
492
|
+
if (options.manifest === undefined) {
|
|
493
|
+
return {
|
|
494
|
+
...options.report,
|
|
495
|
+
routes: options.report.routes.map((route) => ({
|
|
496
|
+
...route,
|
|
497
|
+
cost: {
|
|
498
|
+
reason: "Production client manifest is unavailable.",
|
|
499
|
+
status: "unavailable",
|
|
500
|
+
},
|
|
501
|
+
})),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
const manifest = options.manifest;
|
|
505
|
+
const chunks = new Map((manifest.chunks ?? []).map((chunk) => [chunk.file, chunk]));
|
|
506
|
+
const routeClosures = options.report.routes.map((route) => {
|
|
507
|
+
const manifestRoute = manifest.routes.find((candidate) => candidate.path === route.path);
|
|
508
|
+
if (manifestRoute === undefined) {
|
|
509
|
+
return { initial: undefined, navigation: undefined, route };
|
|
510
|
+
}
|
|
511
|
+
const initial = clientArtifactStaticClosure(manifestRoute, chunks);
|
|
512
|
+
const navigation = new Set(initial);
|
|
513
|
+
addFetchedDynamicImportClosures({
|
|
514
|
+
chunks,
|
|
515
|
+
fetchedDynamicImports: options.boundaryCost?.fetchedDynamicImports?.[route.path] ?? [],
|
|
516
|
+
navigation,
|
|
517
|
+
routeDynamicImports: manifestRoute.dynamicImports ?? [],
|
|
518
|
+
});
|
|
519
|
+
return { initial, navigation, route };
|
|
520
|
+
});
|
|
521
|
+
const availableClosures = routeClosures.flatMap((entry) => entry.initial === undefined ? [] : [entry.initial]);
|
|
522
|
+
const sharedPaths = intersectionOfPathSets(availableClosures);
|
|
523
|
+
const allPaths = new Set();
|
|
524
|
+
for (const entry of routeClosures) {
|
|
525
|
+
for (const path of entry.navigation ?? []) {
|
|
526
|
+
allPaths.add(path);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
const measurements = await measureClientArtifactPaths(options.clientDir, allPaths);
|
|
530
|
+
return {
|
|
531
|
+
...options.report,
|
|
532
|
+
routes: routeClosures.map((entry) => {
|
|
533
|
+
if (entry.initial === undefined || entry.navigation === undefined) {
|
|
534
|
+
return {
|
|
535
|
+
...entry.route,
|
|
536
|
+
cost: {
|
|
537
|
+
reason: "No client route artifact was generated for this route.",
|
|
538
|
+
status: "unavailable",
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
const routePaths = new Set(entry.navigation);
|
|
543
|
+
const unavailable = [...routePaths]
|
|
544
|
+
.filter((path) => measurements.get(path)?.available !== true)
|
|
545
|
+
.sort();
|
|
546
|
+
if (unavailable.length > 0) {
|
|
547
|
+
return {
|
|
548
|
+
...entry.route,
|
|
549
|
+
cost: {
|
|
550
|
+
reason: `Missing client artifacts: ${unavailable.join(", ")}.`,
|
|
551
|
+
status: "unavailable",
|
|
552
|
+
},
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
const initial = byteCostForPaths(entry.initial, measurements);
|
|
556
|
+
const navigation = byteCostForPaths(new Set([...entry.navigation].filter((path) => !sharedPaths.has(path))), measurements);
|
|
557
|
+
const shared = byteCostForPaths(sharedPaths, measurements);
|
|
558
|
+
return {
|
|
559
|
+
...entry.route,
|
|
560
|
+
cost: {
|
|
561
|
+
baseline: {
|
|
562
|
+
initialGzipDeltaBytes: initial.gzipEstimateBytes - shared.gzipEstimateBytes,
|
|
563
|
+
navigationGzipDeltaBytes: navigation.gzipEstimateBytes,
|
|
564
|
+
},
|
|
565
|
+
initial,
|
|
566
|
+
navigation,
|
|
567
|
+
status: "available",
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
}),
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function clientArtifactStaticClosure(route, chunks) {
|
|
574
|
+
const paths = new Set();
|
|
575
|
+
for (const path of route.css ?? []) {
|
|
576
|
+
paths.add(path);
|
|
577
|
+
}
|
|
578
|
+
if (route.navigation === true && route.navigationScript !== undefined) {
|
|
579
|
+
paths.add(route.navigationScript);
|
|
580
|
+
}
|
|
581
|
+
for (const path of route.imports ?? []) {
|
|
582
|
+
addClientArtifactStaticClosure(paths, path, chunks);
|
|
583
|
+
}
|
|
584
|
+
if (route.script !== undefined) {
|
|
585
|
+
addClientArtifactStaticClosure(paths, route.script, chunks);
|
|
586
|
+
}
|
|
587
|
+
return paths;
|
|
588
|
+
}
|
|
589
|
+
function addFetchedDynamicImportClosures(options) {
|
|
590
|
+
const fetchedDynamicImports = new Set(options.fetchedDynamicImports);
|
|
591
|
+
const acceptedDynamicImports = new Set();
|
|
592
|
+
const reachableDynamicImports = new Set(options.routeDynamicImports);
|
|
593
|
+
for (;;) {
|
|
594
|
+
for (const dynamicImport of dynamicImportsReachableFromStaticClosure(options.navigation, options.chunks)) {
|
|
595
|
+
reachableDynamicImports.add(dynamicImport);
|
|
596
|
+
}
|
|
597
|
+
let added = false;
|
|
598
|
+
for (const dynamicImport of fetchedDynamicImports) {
|
|
599
|
+
if (acceptedDynamicImports.has(dynamicImport) ||
|
|
600
|
+
!reachableDynamicImports.has(dynamicImport) ||
|
|
601
|
+
!options.chunks.has(dynamicImport)) {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
acceptedDynamicImports.add(dynamicImport);
|
|
605
|
+
addClientArtifactStaticClosure(options.navigation, dynamicImport, options.chunks);
|
|
606
|
+
added = true;
|
|
607
|
+
}
|
|
608
|
+
if (!added) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function dynamicImportsReachableFromStaticClosure(paths, chunks) {
|
|
614
|
+
const pending = [...paths];
|
|
615
|
+
const visited = new Set();
|
|
616
|
+
const dynamicImports = new Set();
|
|
617
|
+
while (pending.length > 0) {
|
|
618
|
+
const path = pending.pop();
|
|
619
|
+
if (path === undefined || visited.has(path)) {
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
visited.add(path);
|
|
623
|
+
const chunk = chunks.get(path);
|
|
624
|
+
if (chunk === undefined) {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
for (const imported of chunk.imports ?? []) {
|
|
628
|
+
pending.push(imported);
|
|
629
|
+
}
|
|
630
|
+
for (const dynamicImport of chunk.dynamicImports ?? []) {
|
|
631
|
+
dynamicImports.add(dynamicImport);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return dynamicImports;
|
|
635
|
+
}
|
|
636
|
+
function addClientArtifactStaticClosure(paths, path, chunks) {
|
|
637
|
+
if (path === "" || paths.has(path)) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
paths.add(path);
|
|
641
|
+
for (const imported of chunks.get(path)?.imports ?? []) {
|
|
642
|
+
addClientArtifactStaticClosure(paths, imported, chunks);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function intersectionOfPathSets(sets) {
|
|
646
|
+
const [first, ...rest] = sets;
|
|
647
|
+
if (first === undefined || sets.length < 2) {
|
|
648
|
+
return new Set();
|
|
649
|
+
}
|
|
650
|
+
return new Set([...first].filter((path) => rest.every((set) => set.has(path))));
|
|
651
|
+
}
|
|
652
|
+
async function measureClientArtifactPaths(clientDir, paths) {
|
|
653
|
+
const measurements = await Promise.all([...paths].map(async (path) => {
|
|
654
|
+
const absolutePath = safeClientArtifactPath(clientDir, path);
|
|
655
|
+
if (absolutePath === undefined) {
|
|
656
|
+
return [path, { available: false }];
|
|
657
|
+
}
|
|
658
|
+
try {
|
|
659
|
+
const content = await readFile(absolutePath);
|
|
660
|
+
return [
|
|
661
|
+
path,
|
|
662
|
+
{
|
|
663
|
+
available: true,
|
|
664
|
+
gzipEstimateBytes: gzipSync(content).byteLength,
|
|
665
|
+
rawBytes: content.byteLength,
|
|
666
|
+
},
|
|
667
|
+
];
|
|
668
|
+
}
|
|
669
|
+
catch {
|
|
670
|
+
return [path, { available: false }];
|
|
671
|
+
}
|
|
672
|
+
}));
|
|
673
|
+
return new Map(measurements);
|
|
674
|
+
}
|
|
675
|
+
function safeClientArtifactPath(clientDir, path) {
|
|
676
|
+
const absolutePath = resolve(clientDir, path);
|
|
677
|
+
const relativePath = relative(resolve(clientDir), absolutePath);
|
|
678
|
+
return relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep}`)
|
|
679
|
+
? undefined
|
|
680
|
+
: absolutePath;
|
|
681
|
+
}
|
|
682
|
+
function byteCostForPaths(paths, measurements) {
|
|
683
|
+
return [...paths].reduce((cost, path) => {
|
|
684
|
+
const measurement = measurements.get(path);
|
|
685
|
+
return {
|
|
686
|
+
gzipEstimateBytes: cost.gzipEstimateBytes + (measurement?.gzipEstimateBytes ?? 0),
|
|
687
|
+
rawBytes: cost.rawBytes + (measurement?.rawBytes ?? 0),
|
|
688
|
+
};
|
|
689
|
+
}, { gzipEstimateBytes: 0, rawBytes: 0 });
|
|
690
|
+
}
|
|
472
691
|
const incrementalBuildCacheFilename = "build-cache.json";
|
|
473
692
|
const incrementalBuildCacheVersion = 2;
|
|
474
693
|
async function createIncrementalBuildCacheFingerprint(options) {
|
|
@@ -584,6 +803,11 @@ function collectClientManifestOutputFiles(manifest) {
|
|
|
584
803
|
files.add(asset);
|
|
585
804
|
files.add(`public/${asset}`);
|
|
586
805
|
}
|
|
806
|
+
for (const chunk of manifest.chunks ?? []) {
|
|
807
|
+
for (const file of [chunk.file, ...(chunk.imports ?? []), ...(chunk.dynamicImports ?? [])]) {
|
|
808
|
+
files.add(file);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
587
811
|
for (const route of manifest.routes) {
|
|
588
812
|
for (const file of [
|
|
589
813
|
route.script,
|
|
@@ -591,6 +815,7 @@ function collectClientManifestOutputFiles(manifest) {
|
|
|
591
815
|
route.navigationScript,
|
|
592
816
|
...(route.css ?? []),
|
|
593
817
|
...(route.imports ?? []),
|
|
818
|
+
...(route.dynamicImports ?? []),
|
|
594
819
|
]) {
|
|
595
820
|
if (file !== undefined) {
|
|
596
821
|
files.add(file);
|
|
@@ -855,6 +1080,7 @@ async function analyzeBuildRouteSources(options) {
|
|
|
855
1080
|
diagnostics: analysis.diagnostics,
|
|
856
1081
|
entry: analysis.route.file,
|
|
857
1082
|
path: analysis.route.path,
|
|
1083
|
+
source: analysis.source,
|
|
858
1084
|
})),
|
|
859
1085
|
}),
|
|
860
1086
|
byFile,
|
|
@@ -2605,14 +2831,14 @@ const componentGenerateMetadata = readComponentModuleExport(componentModule, "ge
|
|
|
2605
2831
|
const componentMetadata = readComponentModuleExport(componentModule, "metadata");
|
|
2606
2832
|
const componentSecurityHeadersApplied = readComponentModuleExport(componentModule, "__mreactSecurityHeadersApplied");
|
|
2607
2833
|
|
|
2608
|
-
export function App(props) {
|
|
2609
|
-
return renderCloudflareRouteComponent(props);
|
|
2834
|
+
export function App(props, request) {
|
|
2835
|
+
return renderCloudflareRouteComponent(props, request);
|
|
2610
2836
|
}
|
|
2611
|
-
export default function CloudflareDefaultRouteComponent(props) {
|
|
2612
|
-
return renderCloudflareRouteComponent(props);
|
|
2837
|
+
export default function CloudflareDefaultRouteComponent(props, request) {
|
|
2838
|
+
return renderCloudflareRouteComponent(props, request);
|
|
2613
2839
|
}
|
|
2614
|
-
export function CloudflareRouteComponent(props) {
|
|
2615
|
-
return renderCloudflareRouteComponent(props);
|
|
2840
|
+
export function CloudflareRouteComponent(props, request) {
|
|
2841
|
+
return renderCloudflareRouteComponent(props, request);
|
|
2616
2842
|
}
|
|
2617
2843
|
export const slots = componentSlots === undefined ? undefined : { ...componentSlots };
|
|
2618
2844
|
export const generateMetadata =
|
|
@@ -2620,13 +2846,13 @@ export const generateMetadata =
|
|
|
2620
2846
|
export const metadata = componentMetadata;
|
|
2621
2847
|
export const __mreactSecurityHeadersApplied = componentSecurityHeadersApplied === true;
|
|
2622
2848
|
|
|
2623
|
-
function renderCloudflareRouteComponent(props) {
|
|
2849
|
+
function renderCloudflareRouteComponent(props, request) {
|
|
2624
2850
|
const routeComponent = resolveCloudflareRouteComponent();
|
|
2625
2851
|
if (routeComponent === undefined) {
|
|
2626
2852
|
throw new Error("No Cloudflare component export was found for ${componentImport}.");
|
|
2627
2853
|
}
|
|
2628
2854
|
|
|
2629
|
-
return routeComponent(props);
|
|
2855
|
+
return routeComponent(props, request);
|
|
2630
2856
|
}
|
|
2631
2857
|
|
|
2632
2858
|
function resolveCloudflareRouteComponent() {
|
|
@@ -2881,14 +3107,14 @@ ${shellModules.join("\n")}
|
|
|
2881
3107
|
const pageComponent = selectComponent(pageModule, ${JSON.stringify(options.filename)});
|
|
2882
3108
|
const shells = [${shellDefinitions.join(", ")}];
|
|
2883
3109
|
export const slots = pageModule.slots;
|
|
2884
|
-
export default function CloudflareStringRouteComponent(props) {
|
|
2885
|
-
return renderCloudflareStringRoute(props);
|
|
3110
|
+
export default function CloudflareStringRouteComponent(props, request) {
|
|
3111
|
+
return renderCloudflareStringRoute(props, request);
|
|
2886
3112
|
}
|
|
2887
3113
|
|
|
2888
|
-
async function renderCloudflareStringRoute(props) {
|
|
3114
|
+
async function renderCloudflareStringRoute(props, request) {
|
|
2889
3115
|
const slotHtml = await renderRouteSlots(pageModule.slots, props);
|
|
2890
3116
|
const layoutShells = await renderLayoutShells(shells, props, slotHtml);
|
|
2891
|
-
const metadata = await resolveRouteMetadata([...shells.map((shell) => shell.module), pageModule], props);
|
|
3117
|
+
const metadata = await resolveRouteMetadata([...shells.map((shell) => shell.module), pageModule], { ...props, request });
|
|
2892
3118
|
let html = "<!DOCTYPE html>";
|
|
2893
3119
|
for (const shell of layoutShells) {
|
|
2894
3120
|
html += shell.prefix;
|
|
@@ -2899,7 +3125,7 @@ async function renderCloudflareStringRoute(props) {
|
|
|
2899
3125
|
}
|
|
2900
3126
|
html = injectCloudflareHead(html, metadata, cloudflareRouteHeadTags(props.clientManifest, props.route.path));
|
|
2901
3127
|
return new Response(html, {
|
|
2902
|
-
headers: cloudflareMetadataHeaders(metadata,
|
|
3128
|
+
headers: cloudflareMetadataHeaders(metadata, request, {
|
|
2903
3129
|
"content-type": "text/html; charset=utf-8"
|
|
2904
3130
|
})
|
|
2905
3131
|
});
|
|
@@ -3021,14 +3247,14 @@ ${shellImports.join("\n")}
|
|
|
3021
3247
|
const pageComponent = selectComponent(pageModule, ${JSON.stringify(options.filename)});
|
|
3022
3248
|
const shells = [${shellDefinitions.join(", ")}];
|
|
3023
3249
|
export const slots = pageModule.slots;
|
|
3024
|
-
export default function CloudflareStringRouteComponent(props) {
|
|
3025
|
-
return renderCloudflareStringRoute(props);
|
|
3250
|
+
export default function CloudflareStringRouteComponent(props, request) {
|
|
3251
|
+
return renderCloudflareStringRoute(props, request);
|
|
3026
3252
|
}
|
|
3027
3253
|
|
|
3028
|
-
async function renderCloudflareStringRoute(props) {
|
|
3254
|
+
async function renderCloudflareStringRoute(props, request) {
|
|
3029
3255
|
const slotHtml = await renderRouteSlots(pageModule.slots, props);
|
|
3030
3256
|
const layoutShells = await renderLayoutShells(shells, props, slotHtml);
|
|
3031
|
-
const metadata = await resolveRouteMetadata([...shells.map((shell) => shell.module), pageModule], props);
|
|
3257
|
+
const metadata = await resolveRouteMetadata([...shells.map((shell) => shell.module), pageModule], { ...props, request });
|
|
3032
3258
|
let html = "<!DOCTYPE html>";
|
|
3033
3259
|
for (const shell of layoutShells) {
|
|
3034
3260
|
html += shell.prefix;
|
|
@@ -3039,7 +3265,7 @@ async function renderCloudflareStringRoute(props) {
|
|
|
3039
3265
|
}
|
|
3040
3266
|
html = injectCloudflareHead(html, metadata, cloudflareRouteHeadTags(props.clientManifest, props.route.path));
|
|
3041
3267
|
return new Response(html, {
|
|
3042
|
-
headers: cloudflareMetadataHeaders(metadata,
|
|
3268
|
+
headers: cloudflareMetadataHeaders(metadata, request, {
|
|
3043
3269
|
"content-type": "text/html; charset=utf-8"
|
|
3044
3270
|
})
|
|
3045
3271
|
});
|
|
@@ -3114,8 +3340,8 @@ export const slots = pageModule.slots;
|
|
|
3114
3340
|
export const App = renderCloudflareStreamRoute;
|
|
3115
3341
|
export default renderCloudflareStreamRoute;
|
|
3116
3342
|
|
|
3117
|
-
async function renderCloudflareStreamRoute(props) {
|
|
3118
|
-
const metadata = await resolveRouteMetadata([...shells.map((shell) => shell.module), pageModule], props);
|
|
3343
|
+
async function renderCloudflareStreamRoute(props, request) {
|
|
3344
|
+
const metadata = await resolveRouteMetadata([...shells.map((shell) => shell.module), pageModule], { ...props, request });
|
|
3119
3345
|
const body = renderToReadableStream(async ($sink) => {
|
|
3120
3346
|
const slotHtml = await renderRouteSlots(pageModule.slots, props);
|
|
3121
3347
|
const layoutShells = await renderLayoutShells(shells, props, slotHtml);
|
|
@@ -3138,7 +3364,7 @@ async function renderCloudflareStreamRoute(props) {
|
|
|
3138
3364
|
}
|
|
3139
3365
|
});
|
|
3140
3366
|
return new Response(body, {
|
|
3141
|
-
headers: cloudflareMetadataHeaders(metadata,
|
|
3367
|
+
headers: cloudflareMetadataHeaders(metadata, request, {
|
|
3142
3368
|
"content-type": "text/html; charset=utf-8",
|
|
3143
3369
|
"x-mreact-stream": "1"
|
|
3144
3370
|
})
|
|
@@ -3267,9 +3493,15 @@ function cloudflareHydrationMarkerParts(props) {
|
|
|
3267
3493
|
}
|
|
3268
3494
|
const routeId = route.routeId ?? cloudflareRouteIdForPath(props.route.path);
|
|
3269
3495
|
const escapedRouteId = escapeHtmlAttribute(routeId);
|
|
3496
|
+
const requestUrl = new URL(props.request.url);
|
|
3270
3497
|
const propsJson = escapeScriptJson(JSON.stringify({
|
|
3271
3498
|
params: props.params,
|
|
3272
|
-
request: {
|
|
3499
|
+
request: {
|
|
3500
|
+
hash: "",
|
|
3501
|
+
pathname: requestUrl.pathname,
|
|
3502
|
+
search: "",
|
|
3503
|
+
url: requestUrl.pathname,
|
|
3504
|
+
},
|
|
3273
3505
|
data: props.data,
|
|
3274
3506
|
}));
|
|
3275
3507
|
const clientReferencesJson = route.clientReferenceManifest === undefined || route.clientReferenceManifest.length === 0
|
|
@@ -4367,6 +4599,10 @@ function cloudflareWorkspaceRuntimePlugin() {
|
|
|
4367
4599
|
"@reckona/mreact-shared/html-escape",
|
|
4368
4600
|
packageFile("shared", "@reckona/mreact-shared", "html-escape"),
|
|
4369
4601
|
],
|
|
4602
|
+
[
|
|
4603
|
+
"@reckona/mreact-shared/server-render-value-internal",
|
|
4604
|
+
packageFile("shared", "@reckona/mreact-shared", "server-render-value-internal"),
|
|
4605
|
+
],
|
|
4370
4606
|
]);
|
|
4371
4607
|
return {
|
|
4372
4608
|
name: "mreact-cloudflare-workspace-runtime",
|
|
@@ -4545,6 +4781,7 @@ async function writeClientRouteBundles(options) {
|
|
|
4545
4781
|
if (clientEntries.length === 0) {
|
|
4546
4782
|
return {
|
|
4547
4783
|
assets: [...routeCssAssets.assets, ...specialCssAssets.assets].sort(),
|
|
4784
|
+
chunks: [],
|
|
4548
4785
|
routes: entries.flatMap((entry) => ("manifest" in entry ? [entry.manifest] : [])),
|
|
4549
4786
|
styles: specialCssAssets.styles,
|
|
4550
4787
|
};
|
|
@@ -4628,6 +4865,9 @@ async function writeClientRouteBundles(options) {
|
|
|
4628
4865
|
? {}
|
|
4629
4866
|
: { clientReferenceManifest: entry.build.clientReferenceManifest }),
|
|
4630
4867
|
...(entry.css.length === 0 ? {} : { css: entry.css }),
|
|
4868
|
+
...(routeOutput.chunk.dynamicImports.length === 0
|
|
4869
|
+
? {}
|
|
4870
|
+
: { dynamicImports: routeOutput.chunk.dynamicImports }),
|
|
4631
4871
|
...(routeOutput.chunk.imports.length === 0 ? {} : { imports: routeOutput.chunk.imports }),
|
|
4632
4872
|
...(navigation ? { navigation } : {}),
|
|
4633
4873
|
routeId,
|
|
@@ -4638,6 +4878,11 @@ async function writeClientRouteBundles(options) {
|
|
|
4638
4878
|
});
|
|
4639
4879
|
return {
|
|
4640
4880
|
assets: Array.from(generatedAssets).sort(),
|
|
4881
|
+
chunks: output.chunks.map((chunk) => ({
|
|
4882
|
+
...(chunk.dynamicImports.length === 0 ? {} : { dynamicImports: chunk.dynamicImports }),
|
|
4883
|
+
file: chunk.fileName,
|
|
4884
|
+
...(chunk.imports.length === 0 ? {} : { imports: chunk.imports }),
|
|
4885
|
+
})),
|
|
4641
4886
|
routes,
|
|
4642
4887
|
styles: specialCssAssets.styles,
|
|
4643
4888
|
};
|