@reckona/mreact-router 0.0.188 → 0.0.190
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 +16 -3
- package/bin/mreact-router.js +23 -0
- package/dist/adapters/aws-lambda.d.ts +33 -13
- package/dist/adapters/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +128 -20
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/adapters/cloudflare.d.ts +18 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/edge.d.ts +2 -0
- package/dist/adapters/edge.d.ts.map +1 -1
- package/dist/adapters/edge.js.map +1 -1
- package/dist/adapters/node.d.ts +16 -2
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js.map +1 -1
- package/dist/cache.d.ts +8 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +34 -13
- package/dist/cache.js.map +1 -1
- package/dist/cli-options.d.ts +1 -1
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +21 -3
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +19 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/link.d.ts +22 -1
- package/dist/link.d.ts.map +1 -1
- package/dist/link.js +130 -5
- package/dist/link.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +514 -517
- package/dist/render.js.map +1 -1
- package/dist/request.d.ts +10 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +6 -0
- package/dist/request.js.map +1 -0
- package/dist/typed-routes.d.ts +4 -5
- package/dist/typed-routes.d.ts.map +1 -1
- package/dist/typed-routes.js.map +1 -1
- package/dist/vite.d.ts +6 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +4 -1
- package/dist/vite.js.map +1 -1
- package/package.json +19 -13
- package/src/adapters/aws-lambda.ts +227 -56
- package/src/adapters/cloudflare.ts +59 -0
- package/src/adapters/edge.ts +14 -0
- package/src/adapters/node.ts +44 -2
- package/src/cache.ts +39 -17
- package/src/cli-options.ts +28 -6
- package/src/client.ts +2 -1
- package/src/config.ts +10 -2
- package/src/index.ts +56 -10
- package/src/link.ts +205 -10
- package/src/render.ts +5 -7
- package/src/request.ts +35 -0
- package/src/typed-routes.ts +4 -4
- package/src/vite.ts +30 -1
package/dist/render.js
CHANGED
|
@@ -13,7 +13,7 @@ import { matchRoute, scanAppRoutes } from "./routes.js";
|
|
|
13
13
|
import { appFileConventionContentType } from "./file-conventions.js";
|
|
14
14
|
import { dispatchServerActionRequest, prepareRouteServerActionPlaceholders, prepareRouteServerActions, } from "./actions.js";
|
|
15
15
|
import { serverActionCookie } from "./csrf.js";
|
|
16
|
-
import {
|
|
16
|
+
import { activeRouteCacheContext, withRouteCacheContext, cachedRouteResponse, cacheRouteResponse, routeCacheKey, routeCachePolicyFromSource, } from "./cache.js";
|
|
17
17
|
import { resolveRouterCacheLimit } from "./cache-config.js";
|
|
18
18
|
import { importAppRouterBuiltFileModule, importAppRouterFileModule, importAppRouterSourceModule, fileImportMetaUrlPlugin, rewriteCompatVendorPlaceholderImportsForRunner, } from "./module-runner.js";
|
|
19
19
|
import { bytesResponse, htmlResponse } from "./http.js";
|
|
@@ -489,335 +489,430 @@ async function renderAppRequestInternal(options) {
|
|
|
489
489
|
}
|
|
490
490
|
const queryClient = options.queryClient ?? createQueryClient();
|
|
491
491
|
let recoveryRoute;
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
const originalAnalysis = await analyzeRouteSource({
|
|
545
|
-
appDir: options.appDir,
|
|
546
|
-
artifact: options.serverModules?.get(matched.route.file)?.analysis,
|
|
547
|
-
code: originalCode,
|
|
548
|
-
filename: matched.route.file,
|
|
549
|
-
routePath: matched.route.path,
|
|
550
|
-
clientRouteInferenceCache,
|
|
551
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
552
|
-
serverSourceFiles: options.serverSourceFiles,
|
|
553
|
-
define: options.define,
|
|
554
|
-
timing,
|
|
555
|
-
vitePlugins: options.vitePlugins,
|
|
556
|
-
});
|
|
557
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "sourceAnalysisMs");
|
|
558
|
-
const cachePolicy = originalAnalysis.cachePolicy;
|
|
559
|
-
const navigationScript = options.navigationScripts?.get(matched.route.path);
|
|
560
|
-
const cacheKey = routeCacheKey(options.appDir, matched.route.path, url);
|
|
561
|
-
const mayUseRouteCache = cachePolicy === undefined
|
|
562
|
-
? originalAnalysis.usesRuntimeCacheControl
|
|
563
|
-
: cachePolicy.revalidateSeconds !== 0;
|
|
564
|
-
const reloadRouteCache = isNavigationRouteCacheReloadRequest(options.request);
|
|
565
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
566
|
-
const cachedResponse = !mayUseRouteCache || reloadRouteCache
|
|
567
|
-
? undefined
|
|
568
|
-
: await cachedRouteResponse({
|
|
569
|
-
cache: options.routeCache,
|
|
570
|
-
key: cacheKey,
|
|
571
|
-
request: options.request,
|
|
572
|
-
});
|
|
573
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "routeCacheMs");
|
|
574
|
-
if (cachedResponse !== undefined) {
|
|
575
|
-
return cachedResponse;
|
|
576
|
-
}
|
|
577
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
578
|
-
const preparedActions = await prepareRouteServerActions({
|
|
579
|
-
appDir: options.appDir,
|
|
580
|
-
code: originalCode,
|
|
581
|
-
formActionReferences: options.serverActionReferencesByFile?.get(matched.route.file),
|
|
582
|
-
placeholders: true,
|
|
583
|
-
pageFile: matched.route.file,
|
|
584
|
-
request: options.request,
|
|
585
|
-
});
|
|
586
|
-
for (const diagnostic of preparedActions.diagnostics ?? []) {
|
|
587
|
-
console.warn(`${diagnostic.code}: ${diagnostic.message}`);
|
|
588
|
-
}
|
|
589
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "serverActionsMs");
|
|
590
|
-
const code = preparedActions.code;
|
|
591
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
592
|
-
const routeAnalysis = code === originalCode
|
|
593
|
-
? originalAnalysis
|
|
594
|
-
: await analyzeRouteSource({
|
|
492
|
+
return (await withRouteCacheContext(options.routeCache, async () => {
|
|
493
|
+
try {
|
|
494
|
+
if (matched.route.kind === "asset") {
|
|
495
|
+
return await dispatchConventionAssetRoute({
|
|
496
|
+
file: matched.route.file,
|
|
497
|
+
request: options.request,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
if (matched.route.kind === "metadata") {
|
|
501
|
+
return await dispatchMetadataRoute({
|
|
502
|
+
appDir: options.appDir,
|
|
503
|
+
file: matched.route.file,
|
|
504
|
+
importPolicy: options.importPolicy,
|
|
505
|
+
params: matched.params,
|
|
506
|
+
request: options.request,
|
|
507
|
+
route: matched.route,
|
|
508
|
+
serverModules: options.serverModules,
|
|
509
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
510
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
511
|
+
vitePlugins: options.vitePlugins,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
if (matched.route.kind === "server") {
|
|
515
|
+
return await dispatchServerRoute({
|
|
516
|
+
appDir: options.appDir,
|
|
517
|
+
env: options.env,
|
|
518
|
+
file: matched.route.file,
|
|
519
|
+
importPolicy: options.importPolicy,
|
|
520
|
+
params: matched.params,
|
|
521
|
+
request: options.request,
|
|
522
|
+
route: matched.route,
|
|
523
|
+
serverModules: options.serverModules,
|
|
524
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
525
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
526
|
+
vitePlugins: options.vitePlugins,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
// Issue 080: page routes render HTML for GET / HEAD only. Other
|
|
530
|
+
// methods (PUT, PATCH, DELETE, PROPFIND, ...) get 405 with an
|
|
531
|
+
// Allow header so the response shape complies with RFC 9110 §9
|
|
532
|
+
// and so caching intermediaries do not cross-cache method results.
|
|
533
|
+
const methodResponse = pageRouteMethodResponse(options.request.method);
|
|
534
|
+
if (methodResponse !== undefined) {
|
|
535
|
+
return methodResponse;
|
|
536
|
+
}
|
|
537
|
+
const clientScript = options.clientScripts?.get(matched.route.path);
|
|
538
|
+
const clientStyleSheets = options.clientStyles?.get(matched.route.path);
|
|
539
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
540
|
+
const originalCode = await readServerSourceFile(matched.route.file, options.serverModuleCacheVersion, options.serverSourceFiles);
|
|
541
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "readSourceMs");
|
|
542
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
543
|
+
const originalAnalysis = await analyzeRouteSource({
|
|
595
544
|
appDir: options.appDir,
|
|
596
|
-
|
|
597
|
-
code,
|
|
545
|
+
artifact: options.serverModules?.get(matched.route.file)?.analysis,
|
|
546
|
+
code: originalCode,
|
|
598
547
|
filename: matched.route.file,
|
|
599
548
|
routePath: matched.route.path,
|
|
600
549
|
clientRouteInferenceCache,
|
|
601
|
-
serverModuleCacheVersion:
|
|
550
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
602
551
|
serverSourceFiles: options.serverSourceFiles,
|
|
603
552
|
define: options.define,
|
|
553
|
+
timing,
|
|
604
554
|
vitePlugins: options.vitePlugins,
|
|
605
555
|
});
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
queryClient,
|
|
556
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "sourceAnalysisMs");
|
|
557
|
+
const cachePolicy = originalAnalysis.cachePolicy;
|
|
558
|
+
const navigationScript = options.navigationScripts?.get(matched.route.path);
|
|
559
|
+
const cacheKey = routeCacheKey(options.appDir, matched.route.path, url);
|
|
560
|
+
const mayUseRouteCache = cachePolicy === undefined
|
|
561
|
+
? originalAnalysis.usesRuntimeCacheControl
|
|
562
|
+
: cachePolicy.revalidateSeconds !== 0;
|
|
563
|
+
const reloadRouteCache = isNavigationRouteCacheReloadRequest(options.request);
|
|
564
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
565
|
+
const cachedResponse = !mayUseRouteCache || reloadRouteCache
|
|
566
|
+
? undefined
|
|
567
|
+
: await cachedRouteResponse({
|
|
568
|
+
cache: options.routeCache,
|
|
569
|
+
key: cacheKey,
|
|
621
570
|
request: options.request,
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
request: options.request,
|
|
628
|
-
routeId: routeIdForPath(matched.route.path),
|
|
629
|
-
routePath: matched.route.path,
|
|
630
|
-
serverModules: options.serverModules,
|
|
631
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
632
|
-
define: options.define,
|
|
633
|
-
vitePlugins: options.vitePlugins,
|
|
634
|
-
timing,
|
|
635
|
-
onLoaderReady: loaderReady?.resolve,
|
|
636
|
-
})
|
|
637
|
-
: undefined;
|
|
638
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "loaderStartMs");
|
|
639
|
-
recoveryRoute = {
|
|
640
|
-
clientRoute,
|
|
641
|
-
props: {
|
|
642
|
-
params: matched.params,
|
|
643
|
-
request: { url: options.request.url },
|
|
644
|
-
},
|
|
645
|
-
routePath: matched.route.path,
|
|
646
|
-
script: clientScript,
|
|
647
|
-
};
|
|
648
|
-
if (streamRoute) {
|
|
571
|
+
});
|
|
572
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "routeCacheMs");
|
|
573
|
+
if (cachedResponse !== undefined) {
|
|
574
|
+
return cachedResponse;
|
|
575
|
+
}
|
|
649
576
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
650
|
-
const
|
|
577
|
+
const preparedActions = await prepareRouteServerActions({
|
|
651
578
|
appDir: options.appDir,
|
|
652
|
-
|
|
579
|
+
code: originalCode,
|
|
580
|
+
formActionReferences: options.serverActionReferencesByFile?.get(matched.route.file),
|
|
581
|
+
placeholders: true,
|
|
653
582
|
pageFile: matched.route.file,
|
|
654
|
-
|
|
583
|
+
request: options.request,
|
|
655
584
|
});
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
585
|
+
for (const diagnostic of preparedActions.diagnostics ?? []) {
|
|
586
|
+
console.warn(`${diagnostic.code}: ${diagnostic.message}`);
|
|
587
|
+
}
|
|
588
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "serverActionsMs");
|
|
589
|
+
const code = preparedActions.code;
|
|
661
590
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
591
|
+
const routeAnalysis = code === originalCode
|
|
592
|
+
? originalAnalysis
|
|
593
|
+
: await analyzeRouteSource({
|
|
594
|
+
appDir: options.appDir,
|
|
595
|
+
buildRenderCode: preparedActions.htmlReplacements !== undefined,
|
|
596
|
+
code,
|
|
597
|
+
filename: matched.route.file,
|
|
598
|
+
routePath: matched.route.path,
|
|
599
|
+
clientRouteInferenceCache,
|
|
600
|
+
serverModuleCacheVersion: undefined,
|
|
601
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
602
|
+
define: options.define,
|
|
603
|
+
vitePlugins: options.vitePlugins,
|
|
604
|
+
});
|
|
605
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "routeCodeAnalysisMs");
|
|
606
|
+
const routeCode = routeAnalysis.routeCode;
|
|
607
|
+
const streamRoute = routeAnalysis.streamRoute;
|
|
608
|
+
const clientInference = routeAnalysis.clientInference;
|
|
609
|
+
const clientRoute = clientInference.client;
|
|
610
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
611
|
+
const loaderReady = routeAnalysis.hasLoader ? createDeferredSignal() : undefined;
|
|
612
|
+
const dataPromise = routeAnalysis.hasLoader
|
|
613
|
+
? loadRouteDataWithInstrumentation({
|
|
614
|
+
appDir: options.appDir,
|
|
615
|
+
code: originalCode,
|
|
616
|
+
context: {
|
|
617
|
+
env: options.env,
|
|
618
|
+
params: matched.params,
|
|
619
|
+
queryClient,
|
|
620
|
+
request: options.request,
|
|
621
|
+
},
|
|
622
|
+
filename: matched.route.file,
|
|
623
|
+
importPolicy: options.importPolicy,
|
|
624
|
+
instrumentation: options.instrumentation,
|
|
625
|
+
devServerModuleCacheVersion: options.devServerModuleCacheVersion,
|
|
626
|
+
request: options.request,
|
|
627
|
+
routeId: routeIdForPath(matched.route.path),
|
|
628
|
+
routePath: matched.route.path,
|
|
629
|
+
serverModules: options.serverModules,
|
|
630
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
631
|
+
define: options.define,
|
|
632
|
+
vitePlugins: options.vitePlugins,
|
|
633
|
+
timing,
|
|
634
|
+
onLoaderReady: loaderReady?.resolve,
|
|
635
|
+
})
|
|
636
|
+
: undefined;
|
|
637
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "loaderStartMs");
|
|
638
|
+
recoveryRoute = {
|
|
639
|
+
clientRoute,
|
|
640
|
+
props: {
|
|
641
|
+
params: matched.params,
|
|
642
|
+
request: { url: options.request.url },
|
|
643
|
+
},
|
|
644
|
+
routePath: matched.route.path,
|
|
645
|
+
script: clientScript,
|
|
646
|
+
};
|
|
647
|
+
if (streamRoute) {
|
|
648
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
649
|
+
const loadingFile = await nearestExistingBoundaryFileForPage({
|
|
650
|
+
appDir: options.appDir,
|
|
651
|
+
filename: "loading.mreact.tsx",
|
|
652
|
+
pageFile: matched.route.file,
|
|
653
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
654
|
+
});
|
|
655
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "loadingBoundaryLookupMs");
|
|
656
|
+
const streamShellResponseHeaders = {
|
|
657
|
+
"content-type": "text/html; charset=utf-8",
|
|
658
|
+
"x-mreact-stream": "1",
|
|
659
|
+
};
|
|
670
660
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
661
|
+
const mayRenderOutOfOrder = await mayRenderOutOfOrderBoundaryDeep({
|
|
662
|
+
code: routeCode,
|
|
663
|
+
filename: matched.route.file,
|
|
664
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
665
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
666
|
+
});
|
|
667
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "outOfOrderAnalysisMs");
|
|
668
|
+
if (loadingFile === undefined && !mayRenderOutOfOrder) {
|
|
669
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
670
|
+
let data;
|
|
671
|
+
try {
|
|
672
|
+
data = dataPromise === undefined ? undefined : await dataPromise;
|
|
673
|
+
}
|
|
674
|
+
finally {
|
|
675
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
676
|
+
}
|
|
677
|
+
if (data instanceof Response) {
|
|
678
|
+
emitRenderTiming(options, timing, data.status);
|
|
679
|
+
return data;
|
|
680
|
+
}
|
|
681
|
+
await waitForRenderPreload(options, timing);
|
|
682
|
+
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
683
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
684
|
+
const stringOutput = transformServerModule({
|
|
685
|
+
code: routeCode,
|
|
686
|
+
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
687
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
688
|
+
filename: matched.route.file,
|
|
689
|
+
serverModules: options.serverModules,
|
|
690
|
+
serverOutput: "string",
|
|
691
|
+
});
|
|
692
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "stringTransformMs");
|
|
693
|
+
const stringFatalDiagnostics = fatalServerDiagnostics(stringOutput.diagnostics);
|
|
694
|
+
if (stringFatalDiagnostics.length > 0) {
|
|
695
|
+
return new Response(formatServerDiagnostics(matched.route.file, stringFatalDiagnostics), {
|
|
696
|
+
status: 500,
|
|
697
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
const renderedPage = await runWithQueryClient(queryClient, () => runServerModuleWithSlots(stringOutput.code, {
|
|
701
|
+
data,
|
|
702
|
+
params: matched.params,
|
|
703
|
+
queryClient,
|
|
704
|
+
request: options.request,
|
|
705
|
+
}, matched.route.file, options.serverModules, options.serverModuleCacheVersion, options.define, options.vitePlugins, undefined, options.importPolicy, options.devServerModuleCacheVersion));
|
|
706
|
+
const pageHtml = renderedPage.html;
|
|
707
|
+
const pageHtmlForLayout = clientRoute
|
|
708
|
+
? withHydrationMarkers({
|
|
709
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
710
|
+
clientReferenceManifest: stringOutput.metadata.clientReferenceManifest,
|
|
711
|
+
html: pageHtml,
|
|
712
|
+
routePath: matched.route.path,
|
|
713
|
+
script: clientScript,
|
|
714
|
+
props: {
|
|
715
|
+
params: matched.params,
|
|
716
|
+
request: { url: options.request.url },
|
|
717
|
+
data,
|
|
718
|
+
},
|
|
719
|
+
})
|
|
720
|
+
: isNavigationRequest(options.request)
|
|
721
|
+
? withRouteMarkers({
|
|
722
|
+
html: pageHtml,
|
|
723
|
+
routePath: matched.route.path,
|
|
724
|
+
})
|
|
725
|
+
: pageHtml;
|
|
726
|
+
let html = await runWithQueryClient(queryClient, () => applyLayouts({
|
|
727
|
+
appDir: options.appDir,
|
|
728
|
+
pageFile: matched.route.file,
|
|
729
|
+
html: pageHtmlForLayout,
|
|
730
|
+
props: {
|
|
731
|
+
data,
|
|
732
|
+
params: matched.params,
|
|
733
|
+
queryClient,
|
|
734
|
+
request: options.request,
|
|
735
|
+
},
|
|
736
|
+
slots: renderedPage.slots,
|
|
737
|
+
serverModules: options.serverModules,
|
|
738
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
739
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
740
|
+
clientRouteInferenceCache,
|
|
741
|
+
timing,
|
|
742
|
+
vitePlugins: options.vitePlugins,
|
|
743
|
+
importPolicy: options.importPolicy,
|
|
744
|
+
}));
|
|
745
|
+
const metadata = await loadComposedRouteMetadata({
|
|
746
|
+
appDir: options.appDir,
|
|
747
|
+
code: originalCode,
|
|
748
|
+
context: {
|
|
749
|
+
data,
|
|
750
|
+
params: matched.params,
|
|
751
|
+
request: options.request,
|
|
752
|
+
},
|
|
753
|
+
filename: matched.route.file,
|
|
754
|
+
importPolicy: options.importPolicy,
|
|
755
|
+
routes,
|
|
756
|
+
serverModules: options.serverModules,
|
|
757
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
758
|
+
devServerModuleCacheVersion: options.devServerModuleCacheVersion,
|
|
759
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
760
|
+
define: options.define,
|
|
761
|
+
vitePlugins: options.vitePlugins,
|
|
762
|
+
});
|
|
763
|
+
html = injectHeadMetadata(html, metadata);
|
|
764
|
+
warnIfCspNonceWouldBlockInlineTags({
|
|
765
|
+
html,
|
|
766
|
+
logger: options.logger,
|
|
767
|
+
metadata,
|
|
768
|
+
request: options.request,
|
|
769
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
770
|
+
});
|
|
771
|
+
html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
|
|
772
|
+
html = injectQueryState(html, dehydrate(queryClient));
|
|
773
|
+
const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
|
|
774
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
775
|
+
currentStyleSheets: clientStyleSheets,
|
|
776
|
+
currentScript: clientRoute ? clientScript : undefined,
|
|
777
|
+
currentNavigationScript: navigationScript,
|
|
778
|
+
routeScripts: options.clientScripts,
|
|
779
|
+
})}${html}`, preparedActions.htmlReplacements), {
|
|
780
|
+
headers: responseHeadersForMetadata(metadata, options.request, {
|
|
781
|
+
"x-mreact-stream": "1",
|
|
782
|
+
}),
|
|
783
|
+
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
784
|
+
emitRenderTiming(options, timing, response.status);
|
|
785
|
+
return response;
|
|
674
786
|
}
|
|
675
|
-
|
|
676
|
-
|
|
787
|
+
let streamData;
|
|
788
|
+
let streamDataPromise = dataPromise ?? Promise.resolve(undefined);
|
|
789
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
790
|
+
if (loadingFile === undefined || routeLoaderMayReturnControlResponse(originalCode)) {
|
|
791
|
+
try {
|
|
792
|
+
streamData = dataPromise === undefined ? undefined : await dataPromise;
|
|
793
|
+
}
|
|
794
|
+
finally {
|
|
795
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
796
|
+
}
|
|
797
|
+
if (streamData instanceof Response) {
|
|
798
|
+
emitRenderTiming(options, timing, streamData.status);
|
|
799
|
+
return streamData;
|
|
800
|
+
}
|
|
801
|
+
streamDataPromise = Promise.resolve(streamData);
|
|
677
802
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
803
|
+
else {
|
|
804
|
+
try {
|
|
805
|
+
const settledData = await readSettledPromiseAtNextTask(streamDataPromise);
|
|
806
|
+
if (settledData.settled) {
|
|
807
|
+
if (settledData.value instanceof Response) {
|
|
808
|
+
emitRenderTiming(options, timing, settledData.value.status);
|
|
809
|
+
return settledData.value;
|
|
810
|
+
}
|
|
811
|
+
streamDataPromise = Promise.resolve(settledData.value);
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
await waitForLoaderReadyOrSettled(streamDataPromise, loaderReady?.promise);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
finally {
|
|
818
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
819
|
+
}
|
|
681
820
|
}
|
|
682
821
|
await waitForRenderPreload(options, timing);
|
|
683
822
|
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
684
823
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
685
|
-
const
|
|
824
|
+
const output = transformServerModule({
|
|
686
825
|
code: routeCode,
|
|
687
826
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
688
827
|
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
689
828
|
filename: matched.route.file,
|
|
690
829
|
serverModules: options.serverModules,
|
|
691
|
-
serverOutput: "
|
|
830
|
+
serverOutput: "stream",
|
|
831
|
+
serverAwaitHydration: clientRoute,
|
|
692
832
|
});
|
|
693
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "
|
|
694
|
-
const
|
|
695
|
-
if (
|
|
696
|
-
return new Response(formatServerDiagnostics(matched.route.file,
|
|
833
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "streamTransformMs");
|
|
834
|
+
const fatalDiagnostics = fatalServerDiagnostics(output.diagnostics);
|
|
835
|
+
if (fatalDiagnostics.length > 0) {
|
|
836
|
+
return new Response(formatServerDiagnostics(matched.route.file, fatalDiagnostics), {
|
|
697
837
|
status: 500,
|
|
698
838
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
699
839
|
});
|
|
700
840
|
}
|
|
701
|
-
|
|
841
|
+
if (loadingFile !== undefined) {
|
|
842
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
843
|
+
const stream = await runServerStreamModuleWithLoading(output.code, {
|
|
844
|
+
appDir: options.appDir,
|
|
845
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
846
|
+
clientRoute,
|
|
847
|
+
data: streamDataPromise,
|
|
848
|
+
define: options.define,
|
|
849
|
+
loadingFile,
|
|
850
|
+
pageFile: matched.route.file,
|
|
851
|
+
params: matched.params,
|
|
852
|
+
queryClient,
|
|
853
|
+
request: options.request,
|
|
854
|
+
routePath: matched.route.path,
|
|
855
|
+
routeScripts: options.clientScripts,
|
|
856
|
+
serverModules: options.serverModules,
|
|
857
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
858
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
859
|
+
vitePlugins: options.vitePlugins,
|
|
860
|
+
clientRouteInferenceCache,
|
|
861
|
+
importPolicy: options.importPolicy,
|
|
862
|
+
script: clientScript,
|
|
863
|
+
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
864
|
+
});
|
|
865
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "streamConstructionMs");
|
|
866
|
+
const response = withOptionalActionCookie(new Response(stream, {
|
|
867
|
+
headers: streamShellResponseHeaders,
|
|
868
|
+
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
869
|
+
emitRenderTiming(options, timing, response.status);
|
|
870
|
+
return response;
|
|
871
|
+
}
|
|
872
|
+
const data = streamData;
|
|
873
|
+
const props = {
|
|
702
874
|
data,
|
|
703
875
|
params: matched.params,
|
|
704
876
|
queryClient,
|
|
705
877
|
request: options.request,
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
const
|
|
709
|
-
? withHydrationMarkers({
|
|
710
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
711
|
-
clientReferenceManifest: stringOutput.metadata.clientReferenceManifest,
|
|
712
|
-
html: pageHtml,
|
|
713
|
-
routePath: matched.route.path,
|
|
714
|
-
script: clientScript,
|
|
715
|
-
props: {
|
|
716
|
-
params: matched.params,
|
|
717
|
-
request: { url: options.request.url },
|
|
718
|
-
data,
|
|
719
|
-
},
|
|
720
|
-
})
|
|
721
|
-
: isNavigationRequest(options.request)
|
|
722
|
-
? withRouteMarkers({
|
|
723
|
-
html: pageHtml,
|
|
724
|
-
routePath: matched.route.path,
|
|
725
|
-
})
|
|
726
|
-
: pageHtml;
|
|
727
|
-
let html = await runWithQueryClient(queryClient, () => applyLayouts({
|
|
878
|
+
};
|
|
879
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
880
|
+
const stream = runServerStreamModule(output.code, {
|
|
728
881
|
appDir: options.appDir,
|
|
882
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
729
883
|
pageFile: matched.route.file,
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
params: matched.params,
|
|
734
|
-
queryClient,
|
|
735
|
-
request: options.request,
|
|
736
|
-
},
|
|
737
|
-
slots: renderedPage.slots,
|
|
738
|
-
serverModules: options.serverModules,
|
|
739
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
740
|
-
serverSourceFiles: options.serverSourceFiles,
|
|
741
|
-
clientRouteInferenceCache,
|
|
742
|
-
timing,
|
|
743
|
-
vitePlugins: options.vitePlugins,
|
|
744
|
-
importPolicy: options.importPolicy,
|
|
745
|
-
}));
|
|
746
|
-
const metadata = await loadComposedRouteMetadata({
|
|
747
|
-
appDir: options.appDir,
|
|
748
|
-
code: originalCode,
|
|
749
|
-
context: {
|
|
750
|
-
data,
|
|
751
|
-
params: matched.params,
|
|
752
|
-
request: options.request,
|
|
753
|
-
},
|
|
754
|
-
filename: matched.route.file,
|
|
755
|
-
importPolicy: options.importPolicy,
|
|
756
|
-
routes,
|
|
884
|
+
props,
|
|
885
|
+
routePath: matched.route.path,
|
|
886
|
+
routeScripts: options.clientScripts,
|
|
757
887
|
serverModules: options.serverModules,
|
|
758
888
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
759
|
-
devServerModuleCacheVersion: options.devServerModuleCacheVersion,
|
|
760
889
|
serverSourceFiles: options.serverSourceFiles,
|
|
761
890
|
define: options.define,
|
|
762
891
|
vitePlugins: options.vitePlugins,
|
|
892
|
+
clientRouteInferenceCache,
|
|
893
|
+
importPolicy: options.importPolicy,
|
|
894
|
+
clientRoute,
|
|
895
|
+
script: clientScript,
|
|
896
|
+
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
763
897
|
});
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
logger: options.logger,
|
|
768
|
-
metadata,
|
|
769
|
-
request: options.request,
|
|
770
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
771
|
-
});
|
|
772
|
-
html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
|
|
773
|
-
html = injectQueryState(html, dehydrate(queryClient));
|
|
774
|
-
const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
|
|
775
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
776
|
-
currentStyleSheets: clientStyleSheets,
|
|
777
|
-
currentScript: clientRoute ? clientScript : undefined,
|
|
778
|
-
currentNavigationScript: navigationScript,
|
|
779
|
-
routeScripts: options.clientScripts,
|
|
780
|
-
})}${html}`, preparedActions.htmlReplacements), {
|
|
781
|
-
headers: responseHeadersForMetadata(metadata, options.request, {
|
|
782
|
-
"x-mreact-stream": "1",
|
|
783
|
-
}),
|
|
898
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "streamConstructionMs");
|
|
899
|
+
const response = withOptionalActionCookie(new Response(stream, {
|
|
900
|
+
headers: streamShellResponseHeaders,
|
|
784
901
|
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
785
902
|
emitRenderTiming(options, timing, response.status);
|
|
786
903
|
return response;
|
|
787
904
|
}
|
|
788
|
-
let streamData;
|
|
789
|
-
let streamDataPromise = dataPromise ?? Promise.resolve(undefined);
|
|
790
905
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
}
|
|
795
|
-
finally {
|
|
796
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
797
|
-
}
|
|
798
|
-
if (streamData instanceof Response) {
|
|
799
|
-
emitRenderTiming(options, timing, streamData.status);
|
|
800
|
-
return streamData;
|
|
801
|
-
}
|
|
802
|
-
streamDataPromise = Promise.resolve(streamData);
|
|
906
|
+
let data;
|
|
907
|
+
try {
|
|
908
|
+
data = dataPromise === undefined ? undefined : await dataPromise;
|
|
803
909
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
return settledData.value;
|
|
811
|
-
}
|
|
812
|
-
streamDataPromise = Promise.resolve(settledData.value);
|
|
813
|
-
}
|
|
814
|
-
else {
|
|
815
|
-
await waitForLoaderReadyOrSettled(streamDataPromise, loaderReady?.promise);
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
finally {
|
|
819
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
820
|
-
}
|
|
910
|
+
finally {
|
|
911
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
912
|
+
}
|
|
913
|
+
if (data instanceof Response) {
|
|
914
|
+
emitRenderTiming(options, timing, data.status);
|
|
915
|
+
return data;
|
|
821
916
|
}
|
|
822
917
|
await waitForRenderPreload(options, timing);
|
|
823
918
|
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
@@ -828,10 +923,9 @@ async function renderAppRequestInternal(options) {
|
|
|
828
923
|
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
829
924
|
filename: matched.route.file,
|
|
830
925
|
serverModules: options.serverModules,
|
|
831
|
-
serverOutput: "
|
|
832
|
-
serverAwaitHydration: clientRoute,
|
|
926
|
+
serverOutput: "string",
|
|
833
927
|
});
|
|
834
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "
|
|
928
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "stringTransformMs");
|
|
835
929
|
const fatalDiagnostics = fatalServerDiagnostics(output.diagnostics);
|
|
836
930
|
if (fatalDiagnostics.length > 0) {
|
|
837
931
|
return new Response(formatServerDiagnostics(matched.route.file, fatalDiagnostics), {
|
|
@@ -839,273 +933,176 @@ async function renderAppRequestInternal(options) {
|
|
|
839
933
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
840
934
|
});
|
|
841
935
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
const stream = await runServerStreamModuleWithLoading(output.code, {
|
|
845
|
-
appDir: options.appDir,
|
|
846
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
847
|
-
clientRoute,
|
|
848
|
-
data: streamDataPromise,
|
|
849
|
-
define: options.define,
|
|
850
|
-
loadingFile,
|
|
851
|
-
pageFile: matched.route.file,
|
|
852
|
-
params: matched.params,
|
|
853
|
-
queryClient,
|
|
854
|
-
request: options.request,
|
|
855
|
-
routePath: matched.route.path,
|
|
856
|
-
routeScripts: options.clientScripts,
|
|
857
|
-
serverModules: options.serverModules,
|
|
858
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
859
|
-
serverSourceFiles: options.serverSourceFiles,
|
|
860
|
-
vitePlugins: options.vitePlugins,
|
|
861
|
-
clientRouteInferenceCache,
|
|
862
|
-
importPolicy: options.importPolicy,
|
|
863
|
-
script: clientScript,
|
|
864
|
-
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
865
|
-
});
|
|
866
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "streamConstructionMs");
|
|
867
|
-
const response = withOptionalActionCookie(new Response(stream, {
|
|
868
|
-
headers: streamShellResponseHeaders,
|
|
869
|
-
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
870
|
-
emitRenderTiming(options, timing, response.status);
|
|
871
|
-
return response;
|
|
872
|
-
}
|
|
873
|
-
const data = streamData;
|
|
874
|
-
const props = {
|
|
936
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
937
|
+
const renderedPage = await runWithQueryClient(queryClient, () => runServerModuleWithSlots(output.code, {
|
|
875
938
|
data,
|
|
876
939
|
params: matched.params,
|
|
877
940
|
queryClient,
|
|
878
941
|
request: options.request,
|
|
879
|
-
};
|
|
942
|
+
}, matched.route.file, options.serverModules, options.serverModuleCacheVersion, options.define, options.vitePlugins, timing, options.importPolicy, options.devServerModuleCacheVersion));
|
|
943
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "pageRenderMs");
|
|
944
|
+
const pageHtml = renderedPage.html;
|
|
945
|
+
// Wrap the page (not the full document) with the hydration marker so
|
|
946
|
+
// the marker sits inside <body>, not around <html>. Wrapping <html>
|
|
947
|
+
// forces the browser HTML parser to strip the wrappers and promote
|
|
948
|
+
// <head> / <body> children up to the marker, which flattens the
|
|
949
|
+
// layout into the marker and breaks the hydration target lookup.
|
|
950
|
+
const pageHtmlForLayout = clientRoute
|
|
951
|
+
? withHydrationMarkers({
|
|
952
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
953
|
+
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
954
|
+
html: pageHtml,
|
|
955
|
+
routePath: matched.route.path,
|
|
956
|
+
script: clientScript,
|
|
957
|
+
props: {
|
|
958
|
+
params: matched.params,
|
|
959
|
+
request: { url: options.request.url },
|
|
960
|
+
data,
|
|
961
|
+
},
|
|
962
|
+
})
|
|
963
|
+
: isNavigationRequest(options.request)
|
|
964
|
+
? withRouteMarkers({
|
|
965
|
+
html: pageHtml,
|
|
966
|
+
routePath: matched.route.path,
|
|
967
|
+
})
|
|
968
|
+
: pageHtml;
|
|
880
969
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
881
|
-
|
|
970
|
+
let html = await runWithQueryClient(queryClient, () => applyLayouts({
|
|
882
971
|
appDir: options.appDir,
|
|
883
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
884
972
|
pageFile: matched.route.file,
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
973
|
+
html: pageHtmlForLayout,
|
|
974
|
+
props: {
|
|
975
|
+
data,
|
|
976
|
+
params: matched.params,
|
|
977
|
+
queryClient,
|
|
978
|
+
request: options.request,
|
|
979
|
+
},
|
|
980
|
+
slots: renderedPage.slots,
|
|
888
981
|
serverModules: options.serverModules,
|
|
889
982
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
890
983
|
serverSourceFiles: options.serverSourceFiles,
|
|
891
|
-
define: options.define,
|
|
892
|
-
vitePlugins: options.vitePlugins,
|
|
893
984
|
clientRouteInferenceCache,
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
emitRenderTiming(options, timing, response.status);
|
|
904
|
-
return response;
|
|
905
|
-
}
|
|
906
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
907
|
-
let data;
|
|
908
|
-
try {
|
|
909
|
-
data = dataPromise === undefined ? undefined : await dataPromise;
|
|
910
|
-
}
|
|
911
|
-
finally {
|
|
912
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "loaderWaitMs");
|
|
913
|
-
}
|
|
914
|
-
if (data instanceof Response) {
|
|
915
|
-
emitRenderTiming(options, timing, data.status);
|
|
916
|
-
return data;
|
|
917
|
-
}
|
|
918
|
-
await waitForRenderPreload(options, timing);
|
|
919
|
-
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
920
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
921
|
-
const output = transformServerModule({
|
|
922
|
-
code: routeCode,
|
|
923
|
-
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
924
|
-
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
925
|
-
filename: matched.route.file,
|
|
926
|
-
serverModules: options.serverModules,
|
|
927
|
-
serverOutput: "string",
|
|
928
|
-
});
|
|
929
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "stringTransformMs");
|
|
930
|
-
const fatalDiagnostics = fatalServerDiagnostics(output.diagnostics);
|
|
931
|
-
if (fatalDiagnostics.length > 0) {
|
|
932
|
-
return new Response(formatServerDiagnostics(matched.route.file, fatalDiagnostics), {
|
|
933
|
-
status: 500,
|
|
934
|
-
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
935
|
-
});
|
|
936
|
-
}
|
|
937
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
938
|
-
const renderedPage = await runWithQueryClient(queryClient, () => runServerModuleWithSlots(output.code, {
|
|
939
|
-
data,
|
|
940
|
-
params: matched.params,
|
|
941
|
-
queryClient,
|
|
942
|
-
request: options.request,
|
|
943
|
-
}, matched.route.file, options.serverModules, options.serverModuleCacheVersion, options.define, options.vitePlugins, timing, options.importPolicy, options.devServerModuleCacheVersion));
|
|
944
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "pageRenderMs");
|
|
945
|
-
const pageHtml = renderedPage.html;
|
|
946
|
-
// Wrap the page (not the full document) with the hydration marker so
|
|
947
|
-
// the marker sits inside <body>, not around <html>. Wrapping <html>
|
|
948
|
-
// forces the browser HTML parser to strip the wrappers and promote
|
|
949
|
-
// <head> / <body> children up to the marker, which flattens the
|
|
950
|
-
// layout into the marker and breaks the hydration target lookup.
|
|
951
|
-
const pageHtmlForLayout = clientRoute
|
|
952
|
-
? withHydrationMarkers({
|
|
953
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
954
|
-
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
955
|
-
html: pageHtml,
|
|
956
|
-
routePath: matched.route.path,
|
|
957
|
-
script: clientScript,
|
|
958
|
-
props: {
|
|
959
|
-
params: matched.params,
|
|
960
|
-
request: { url: options.request.url },
|
|
985
|
+
timing,
|
|
986
|
+
vitePlugins: options.vitePlugins,
|
|
987
|
+
}));
|
|
988
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "layoutRenderMs");
|
|
989
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
990
|
+
const metadata = await loadComposedRouteMetadata({
|
|
991
|
+
appDir: options.appDir,
|
|
992
|
+
code: originalCode,
|
|
993
|
+
context: {
|
|
961
994
|
data,
|
|
995
|
+
params: matched.params,
|
|
996
|
+
request: options.request,
|
|
962
997
|
},
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
:
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
appDir: options.appDir,
|
|
973
|
-
pageFile: matched.route.file,
|
|
974
|
-
html: pageHtmlForLayout,
|
|
975
|
-
props: {
|
|
976
|
-
data,
|
|
977
|
-
params: matched.params,
|
|
978
|
-
queryClient,
|
|
979
|
-
request: options.request,
|
|
980
|
-
},
|
|
981
|
-
slots: renderedPage.slots,
|
|
982
|
-
serverModules: options.serverModules,
|
|
983
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
984
|
-
serverSourceFiles: options.serverSourceFiles,
|
|
985
|
-
clientRouteInferenceCache,
|
|
986
|
-
timing,
|
|
987
|
-
vitePlugins: options.vitePlugins,
|
|
988
|
-
}));
|
|
989
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "layoutRenderMs");
|
|
990
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
991
|
-
const metadata = await loadComposedRouteMetadata({
|
|
992
|
-
appDir: options.appDir,
|
|
993
|
-
code: originalCode,
|
|
994
|
-
context: {
|
|
995
|
-
data,
|
|
996
|
-
params: matched.params,
|
|
997
|
-
request: options.request,
|
|
998
|
-
},
|
|
999
|
-
filename: matched.route.file,
|
|
1000
|
-
importPolicy: options.importPolicy,
|
|
1001
|
-
routes,
|
|
1002
|
-
serverModules: options.serverModules,
|
|
1003
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1004
|
-
devServerModuleCacheVersion: options.devServerModuleCacheVersion,
|
|
1005
|
-
serverSourceFiles: options.serverSourceFiles,
|
|
1006
|
-
define: options.define,
|
|
1007
|
-
vitePlugins: options.vitePlugins,
|
|
1008
|
-
});
|
|
1009
|
-
finishRenderTimingPhase(timing, phaseStartedAt, "metadataMs");
|
|
1010
|
-
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
1011
|
-
html = injectHeadMetadata(html, metadata);
|
|
1012
|
-
warnIfCspNonceWouldBlockInlineTags({
|
|
1013
|
-
html,
|
|
1014
|
-
logger: options.logger,
|
|
1015
|
-
metadata,
|
|
1016
|
-
request: options.request,
|
|
1017
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1018
|
-
});
|
|
1019
|
-
html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
|
|
1020
|
-
html = injectQueryState(html, dehydrate(queryClient));
|
|
1021
|
-
const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
|
|
1022
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
1023
|
-
currentStyleSheets: clientStyleSheets,
|
|
1024
|
-
currentScript: clientRoute ? clientScript : undefined,
|
|
1025
|
-
currentNavigationScript: navigationScript,
|
|
1026
|
-
routeScripts: options.clientScripts,
|
|
1027
|
-
})}${html}`, preparedActions.htmlReplacements), {
|
|
1028
|
-
headers: responseHeadersForMetadata(metadata, options.request),
|
|
1029
|
-
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
1030
|
-
const effectiveCachePolicy = cachePolicy ?? routeCacheContext.cachePolicy;
|
|
1031
|
-
const finalResponse = preparedActions.hasFormActions
|
|
1032
|
-
? withRouteCacheHeader(response, effectiveCachePolicy)
|
|
1033
|
-
: await cacheRouteResponse({
|
|
1034
|
-
key: cacheKey,
|
|
1035
|
-
cache: options.routeCache,
|
|
1036
|
-
path: matched.route.path,
|
|
1037
|
-
policy: effectiveCachePolicy,
|
|
1038
|
-
request: options.request,
|
|
1039
|
-
response,
|
|
998
|
+
filename: matched.route.file,
|
|
999
|
+
importPolicy: options.importPolicy,
|
|
1000
|
+
routes,
|
|
1001
|
+
serverModules: options.serverModules,
|
|
1002
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1003
|
+
devServerModuleCacheVersion: options.devServerModuleCacheVersion,
|
|
1004
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
1005
|
+
define: options.define,
|
|
1006
|
+
vitePlugins: options.vitePlugins,
|
|
1040
1007
|
});
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1008
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "metadataMs");
|
|
1009
|
+
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
1010
|
+
html = injectHeadMetadata(html, metadata);
|
|
1011
|
+
warnIfCspNonceWouldBlockInlineTags({
|
|
1012
|
+
html,
|
|
1013
|
+
logger: options.logger,
|
|
1014
|
+
metadata,
|
|
1015
|
+
request: options.request,
|
|
1016
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1050
1017
|
});
|
|
1051
|
-
|
|
1052
|
-
|
|
1018
|
+
html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
|
|
1019
|
+
html = injectQueryState(html, dehydrate(queryClient));
|
|
1020
|
+
const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
|
|
1021
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
1022
|
+
currentStyleSheets: clientStyleSheets,
|
|
1023
|
+
currentScript: clientRoute ? clientScript : undefined,
|
|
1024
|
+
currentNavigationScript: navigationScript,
|
|
1025
|
+
routeScripts: options.clientScripts,
|
|
1026
|
+
})}${html}`, preparedActions.htmlReplacements), {
|
|
1027
|
+
headers: responseHeadersForMetadata(metadata, options.request),
|
|
1028
|
+
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
1029
|
+
const effectiveCachePolicy = cachePolicy ?? activeRouteCacheContext()?.cachePolicy;
|
|
1030
|
+
const finalResponse = preparedActions.hasFormActions
|
|
1031
|
+
? withRouteCacheHeader(response, effectiveCachePolicy)
|
|
1032
|
+
: await cacheRouteResponse({
|
|
1033
|
+
key: cacheKey,
|
|
1034
|
+
cache: options.routeCache,
|
|
1035
|
+
path: matched.route.path,
|
|
1036
|
+
policy: effectiveCachePolicy,
|
|
1037
|
+
request: options.request,
|
|
1038
|
+
response,
|
|
1039
|
+
});
|
|
1040
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "responseBuildMs");
|
|
1041
|
+
emitRenderTiming(options, timing, finalResponse.status);
|
|
1042
|
+
return finalResponse;
|
|
1053
1043
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1044
|
+
catch (error) {
|
|
1045
|
+
if (isRedirectError(error)) {
|
|
1046
|
+
const response = new Response(null, {
|
|
1047
|
+
headers: { location: error.location },
|
|
1048
|
+
status: error.status,
|
|
1049
|
+
});
|
|
1050
|
+
emitRenderTiming(options, timing, response.status);
|
|
1051
|
+
return response;
|
|
1052
|
+
}
|
|
1053
|
+
if (isNotFoundError(error)) {
|
|
1054
|
+
const notFoundFile = await nearestBoundaryFileForPage({
|
|
1055
|
+
appDir: options.appDir,
|
|
1056
|
+
filename: "not-found.mreact.tsx",
|
|
1057
|
+
pageFile: matched.route.file,
|
|
1058
|
+
});
|
|
1059
|
+
const response = await renderSpecialRoute({
|
|
1060
|
+
appDir: options.appDir,
|
|
1061
|
+
assetBaseUrl: options.assetBaseUrl,
|
|
1062
|
+
currentStyleSheets: options.clientStylesByFile?.get(notFoundFile),
|
|
1063
|
+
error: undefined,
|
|
1064
|
+
request: options.request,
|
|
1065
|
+
routePath: matched.route.path,
|
|
1066
|
+
routeFile: notFoundFile,
|
|
1067
|
+
routeScripts: options.clientScripts,
|
|
1068
|
+
serverModules: options.serverModules,
|
|
1069
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1070
|
+
serverSourceFiles: options.serverSourceFiles,
|
|
1071
|
+
vitePlugins: options.vitePlugins,
|
|
1072
|
+
navigation: recoveryRoute,
|
|
1073
|
+
status: 404,
|
|
1074
|
+
textFallback: "Not Found",
|
|
1075
|
+
});
|
|
1076
|
+
emitRenderTiming(options, timing, response.status);
|
|
1077
|
+
return response;
|
|
1078
|
+
}
|
|
1079
|
+
const errorFile = await nearestBoundaryFileForPage({
|
|
1056
1080
|
appDir: options.appDir,
|
|
1057
|
-
filename: "
|
|
1081
|
+
filename: "error.mreact.tsx",
|
|
1058
1082
|
pageFile: matched.route.file,
|
|
1059
1083
|
});
|
|
1084
|
+
options.onRenderError?.(error);
|
|
1060
1085
|
const response = await renderSpecialRoute({
|
|
1061
1086
|
appDir: options.appDir,
|
|
1062
1087
|
assetBaseUrl: options.assetBaseUrl,
|
|
1063
|
-
currentStyleSheets: options.clientStylesByFile?.get(
|
|
1064
|
-
error
|
|
1088
|
+
currentStyleSheets: options.clientStylesByFile?.get(errorFile),
|
|
1089
|
+
error,
|
|
1065
1090
|
request: options.request,
|
|
1066
1091
|
routePath: matched.route.path,
|
|
1067
|
-
routeFile:
|
|
1092
|
+
routeFile: errorFile,
|
|
1068
1093
|
routeScripts: options.clientScripts,
|
|
1069
1094
|
serverModules: options.serverModules,
|
|
1070
1095
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1071
1096
|
serverSourceFiles: options.serverSourceFiles,
|
|
1072
1097
|
vitePlugins: options.vitePlugins,
|
|
1073
1098
|
navigation: recoveryRoute,
|
|
1074
|
-
status:
|
|
1075
|
-
textFallback: "
|
|
1099
|
+
status: 500,
|
|
1100
|
+
textFallback: "Internal Server Error",
|
|
1076
1101
|
});
|
|
1077
1102
|
emitRenderTiming(options, timing, response.status);
|
|
1078
1103
|
return response;
|
|
1079
1104
|
}
|
|
1080
|
-
|
|
1081
|
-
appDir: options.appDir,
|
|
1082
|
-
filename: "error.mreact.tsx",
|
|
1083
|
-
pageFile: matched.route.file,
|
|
1084
|
-
});
|
|
1085
|
-
options.onRenderError?.(error);
|
|
1086
|
-
const response = await renderSpecialRoute({
|
|
1087
|
-
appDir: options.appDir,
|
|
1088
|
-
assetBaseUrl: options.assetBaseUrl,
|
|
1089
|
-
currentStyleSheets: options.clientStylesByFile?.get(errorFile),
|
|
1090
|
-
error,
|
|
1091
|
-
request: options.request,
|
|
1092
|
-
routePath: matched.route.path,
|
|
1093
|
-
routeFile: errorFile,
|
|
1094
|
-
routeScripts: options.clientScripts,
|
|
1095
|
-
serverModules: options.serverModules,
|
|
1096
|
-
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1097
|
-
serverSourceFiles: options.serverSourceFiles,
|
|
1098
|
-
vitePlugins: options.vitePlugins,
|
|
1099
|
-
navigation: recoveryRoute,
|
|
1100
|
-
status: 500,
|
|
1101
|
-
textFallback: "Internal Server Error",
|
|
1102
|
-
});
|
|
1103
|
-
emitRenderTiming(options, timing, response.status);
|
|
1104
|
-
return response;
|
|
1105
|
-
}
|
|
1106
|
-
finally {
|
|
1107
|
-
await routeCacheContext?.dispose();
|
|
1108
|
-
}
|
|
1105
|
+
})).value;
|
|
1109
1106
|
}
|
|
1110
1107
|
async function applyAppRouterResponseHook(response, options) {
|
|
1111
1108
|
const hooked = await options.onResponse?.(response, {
|