@reckona/mreact-router 0.0.30 → 0.0.32
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/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +21 -21
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/build.d.ts +3 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +141 -94
- package/dist/build.js.map +1 -1
- package/dist/client.d.ts +38 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +430 -94
- package/dist/client.js.map +1 -1
- package/dist/module-runner.d.ts +7 -1
- package/dist/module-runner.d.ts.map +1 -1
- package/dist/module-runner.js +41 -5
- package/dist/module-runner.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +137 -45
- package/dist/render.js.map +1 -1
- package/dist/route-shells.d.ts +9 -0
- package/dist/route-shells.d.ts.map +1 -0
- package/dist/route-shells.js +26 -0
- package/dist/route-shells.js.map +1 -0
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +104 -31
- package/dist/serve.js.map +1 -1
- package/dist/source-modules.d.ts +2 -0
- package/dist/source-modules.d.ts.map +1 -0
- package/dist/source-modules.js +60 -0
- package/dist/source-modules.js.map +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +7 -4
- package/dist/vite.js.map +1 -1
- package/package.json +9 -8
package/dist/render.js
CHANGED
|
@@ -5,19 +5,20 @@ import { dirname, join, relative, sep } from "node:path";
|
|
|
5
5
|
import { transform, } from "@reckona/mreact-compiler";
|
|
6
6
|
import { createQueryClient, dehydrate, __MREACT_QUERY_STATE_SCRIPT_ID, runWithQueryClient, } from "@reckona/mreact-query";
|
|
7
7
|
import { createStringSink, renderAsyncBoundary, renderOutOfOrderReorderScript, renderToReadableStream, } from "@reckona/mreact-server";
|
|
8
|
-
import { hydrationMarkerParts, inferClientRouteModule, routeIdForPath, withHydrationMarkers, withRouteMarkers, } from "./client.js";
|
|
8
|
+
import { createClientRouteInferenceCache, hydrationMarkerParts, formatClientRouteInferenceDiagnostic, inferClientRouteModule, routeIdForPath, withHydrationMarkers, withRouteMarkers, } from "./client.js";
|
|
9
9
|
import { assetPath } from "./assets.js";
|
|
10
10
|
import { escapeHtmlAttribute, escapeHtmlText as escapeHtml, } from "@reckona/mreact-shared/html-escape";
|
|
11
11
|
import { matchRoute, scanAppRoutes } from "./routes.js";
|
|
12
12
|
import { dispatchServerActionRequest, prepareRouteServerActions, serverActionCookie, } from "./actions.js";
|
|
13
13
|
import { beginRouteCacheContext, cachedRouteResponse, cacheRouteResponse, routeCacheKey, routeCachePolicyFromSource, } from "./cache.js";
|
|
14
14
|
import { resolveRouterCacheLimit } from "./cache-config.js";
|
|
15
|
-
import { importAppRouterFileModule, importAppRouterSourceModule } from "./module-runner.js";
|
|
15
|
+
import { importAppRouterBuiltFileModule, importAppRouterFileModule, importAppRouterSourceModule, } from "./module-runner.js";
|
|
16
16
|
import { contentSecurityPolicy } from "./csp.js";
|
|
17
17
|
import { htmlResponse } from "./http.js";
|
|
18
18
|
import { isNotFoundError, isRedirectError, rewriteLocation } from "./navigation.js";
|
|
19
19
|
import { createAppRouterImportPolicyPlugin } from "./import-policy.js";
|
|
20
|
-
import {
|
|
20
|
+
import { existingRouteShellCandidates } from "./route-shells.js";
|
|
21
|
+
import { hasLoaderExport, isStreamRouteSource, stripRouteClientOnlyExports, stripRouteLoaderOnlyExports, stripRouteMetadataOnlyExports, stripRouteModuleExports, } from "./route-source.js";
|
|
21
22
|
import { emitRouterLog, logDurationMs, logNow } from "./logger.js";
|
|
22
23
|
import { createRouterRuntimeCacheCounters, readRouterRuntimeCacheEntry, routerRuntimeCacheStat, } from "./cache-stats.js";
|
|
23
24
|
import { bundleRouterModule } from "./bundle-pipeline.js";
|
|
@@ -29,6 +30,7 @@ const nativeEscapeTransform = {
|
|
|
29
30
|
const authRuntimeStateKey = "__mreactAuthRuntimeState";
|
|
30
31
|
const authSessionScriptId = "__mreact_auth_session";
|
|
31
32
|
export async function preloadBuiltRequestModules(options) {
|
|
33
|
+
const clientRouteInferenceCache = createClientRouteInferenceCache();
|
|
32
34
|
const middlewareFiles = [
|
|
33
35
|
join(options.appDir, "middleware.ts"),
|
|
34
36
|
join(options.appDir, "middleware.mreact.ts"),
|
|
@@ -58,10 +60,12 @@ export async function preloadBuiltRequestModules(options) {
|
|
|
58
60
|
}
|
|
59
61
|
if (options.includeRenderModules !== false) {
|
|
60
62
|
const analysis = await analyzeRouteSource({
|
|
63
|
+
appDir: options.appDir,
|
|
61
64
|
artifact: options.serverModules?.get(route.file)?.analysis,
|
|
62
65
|
code,
|
|
63
66
|
filename: route.file,
|
|
64
67
|
routePath: route.path,
|
|
68
|
+
clientRouteInferenceCache,
|
|
65
69
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
66
70
|
});
|
|
67
71
|
await preloadBuiltPageRouteModules({
|
|
@@ -251,6 +255,19 @@ async function waitForRenderPreload(options, timing) {
|
|
|
251
255
|
finishRenderTimingPhase(timing, phaseStartedAt, "preloadWaitMs");
|
|
252
256
|
}
|
|
253
257
|
}
|
|
258
|
+
async function loadServerRenderArtifacts(options, routeFile, timing) {
|
|
259
|
+
const loader = options.__mreactLoadServerRenderArtifacts;
|
|
260
|
+
if (loader === undefined) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
264
|
+
try {
|
|
265
|
+
await loader(routeFile);
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
finishRenderTimingPhase(timing, phaseStartedAt, "renderArtifactLoadMs");
|
|
269
|
+
}
|
|
270
|
+
}
|
|
254
271
|
function emitRenderTiming(options, timing, status) {
|
|
255
272
|
if (timing === undefined) {
|
|
256
273
|
return;
|
|
@@ -279,6 +296,7 @@ export async function resolveAppRouterMiddleware(options) {
|
|
|
279
296
|
}
|
|
280
297
|
async function renderAppRequestInternal(options) {
|
|
281
298
|
const timing = createRenderTiming(options.logger);
|
|
299
|
+
const clientRouteInferenceCache = createClientRouteInferenceCache();
|
|
282
300
|
let phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
283
301
|
const routes = options.routes ?? (await scanAppRoutes({ appDir: options.appDir }));
|
|
284
302
|
finishRenderTimingPhase(timing, phaseStartedAt, "routeScanMs");
|
|
@@ -400,10 +418,12 @@ async function renderAppRequestInternal(options) {
|
|
|
400
418
|
finishRenderTimingPhase(timing, phaseStartedAt, "readSourceMs");
|
|
401
419
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
402
420
|
const originalAnalysis = await analyzeRouteSource({
|
|
421
|
+
appDir: options.appDir,
|
|
403
422
|
artifact: options.serverModules?.get(matched.route.file)?.analysis,
|
|
404
423
|
code: originalCode,
|
|
405
424
|
filename: matched.route.file,
|
|
406
425
|
routePath: matched.route.path,
|
|
426
|
+
clientRouteInferenceCache,
|
|
407
427
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
408
428
|
timing,
|
|
409
429
|
});
|
|
@@ -438,9 +458,11 @@ async function renderAppRequestInternal(options) {
|
|
|
438
458
|
const routeAnalysis = code === originalCode
|
|
439
459
|
? originalAnalysis
|
|
440
460
|
: await analyzeRouteSource({
|
|
461
|
+
appDir: options.appDir,
|
|
441
462
|
code,
|
|
442
463
|
filename: matched.route.file,
|
|
443
464
|
routePath: matched.route.path,
|
|
465
|
+
clientRouteInferenceCache,
|
|
444
466
|
serverModuleCacheVersion: undefined,
|
|
445
467
|
});
|
|
446
468
|
finishRenderTimingPhase(timing, phaseStartedAt, "routeCodeAnalysisMs");
|
|
@@ -514,6 +536,7 @@ async function renderAppRequestInternal(options) {
|
|
|
514
536
|
return data;
|
|
515
537
|
}
|
|
516
538
|
await waitForRenderPreload(options, timing);
|
|
539
|
+
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
517
540
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
518
541
|
const stringOutput = transformServerModule({
|
|
519
542
|
code: routeCode,
|
|
@@ -570,6 +593,7 @@ async function renderAppRequestInternal(options) {
|
|
|
570
593
|
serverModules: options.serverModules,
|
|
571
594
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
572
595
|
serverSourceFiles: options.serverSourceFiles,
|
|
596
|
+
clientRouteInferenceCache,
|
|
573
597
|
timing,
|
|
574
598
|
}));
|
|
575
599
|
const metadata = await loadComposedRouteMetadata({
|
|
@@ -612,6 +636,7 @@ async function renderAppRequestInternal(options) {
|
|
|
612
636
|
}
|
|
613
637
|
}
|
|
614
638
|
await waitForRenderPreload(options, timing);
|
|
639
|
+
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
615
640
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
616
641
|
const output = transformServerModule({
|
|
617
642
|
code: routeCode,
|
|
@@ -646,6 +671,7 @@ async function renderAppRequestInternal(options) {
|
|
|
646
671
|
serverModules: options.serverModules,
|
|
647
672
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
648
673
|
serverSourceFiles: options.serverSourceFiles,
|
|
674
|
+
clientRouteInferenceCache,
|
|
649
675
|
script: clientScript,
|
|
650
676
|
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
651
677
|
});
|
|
@@ -674,6 +700,7 @@ async function renderAppRequestInternal(options) {
|
|
|
674
700
|
serverModules: options.serverModules,
|
|
675
701
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
676
702
|
serverSourceFiles: options.serverSourceFiles,
|
|
703
|
+
clientRouteInferenceCache,
|
|
677
704
|
clientRoute,
|
|
678
705
|
script: clientScript,
|
|
679
706
|
clientReferenceManifest: output.metadata.clientReferenceManifest,
|
|
@@ -698,6 +725,7 @@ async function renderAppRequestInternal(options) {
|
|
|
698
725
|
return data;
|
|
699
726
|
}
|
|
700
727
|
await waitForRenderPreload(options, timing);
|
|
728
|
+
await loadServerRenderArtifacts(options, matched.route.file, timing);
|
|
701
729
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
702
730
|
const output = transformServerModule({
|
|
703
731
|
code: routeCode,
|
|
@@ -762,6 +790,7 @@ async function renderAppRequestInternal(options) {
|
|
|
762
790
|
serverModules: options.serverModules,
|
|
763
791
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
764
792
|
serverSourceFiles: options.serverSourceFiles,
|
|
793
|
+
clientRouteInferenceCache,
|
|
765
794
|
timing,
|
|
766
795
|
}));
|
|
767
796
|
finishRenderTimingPhase(timing, phaseStartedAt, "layoutRenderMs");
|
|
@@ -1088,6 +1117,13 @@ async function loadServerRouteModule(options) {
|
|
|
1088
1117
|
const code = await readServerSourceFile(options.file, options.serverModuleCacheVersion, options.serverSourceFiles);
|
|
1089
1118
|
const artifactCode = options.serverModules?.get(options.file)?.request;
|
|
1090
1119
|
const codeHash = memoizedHashText(code);
|
|
1120
|
+
if (artifactCode !== undefined && artifactCode.sourceHash === codeHash && artifactCode.moduleFile !== undefined) {
|
|
1121
|
+
return await importBuiltServerModuleFile({
|
|
1122
|
+
file: artifactCode.moduleFile,
|
|
1123
|
+
label: `server-route:${options.file}`,
|
|
1124
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1091
1127
|
const moduleCode = artifactCode !== undefined && artifactCode.sourceHash === codeHash ? artifactCode.code : code;
|
|
1092
1128
|
const cacheKey = `server-route\0${options.file}\0${options.serverModuleCacheVersion}\0${codeHash}\0${memoizedHashText(moduleCode)}`;
|
|
1093
1129
|
const cached = readRouterRuntimeCacheEntry(serverRouteModuleCache, cacheKey, serverRouteModuleCacheCounters);
|
|
@@ -1254,7 +1290,7 @@ async function loadMiddlewareModule(options) {
|
|
|
1254
1290
|
code,
|
|
1255
1291
|
file: options.file,
|
|
1256
1292
|
importPolicy: options.importPolicy,
|
|
1257
|
-
|
|
1293
|
+
prebuiltArtifact: prebuiltRequestModuleArtifact(options.serverModules, options.file, code),
|
|
1258
1294
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1259
1295
|
}).catch((error) => {
|
|
1260
1296
|
if (cacheKey !== undefined) {
|
|
@@ -1287,7 +1323,14 @@ export async function bundleMiddlewareModuleCode(options) {
|
|
|
1287
1323
|
return compiled;
|
|
1288
1324
|
}
|
|
1289
1325
|
async function loadBundledMiddlewareModule(options) {
|
|
1290
|
-
|
|
1326
|
+
if (options.prebuiltArtifact?.moduleFile !== undefined) {
|
|
1327
|
+
return await importBuiltServerModuleFile({
|
|
1328
|
+
file: options.prebuiltArtifact.moduleFile,
|
|
1329
|
+
label: `middleware:${options.file}`,
|
|
1330
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
const compiled = options.prebuiltArtifact?.code ??
|
|
1291
1334
|
(await bundleMiddlewareModuleCode({
|
|
1292
1335
|
appDir: options.appDir,
|
|
1293
1336
|
code: options.code,
|
|
@@ -1416,6 +1459,8 @@ function routeSourceAnalysisFromArtifact(artifact) {
|
|
|
1416
1459
|
async function analyzeRouteSourceUncached(options) {
|
|
1417
1460
|
const routeCode = stripRouteModuleExports(options.code);
|
|
1418
1461
|
const clientInference = await inferClientRouteModule({
|
|
1462
|
+
appDir: options.appDir,
|
|
1463
|
+
cache: options.clientRouteInferenceCache,
|
|
1419
1464
|
code: routeCode,
|
|
1420
1465
|
filename: options.filename,
|
|
1421
1466
|
routePath: options.routePath,
|
|
@@ -1476,6 +1521,15 @@ async function loadServerModule(code, sourcefile, serverModules, serverModuleCac
|
|
|
1476
1521
|
const artifact = serverModules?.get(sourcefile)?.string;
|
|
1477
1522
|
const codeHash = memoizedHashText(code);
|
|
1478
1523
|
const prebuiltCode = prebuiltServerComponentModuleCode(artifact, code, codeHash);
|
|
1524
|
+
if (artifact !== undefined &&
|
|
1525
|
+
prebuiltServerModuleOutputMatches(artifact, code, codeHash) &&
|
|
1526
|
+
artifact.moduleFile !== undefined) {
|
|
1527
|
+
return await importBuiltServerModuleFile({
|
|
1528
|
+
file: artifact.moduleFile,
|
|
1529
|
+
label: `server-component:${sourcefile}`,
|
|
1530
|
+
serverModuleCacheVersion,
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1479
1533
|
const moduleCode = prebuiltCode ?? code;
|
|
1480
1534
|
const cacheKey = serverModuleCacheVersion === undefined
|
|
1481
1535
|
? undefined
|
|
@@ -1501,11 +1555,24 @@ function prebuiltServerComponentModuleCode(artifact, code, codeHash) {
|
|
|
1501
1555
|
if (artifact === undefined) {
|
|
1502
1556
|
return undefined;
|
|
1503
1557
|
}
|
|
1504
|
-
if (artifact
|
|
1558
|
+
if (!prebuiltServerModuleOutputMatches(artifact, code, codeHash)) {
|
|
1505
1559
|
return undefined;
|
|
1506
1560
|
}
|
|
1507
1561
|
return artifact.bundleCode;
|
|
1508
1562
|
}
|
|
1563
|
+
function prebuiltServerModuleOutputMatches(artifact, code, codeHash) {
|
|
1564
|
+
return artifact.sourceHash === codeHash || artifact.code === code;
|
|
1565
|
+
}
|
|
1566
|
+
async function importBuiltServerModuleFile(options) {
|
|
1567
|
+
return await importAppRouterBuiltFileModule({
|
|
1568
|
+
...(options.serverModuleCacheVersion === undefined
|
|
1569
|
+
? {}
|
|
1570
|
+
: {
|
|
1571
|
+
cacheKey: `${options.label}:${options.serverModuleCacheVersion}:${options.file}`,
|
|
1572
|
+
}),
|
|
1573
|
+
file: options.file,
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1509
1576
|
async function loadServerComponent(code, sourcefile, serverModules, serverModuleCacheVersion) {
|
|
1510
1577
|
const module = await loadServerModule(code, sourcefile, serverModules, serverModuleCacheVersion);
|
|
1511
1578
|
return selectServerComponent(module);
|
|
@@ -1535,7 +1602,7 @@ function runServerStreamModule(code, options) {
|
|
|
1535
1602
|
serverModules: options.serverModules,
|
|
1536
1603
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1537
1604
|
});
|
|
1538
|
-
const layoutShells = await layoutShellsForPage(options.appDir, options.pageFile, options.props, slots, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles);
|
|
1605
|
+
const layoutShells = await layoutShellsForPage(options.appDir, options.pageFile, options.props, slots, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles, options.clientRouteInferenceCache);
|
|
1539
1606
|
const marker = options.clientRoute
|
|
1540
1607
|
? hydrationMarkerParts({
|
|
1541
1608
|
assetBaseUrl: options.assetBaseUrl,
|
|
@@ -1668,7 +1735,7 @@ async function runServerStreamModuleWithLoading(code, options) {
|
|
|
1668
1735
|
queryClient: options.queryClient,
|
|
1669
1736
|
request: options.request,
|
|
1670
1737
|
};
|
|
1671
|
-
const layoutShells = await layoutShellsForPage(options.appDir, options.pageFile, loadingProps, {}, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles);
|
|
1738
|
+
const layoutShells = await layoutShellsForPage(options.appDir, options.pageFile, loadingProps, {}, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles, options.clientRouteInferenceCache);
|
|
1672
1739
|
const loadingHtml = await renderServerFileToHtml(options.loadingFile, loadingProps, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles);
|
|
1673
1740
|
const marker = options.clientRoute
|
|
1674
1741
|
? hydrationMarkerParts({
|
|
@@ -1770,6 +1837,15 @@ async function loadServerStreamModule(code, sourcefile, serverModules, serverMod
|
|
|
1770
1837
|
const artifactCode = serverModules?.get(sourcefile)?.stream;
|
|
1771
1838
|
const codeHash = memoizedHashText(code);
|
|
1772
1839
|
const prebuiltCode = prebuiltServerComponentModuleCode(artifactCode, code, codeHash);
|
|
1840
|
+
if (artifactCode !== undefined &&
|
|
1841
|
+
prebuiltServerModuleOutputMatches(artifactCode, code, codeHash) &&
|
|
1842
|
+
artifactCode.moduleFile !== undefined) {
|
|
1843
|
+
return await importBuiltServerModuleFile({
|
|
1844
|
+
file: artifactCode.moduleFile,
|
|
1845
|
+
label: `server-stream-component:${sourcefile}`,
|
|
1846
|
+
serverModuleCacheVersion,
|
|
1847
|
+
});
|
|
1848
|
+
}
|
|
1773
1849
|
const moduleCode = prebuiltCode ?? code;
|
|
1774
1850
|
const cacheKey = serverModuleCacheVersion === undefined
|
|
1775
1851
|
? undefined
|
|
@@ -1803,7 +1879,7 @@ async function applyLayouts(options) {
|
|
|
1803
1879
|
let html = options.html;
|
|
1804
1880
|
const slotContext = createSlotRenderContext(options.slots);
|
|
1805
1881
|
for (const shell of layoutFiles.reverse()) {
|
|
1806
|
-
const rendered = await renderShellPrefixSuffix(options.appDir, shell, options.props, slotContext, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles, options.timing);
|
|
1882
|
+
const rendered = await renderShellPrefixSuffix(options.appDir, shell, options.props, slotContext, options.serverModules, options.serverModuleCacheVersion, options.serverSourceFiles, options.clientRouteInferenceCache, options.timing);
|
|
1807
1883
|
html = `${rendered.prefix}${html}${rendered.suffix}`;
|
|
1808
1884
|
}
|
|
1809
1885
|
warnUnconsumedRouteSlots({
|
|
@@ -1814,12 +1890,12 @@ async function applyLayouts(options) {
|
|
|
1814
1890
|
});
|
|
1815
1891
|
return html;
|
|
1816
1892
|
}
|
|
1817
|
-
async function layoutShellsForPage(appDir, pageFile, props, slots, serverModules, serverModuleCacheVersion, serverSourceFiles) {
|
|
1893
|
+
async function layoutShellsForPage(appDir, pageFile, props, slots, serverModules, serverModuleCacheVersion, serverSourceFiles, clientRouteInferenceCache) {
|
|
1818
1894
|
const layoutFiles = await shellFilesForPage(appDir, pageFile, serverModuleCacheVersion);
|
|
1819
1895
|
const shells = [];
|
|
1820
1896
|
const slotContext = createSlotRenderContext(slots);
|
|
1821
1897
|
for (const shell of layoutFiles) {
|
|
1822
|
-
shells.push(await renderShellPrefixSuffix(appDir, shell, props, slotContext, serverModules, serverModuleCacheVersion, serverSourceFiles));
|
|
1898
|
+
shells.push(await renderShellPrefixSuffix(appDir, shell, props, slotContext, serverModules, serverModuleCacheVersion, serverSourceFiles, clientRouteInferenceCache));
|
|
1823
1899
|
}
|
|
1824
1900
|
warnUnconsumedRouteSlots({
|
|
1825
1901
|
appDir,
|
|
@@ -1829,7 +1905,7 @@ async function layoutShellsForPage(appDir, pageFile, props, slots, serverModules
|
|
|
1829
1905
|
});
|
|
1830
1906
|
return shells;
|
|
1831
1907
|
}
|
|
1832
|
-
async function renderShellPrefixSuffix(appDir, shell, props, slotContext, serverModules, serverModuleCacheVersion, serverSourceFiles, timing) {
|
|
1908
|
+
async function renderShellPrefixSuffix(appDir, shell, props, slotContext, serverModules, serverModuleCacheVersion, serverSourceFiles, clientRouteInferenceCache, timing) {
|
|
1833
1909
|
const hasNamedSlots = Object.keys(slotContext.namedSlots).length > 0;
|
|
1834
1910
|
const cacheKey = serverModuleCacheVersion === undefined || hasNamedSlots || shell.kind === "template"
|
|
1835
1911
|
? undefined
|
|
@@ -1844,8 +1920,20 @@ async function renderShellPrefixSuffix(appDir, shell, props, slotContext, server
|
|
|
1844
1920
|
const code = await readServerSourceFile(shell.file, serverModuleCacheVersion, serverSourceFiles);
|
|
1845
1921
|
addRenderTimingPhaseDuration(timing, phaseStartedAt, "layoutSourceReadMs");
|
|
1846
1922
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
1923
|
+
const artifact = serverModules?.get(shell.file)?.string;
|
|
1924
|
+
const clientInference = artifact !== undefined && artifact.sourceHash === memoizedHashText(code)
|
|
1925
|
+
? { client: false, clientBoundaryImports: [], diagnostics: [] }
|
|
1926
|
+
: await inferClientRouteModule({
|
|
1927
|
+
cache: clientRouteInferenceCache,
|
|
1928
|
+
code: stripRouteClientOnlyExports(code),
|
|
1929
|
+
filename: shell.file,
|
|
1930
|
+
});
|
|
1931
|
+
for (const diagnostic of clientInference.diagnostics) {
|
|
1932
|
+
console.warn(formatClientRouteInferenceDiagnostic(diagnostic));
|
|
1933
|
+
}
|
|
1847
1934
|
const output = transformServerModule({
|
|
1848
1935
|
code,
|
|
1936
|
+
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
1849
1937
|
filename: shell.file,
|
|
1850
1938
|
serverModules,
|
|
1851
1939
|
serverOutput: "string",
|
|
@@ -1930,31 +2018,20 @@ async function shellFilesForPage(appDir, pageFile, serverModuleCacheVersion) {
|
|
|
1930
2018
|
return cached;
|
|
1931
2019
|
}
|
|
1932
2020
|
}
|
|
1933
|
-
const
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
directories.push(join(appDir, ...parts.slice(0, index + 1)));
|
|
1938
|
-
}
|
|
1939
|
-
const files = [];
|
|
1940
|
-
for (const directory of directories) {
|
|
1941
|
-
const shellId = shellBoundaryId(appDir, directory);
|
|
1942
|
-
for (const [filename, kind] of [
|
|
1943
|
-
["layout.tsx", "layout"],
|
|
1944
|
-
["layout.mreact.tsx", "layout"],
|
|
1945
|
-
["template.tsx", "template"],
|
|
1946
|
-
["template.mreact.tsx", "template"],
|
|
1947
|
-
]) {
|
|
1948
|
-
const candidate = join(directory, filename);
|
|
1949
|
-
try {
|
|
1950
|
-
await access(candidate);
|
|
1951
|
-
files.push({ file: candidate, id: shellId, kind });
|
|
1952
|
-
}
|
|
1953
|
-
catch {
|
|
1954
|
-
// Missing shell files are allowed.
|
|
1955
|
-
}
|
|
2021
|
+
const shells = await existingRouteShellCandidates(appDir, pageFile, async (file) => {
|
|
2022
|
+
try {
|
|
2023
|
+
await access(file);
|
|
2024
|
+
return true;
|
|
1956
2025
|
}
|
|
1957
|
-
|
|
2026
|
+
catch {
|
|
2027
|
+
return false;
|
|
2028
|
+
}
|
|
2029
|
+
});
|
|
2030
|
+
const files = shells.map((shell) => ({
|
|
2031
|
+
file: shell.file,
|
|
2032
|
+
id: shellBoundaryId(appDir, shell.directory),
|
|
2033
|
+
kind: shell.kind,
|
|
2034
|
+
}));
|
|
1958
2035
|
if (cacheKey !== undefined) {
|
|
1959
2036
|
if (shellFilesCache.size >= MAX_SHELL_FILES_CACHE_ENTRIES) {
|
|
1960
2037
|
const oldestKey = shellFilesCache.keys().next().value;
|
|
@@ -2238,7 +2315,7 @@ async function loadRouteLoaderModule(options) {
|
|
|
2238
2315
|
}
|
|
2239
2316
|
const loaded = loadBundledRouteLoaderModule({
|
|
2240
2317
|
...options,
|
|
2241
|
-
|
|
2318
|
+
prebuiltArtifact: prebuiltRouteLoaderModuleArtifact(options.serverModules, options.filename, options.code),
|
|
2242
2319
|
}).catch((error) => {
|
|
2243
2320
|
if (cacheKey !== undefined) {
|
|
2244
2321
|
routeLoaderModuleCache.delete(cacheKey);
|
|
@@ -2270,7 +2347,14 @@ export async function bundleRouteLoaderModuleCode(options) {
|
|
|
2270
2347
|
return code;
|
|
2271
2348
|
}
|
|
2272
2349
|
async function loadBundledRouteLoaderModule(options) {
|
|
2273
|
-
|
|
2350
|
+
if (options.prebuiltArtifact?.moduleFile !== undefined) {
|
|
2351
|
+
return await importBuiltServerModuleFile({
|
|
2352
|
+
file: options.prebuiltArtifact.moduleFile,
|
|
2353
|
+
label: `loader:${options.filename}`,
|
|
2354
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2357
|
+
const code = options.prebuiltArtifact?.code ??
|
|
2274
2358
|
(await bundleRouteLoaderModuleCode({
|
|
2275
2359
|
appDir: options.appDir,
|
|
2276
2360
|
code: options.code,
|
|
@@ -2287,17 +2371,17 @@ async function loadBundledRouteLoaderModule(options) {
|
|
|
2287
2371
|
label: `loader:${options.filename}`,
|
|
2288
2372
|
});
|
|
2289
2373
|
}
|
|
2290
|
-
function
|
|
2374
|
+
function prebuiltRequestModuleArtifact(serverModules, file, source, kind = "request") {
|
|
2291
2375
|
const artifact = serverModules?.get(file)?.[kind];
|
|
2292
2376
|
return artifact !== undefined && artifact.sourceHash === memoizedHashText(source)
|
|
2293
|
-
? artifact
|
|
2377
|
+
? artifact
|
|
2294
2378
|
: undefined;
|
|
2295
2379
|
}
|
|
2296
|
-
function
|
|
2380
|
+
function prebuiltRouteLoaderModuleArtifact(serverModules, file, source) {
|
|
2297
2381
|
const artifact = serverModules?.get(file)?.loader;
|
|
2298
2382
|
return artifact !== undefined && artifact.sourceHash === memoizedHashText(source)
|
|
2299
|
-
? artifact
|
|
2300
|
-
:
|
|
2383
|
+
? artifact
|
|
2384
|
+
: prebuiltRequestModuleArtifact(serverModules, file, source);
|
|
2301
2385
|
}
|
|
2302
2386
|
function importPolicyCacheKey(policy) {
|
|
2303
2387
|
if (policy === undefined) {
|
|
@@ -2313,8 +2397,16 @@ async function loadRouteMetadata(options) {
|
|
|
2313
2397
|
if (!hasMetadataExport(options.code)) {
|
|
2314
2398
|
return undefined;
|
|
2315
2399
|
}
|
|
2316
|
-
const
|
|
2317
|
-
|
|
2400
|
+
const prebuiltArtifact = prebuiltRequestModuleArtifact(options.serverModules, options.filename, options.code, "routeMetadata");
|
|
2401
|
+
if (prebuiltArtifact?.moduleFile !== undefined) {
|
|
2402
|
+
const module = await importBuiltServerModuleFile({
|
|
2403
|
+
file: prebuiltArtifact.moduleFile,
|
|
2404
|
+
label: `metadata:${options.filename}`,
|
|
2405
|
+
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
2406
|
+
});
|
|
2407
|
+
return module.metadata;
|
|
2408
|
+
}
|
|
2409
|
+
const code = prebuiltArtifact?.code ?? await bundleRouteMetadataModuleCode(options);
|
|
2318
2410
|
const module = await importAppRouterSourceModule({
|
|
2319
2411
|
...(options.serverModuleCacheVersion === undefined
|
|
2320
2412
|
? {}
|