@reckona/mreact-router 0.0.202 → 0.0.203
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 +5 -2
- package/dist/actions.d.ts +2 -3
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +61 -41
- package/dist/actions.js.map +1 -1
- package/dist/adapters/cloudflare.d.ts +3 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +26 -10
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/build.d.ts +3 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +98 -12
- package/dist/build.js.map +1 -1
- package/dist/cache.d.ts +1 -1
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +5 -4
- package/dist/cache.js.map +1 -1
- package/dist/cli-options.d.ts +3 -0
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +10 -2
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -2
- package/dist/client.js.map +1 -1
- package/dist/navigation-marker.d.ts +2 -0
- package/dist/navigation-marker.d.ts.map +1 -0
- package/dist/navigation-marker.js +294 -0
- package/dist/navigation-marker.js.map +1 -0
- package/dist/navigation-runtime.d.ts +1 -1
- package/dist/navigation-runtime.d.ts.map +1 -1
- package/dist/navigation-runtime.js +1 -1
- package/dist/navigation-runtime.js.map +1 -1
- package/dist/prerender-entry.d.ts +3 -1
- package/dist/prerender-entry.d.ts.map +1 -1
- package/dist/prerender-entry.js +61 -3
- package/dist/prerender-entry.js.map +1 -1
- package/dist/render.d.ts +7 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +51 -23
- package/dist/render.js.map +1 -1
- package/dist/serve.d.ts +3 -0
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +54 -30
- package/dist/serve.js.map +1 -1
- package/package.json +11 -11
- package/src/actions.ts +72 -56
- package/src/adapters/cloudflare.ts +40 -10
- package/src/build.ts +107 -10
- package/src/cache.ts +10 -4
- package/src/cli-options.ts +15 -2
- package/src/cli.ts +2 -1
- package/src/client.ts +15 -2
- package/src/navigation-marker.ts +353 -0
- package/src/navigation-runtime.ts +1 -0
- package/src/prerender-entry.ts +78 -5
- package/src/render.ts +80 -24
- package/src/serve.ts +71 -34
package/dist/render.js
CHANGED
|
@@ -7,7 +7,7 @@ import { formatDiagnostic, transform } from "@reckona/mreact-compiler";
|
|
|
7
7
|
import { createQueryClient, dehydrate, __MREACT_QUERY_STATE_SCRIPT_ID, installQueryAsyncStorage, runWithQueryClient, } from "@reckona/mreact-query";
|
|
8
8
|
import { createStringSink, renderAsyncBoundary, renderOutOfOrderReorderScript, renderReactNodeToString, renderToReadableStream, } from "@reckona/mreact-server";
|
|
9
9
|
import { createClientRouteInferenceCache, formatClientRouteInferenceDiagnostic, inferClientRouteModule, } from "./client-route-inference.js";
|
|
10
|
-
import { hydrationMarkerParts, routeIdForPath, withHydrationMarkers,
|
|
10
|
+
import { hydrationMarkerParts, routeMarkerParts, routeIdForPath, withHydrationMarkers, } from "./navigation-runtime.js";
|
|
11
11
|
import { assetPath } from "./assets.js";
|
|
12
12
|
import { escapeHtmlAttribute } from "@reckona/mreact-shared/html-escape";
|
|
13
13
|
import { matchRoute, scanAppRoutes } from "./routes.js";
|
|
@@ -493,6 +493,7 @@ async function renderAppRequestInternal(options) {
|
|
|
493
493
|
let trackedRequest;
|
|
494
494
|
let sourceUsesRequestInput = true;
|
|
495
495
|
let invalidConfiguredHsts = false;
|
|
496
|
+
let renderedStrictTransportSecurity;
|
|
496
497
|
return (await withRouteCacheContext(options.routeCache, async () => {
|
|
497
498
|
try {
|
|
498
499
|
if (matched.route.kind === "asset") {
|
|
@@ -561,7 +562,8 @@ async function renderAppRequestInternal(options) {
|
|
|
561
562
|
finishRenderTimingPhase(timing, phaseStartedAt, "sourceAnalysisMs");
|
|
562
563
|
const cachePolicy = originalAnalysis.cachePolicy;
|
|
563
564
|
const navigationScript = options.navigationScripts?.get(matched.route.path);
|
|
564
|
-
const
|
|
565
|
+
const navigationRequest = isNavigationRequest(options.request);
|
|
566
|
+
const cacheKey = routeCacheKey(options.appDir, matched.route.path, url, navigationRequest ? "navigation" : "document");
|
|
565
567
|
const mayUseRouteCache = !sourceUsesRequestInput &&
|
|
566
568
|
(cachePolicy === undefined
|
|
567
569
|
? originalAnalysis.usesRuntimeCacheControl
|
|
@@ -655,7 +657,7 @@ async function renderAppRequestInternal(options) {
|
|
|
655
657
|
clientRoute,
|
|
656
658
|
props: {
|
|
657
659
|
params: matched.params,
|
|
658
|
-
request: { url:
|
|
660
|
+
request: { url: url.pathname },
|
|
659
661
|
},
|
|
660
662
|
routePath: matched.route.path,
|
|
661
663
|
script: clientScript,
|
|
@@ -728,16 +730,11 @@ async function renderAppRequestInternal(options) {
|
|
|
728
730
|
script: clientScript,
|
|
729
731
|
props: {
|
|
730
732
|
params: matched.params,
|
|
731
|
-
request: { url:
|
|
733
|
+
request: { url: url.pathname },
|
|
732
734
|
data,
|
|
733
735
|
},
|
|
734
736
|
})
|
|
735
|
-
:
|
|
736
|
-
? withRouteMarkers({
|
|
737
|
-
html: pageHtml,
|
|
738
|
-
routePath: matched.route.path,
|
|
739
|
-
})
|
|
740
|
-
: pageHtml;
|
|
737
|
+
: withServerOnlyRouteMarkers(pageHtml, matched.route.path, options.request);
|
|
741
738
|
let html = await runWithQueryClient(queryClient, () => applyLayouts({
|
|
742
739
|
appDir: options.appDir,
|
|
743
740
|
pageFile: matched.route.file,
|
|
@@ -782,7 +779,7 @@ async function renderAppRequestInternal(options) {
|
|
|
782
779
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
783
780
|
});
|
|
784
781
|
html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
|
|
785
|
-
html = injectQueryState(html, dehydrate(queryClient));
|
|
782
|
+
html = injectQueryState(html, dehydrate(queryClient, options.dehydrateOptions));
|
|
786
783
|
const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
|
|
787
784
|
assetBaseUrl: options.assetBaseUrl,
|
|
788
785
|
currentStyleSheets: clientStyleSheets,
|
|
@@ -794,6 +791,7 @@ async function renderAppRequestInternal(options) {
|
|
|
794
791
|
"x-mreact-stream": "1",
|
|
795
792
|
}),
|
|
796
793
|
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
794
|
+
appendNavigationVary(response.headers);
|
|
797
795
|
emitRenderTiming(options, timing, response.status);
|
|
798
796
|
return response;
|
|
799
797
|
}
|
|
@@ -860,10 +858,12 @@ async function renderAppRequestInternal(options) {
|
|
|
860
858
|
data: streamDataPromise,
|
|
861
859
|
define: options.define,
|
|
862
860
|
loadingFile,
|
|
861
|
+
markerRequest: options.request,
|
|
863
862
|
pageFile: matched.route.file,
|
|
864
863
|
params: matched.params,
|
|
865
864
|
queryClient,
|
|
866
865
|
request: appRequest,
|
|
866
|
+
requestUrl: url.pathname,
|
|
867
867
|
trackedRequest,
|
|
868
868
|
routePath: matched.route.path,
|
|
869
869
|
routeScripts: options.clientScripts,
|
|
@@ -880,6 +880,7 @@ async function renderAppRequestInternal(options) {
|
|
|
880
880
|
const response = withOptionalActionCookie(new Response(stream, {
|
|
881
881
|
headers: streamShellResponseHeaders,
|
|
882
882
|
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
883
|
+
appendNavigationVary(response.headers);
|
|
883
884
|
emitRenderTiming(options, timing, response.status);
|
|
884
885
|
return response;
|
|
885
886
|
}
|
|
@@ -894,7 +895,9 @@ async function renderAppRequestInternal(options) {
|
|
|
894
895
|
appDir: options.appDir,
|
|
895
896
|
assetBaseUrl: options.assetBaseUrl,
|
|
896
897
|
pageFile: matched.route.file,
|
|
898
|
+
markerRequest: options.request,
|
|
897
899
|
props,
|
|
900
|
+
requestUrl: url.pathname,
|
|
898
901
|
routePath: matched.route.path,
|
|
899
902
|
routeScripts: options.clientScripts,
|
|
900
903
|
serverModules: options.serverModules,
|
|
@@ -912,6 +915,7 @@ async function renderAppRequestInternal(options) {
|
|
|
912
915
|
const response = withOptionalActionCookie(new Response(stream, {
|
|
913
916
|
headers: streamShellResponseHeaders,
|
|
914
917
|
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
918
|
+
appendNavigationVary(response.headers);
|
|
915
919
|
emitRenderTiming(options, timing, response.status);
|
|
916
920
|
return response;
|
|
917
921
|
}
|
|
@@ -974,16 +978,11 @@ async function renderAppRequestInternal(options) {
|
|
|
974
978
|
script: clientScript,
|
|
975
979
|
props: {
|
|
976
980
|
params: matched.params,
|
|
977
|
-
request: { url:
|
|
981
|
+
request: { url: url.pathname },
|
|
978
982
|
data,
|
|
979
983
|
},
|
|
980
984
|
})
|
|
981
|
-
:
|
|
982
|
-
? withRouteMarkers({
|
|
983
|
-
html: pageHtml,
|
|
984
|
-
routePath: matched.route.path,
|
|
985
|
-
})
|
|
986
|
-
: pageHtml;
|
|
985
|
+
: withServerOnlyRouteMarkers(pageHtml, matched.route.path, options.request);
|
|
987
986
|
phaseStartedAt = renderTimingPhaseStartedAt(timing);
|
|
988
987
|
let html = await runWithQueryClient(queryClient, () => applyLayouts({
|
|
989
988
|
appDir: options.appDir,
|
|
@@ -1032,7 +1031,7 @@ async function renderAppRequestInternal(options) {
|
|
|
1032
1031
|
serverModuleCacheVersion: options.serverModuleCacheVersion,
|
|
1033
1032
|
});
|
|
1034
1033
|
html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
|
|
1035
|
-
html = injectQueryState(html, dehydrate(queryClient));
|
|
1034
|
+
html = injectQueryState(html, dehydrate(queryClient, options.dehydrateOptions));
|
|
1036
1035
|
const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
|
|
1037
1036
|
assetBaseUrl: options.assetBaseUrl,
|
|
1038
1037
|
currentStyleSheets: clientStyleSheets,
|
|
@@ -1042,8 +1041,10 @@ async function renderAppRequestInternal(options) {
|
|
|
1042
1041
|
})}${html}`, preparedActions.htmlReplacements), {
|
|
1043
1042
|
headers: responseHeadersForMetadata(metadata, options.request),
|
|
1044
1043
|
}), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
|
|
1044
|
+
appendNavigationVary(response.headers);
|
|
1045
1045
|
const effectiveCachePolicy = cachePolicy ?? activeRouteCacheContext()?.cachePolicy;
|
|
1046
1046
|
const configuredHsts = configuredHstsHeader(metadata?.security);
|
|
1047
|
+
renderedStrictTransportSecurity = configuredHsts;
|
|
1047
1048
|
invalidConfiguredHsts = hasInvalidConfiguredHsts(metadata?.security);
|
|
1048
1049
|
const finalResponse = preparedActions.hasFormActions
|
|
1049
1050
|
? withRouteCacheHeader(response, effectiveCachePolicy)
|
|
@@ -1137,6 +1138,7 @@ async function renderAppRequestInternal(options) {
|
|
|
1137
1138
|
if (options.renderSignals !== undefined) {
|
|
1138
1139
|
const tracked = trackedRequest;
|
|
1139
1140
|
options.renderSignals.headerDependent = () => sourceUsesRequestInput || invalidConfiguredHsts || (tracked?.requestDependent() ?? true);
|
|
1141
|
+
options.renderSignals.strictTransportSecurity = () => renderedStrictTransportSecurity;
|
|
1140
1142
|
}
|
|
1141
1143
|
}
|
|
1142
1144
|
})).value;
|
|
@@ -1274,6 +1276,32 @@ function routePrefetchManifestScript(routeScripts, assetBaseUrl) {
|
|
|
1274
1276
|
function isNavigationRequest(request) {
|
|
1275
1277
|
return request.headers.get("x-mreact-navigation") === "1";
|
|
1276
1278
|
}
|
|
1279
|
+
function withServerOnlyRouteMarkers(html, routePath, request) {
|
|
1280
|
+
const marker = serverOnlyRouteMarkerParts(routePath, request);
|
|
1281
|
+
return marker === undefined ? html : `${marker.prefix}${html}${marker.suffix}`;
|
|
1282
|
+
}
|
|
1283
|
+
function serverOnlyRouteMarkerParts(routePath, request) {
|
|
1284
|
+
if (request.headers.get("x-mreact-prerender-variant-capture") === "1") {
|
|
1285
|
+
return prerenderVariantMarkerParts(routePath);
|
|
1286
|
+
}
|
|
1287
|
+
return isNavigationRequest(request) ? routeMarkerParts(routePath) : undefined;
|
|
1288
|
+
}
|
|
1289
|
+
export function prerenderVariantMarkerParts(routePath) {
|
|
1290
|
+
const routeId = routeIdForPath(routePath);
|
|
1291
|
+
return {
|
|
1292
|
+
prefix: `<!--mreact-route-variant-start:${routeId}-->`,
|
|
1293
|
+
suffix: `<!--mreact-route-variant-end:${routeId}-->`,
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
function appendNavigationVary(headers) {
|
|
1297
|
+
const vary = headers.get("vary");
|
|
1298
|
+
if (vary
|
|
1299
|
+
?.split(",")
|
|
1300
|
+
.some((value) => value.trim().toLowerCase() === "x-mreact-navigation") === true) {
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
headers.append("vary", "x-mreact-navigation");
|
|
1304
|
+
}
|
|
1277
1305
|
function isNavigationRouteCacheReloadRequest(request) {
|
|
1278
1306
|
return (isNavigationRequest(request) && request.headers.get("x-mreact-navigation-cache") === "reload");
|
|
1279
1307
|
}
|
|
@@ -2184,11 +2212,11 @@ function runServerStreamModule(code, options) {
|
|
|
2184
2212
|
script: options.script,
|
|
2185
2213
|
props: {
|
|
2186
2214
|
params: options.props.params,
|
|
2187
|
-
request: { url: options.
|
|
2215
|
+
request: { url: options.requestUrl },
|
|
2188
2216
|
data: options.props.data,
|
|
2189
2217
|
},
|
|
2190
2218
|
})
|
|
2191
|
-
:
|
|
2219
|
+
: serverOnlyRouteMarkerParts(options.routePath, options.markerRequest);
|
|
2192
2220
|
sink.append("<!DOCTYPE html>");
|
|
2193
2221
|
sink.append(clientNavigationHeadTags({
|
|
2194
2222
|
assetBaseUrl: options.assetBaseUrl,
|
|
@@ -2317,10 +2345,10 @@ async function runServerStreamModuleWithLoading(code, options) {
|
|
|
2317
2345
|
script: options.script,
|
|
2318
2346
|
props: {
|
|
2319
2347
|
params: options.params,
|
|
2320
|
-
request: { url: options.
|
|
2348
|
+
request: { url: options.requestUrl },
|
|
2321
2349
|
},
|
|
2322
2350
|
})
|
|
2323
|
-
:
|
|
2351
|
+
: serverOnlyRouteMarkerParts(options.routePath, options.markerRequest);
|
|
2324
2352
|
return renderToReadableStream((sink) => {
|
|
2325
2353
|
sink.append("<!DOCTYPE html>");
|
|
2326
2354
|
sink.append(clientNavigationHeadTags({
|