@rsc-kit/core 0.20.7 → 0.20.10
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/dist/cache.d.ts +11 -0
- package/dist/cache.js +13 -0
- package/dist/cache.js.map +1 -1
- package/dist/clientEntries.js +4 -1
- package/dist/clientEntries.js.map +1 -1
- package/dist/earlyHints.d.ts +14 -2
- package/dist/earlyHints.js +15 -8
- package/dist/earlyHints.js.map +1 -1
- package/dist/files.d.ts +38 -0
- package/dist/files.js +109 -0
- package/dist/files.js.map +1 -1
- package/dist/host.d.ts +11 -2
- package/dist/host.js +38 -8
- package/dist/host.js.map +1 -1
- package/dist/js/ActivityRouter.d.ts +11 -0
- package/dist/js/ActivityRouter.js +19 -4
- package/dist/js/ActivityRouter.js.map +1 -1
- package/dist/js/Form.js +24 -2
- package/dist/js/Form.js.map +1 -1
- package/dist/js/PathnameProvider.d.ts +15 -2
- package/dist/js/PathnameProvider.js +17 -2
- package/dist/js/PathnameProvider.js.map +1 -1
- package/dist/js/SegmentBoundary.js +19 -3
- package/dist/js/SegmentBoundary.js.map +1 -1
- package/dist/js/activityMarkers.d.ts +7 -0
- package/dist/js/activityMarkers.js +18 -0
- package/dist/js/activityMarkers.js.map +1 -0
- package/dist/js/createViteRscApp.js +122 -76
- package/dist/js/createViteRscApp.js.map +1 -1
- package/dist/js/earlyClicks.d.ts +3 -1
- package/dist/js/earlyClicks.js +28 -5
- package/dist/js/earlyClicks.js.map +1 -1
- package/dist/js/errors.d.ts +2 -0
- package/dist/js/errors.js +11 -0
- package/dist/js/errors.js.map +1 -1
- package/dist/js/imagePreload.d.ts +37 -0
- package/dist/js/imagePreload.js +116 -0
- package/dist/js/imagePreload.js.map +1 -0
- package/dist/js/navigate.d.ts +33 -0
- package/dist/js/navigate.js +200 -12
- package/dist/js/navigate.js.map +1 -1
- package/dist/js/segmentStore.d.ts +58 -0
- package/dist/js/segmentStore.js +134 -4
- package/dist/js/segmentStore.js.map +1 -1
- package/dist/js/staleAssets.d.ts +10 -0
- package/dist/js/staleAssets.js +23 -2
- package/dist/js/staleAssets.js.map +1 -1
- package/dist/js/viewportPrefetch.js +27 -2
- package/dist/js/viewportPrefetch.js.map +1 -1
- package/dist/shellHead.d.ts +22 -0
- package/dist/shellHead.js +43 -0
- package/dist/shellHead.js.map +1 -0
- package/dist/vite.js +237 -55
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/dist/host.js
CHANGED
|
@@ -28,6 +28,7 @@ import { compressed } from "./compress.js";
|
|
|
28
28
|
import { withCache } from "./cache.js";
|
|
29
29
|
import { takeAfterWork, withRequest, withResponseDraft } from "./request.js";
|
|
30
30
|
import { criticalAssetsOf, linkHeader, mergeAssets } from "./earlyHints.js";
|
|
31
|
+
import { withHead } from "./shellHead.js";
|
|
31
32
|
/**
|
|
32
33
|
* @internal For a host adapter that embeds the engine. An app imports this
|
|
33
34
|
* from `@rsc-kit/core/redirect` - the one the guides teach, and the one an
|
|
@@ -328,10 +329,23 @@ export function createRscHandler(options) {
|
|
|
328
329
|
return options.props ? await options.props(match, request) : match.params;
|
|
329
330
|
}
|
|
330
331
|
/** The page a server action was invoked from, so it can re-render regions of it. */
|
|
331
|
-
|
|
332
|
+
/** Whether a document at this url is served from the route's pattern shell: no page or shell of its own, and one for the pattern. */
|
|
333
|
+
async function servedFromPatternShell(url, match) {
|
|
334
|
+
const source = options.prerendered;
|
|
335
|
+
if (!source)
|
|
336
|
+
return false;
|
|
337
|
+
const key = pathKey(url.pathname);
|
|
338
|
+
if ((await source(`${key}.html`)) !== null)
|
|
339
|
+
return false;
|
|
340
|
+
if ((await source(`${key}.ppr.html`)) !== null)
|
|
341
|
+
return false;
|
|
342
|
+
return (await source(`${patternKey(match.route)}.ppr.html`)) !== null;
|
|
343
|
+
}
|
|
344
|
+
function pageContext(match, props, url) {
|
|
332
345
|
return {
|
|
333
346
|
component: match.route.component,
|
|
334
347
|
props,
|
|
348
|
+
url,
|
|
335
349
|
layouts: match.route.layouts.map((component) => ({
|
|
336
350
|
component,
|
|
337
351
|
props: {},
|
|
@@ -360,7 +374,6 @@ export function createRscHandler(options) {
|
|
|
360
374
|
/** What a stored document's head names, read once per file, for the Link header. */
|
|
361
375
|
const hinted = new WeakMap();
|
|
362
376
|
const hintsByKey = new Map();
|
|
363
|
-
const EMPTY_ASSETS = { styles: [], modules: [], fonts: [] };
|
|
364
377
|
/**
|
|
365
378
|
* The page a payload url belongs to, if this is one.
|
|
366
379
|
*
|
|
@@ -468,7 +481,7 @@ export function createRscHandler(options) {
|
|
|
468
481
|
// document, stored ones included - a stored document's own head
|
|
469
482
|
// names its fonts; a rendered one's is not known until too late.
|
|
470
483
|
if (response.status === 200 && (response.headers.get("Content-Type") ?? "").startsWith("text/html")) {
|
|
471
|
-
const link = linkHeader(mergeAssets(hinted.get(response) ??
|
|
484
|
+
const link = linkHeader(mergeAssets(hinted.get(response) ?? null, engine.criticalAssets?.() ?? null));
|
|
472
485
|
if (link)
|
|
473
486
|
response.headers.set("Link", link);
|
|
474
487
|
}
|
|
@@ -742,6 +755,13 @@ export function createRscHandler(options) {
|
|
|
742
755
|
});
|
|
743
756
|
}
|
|
744
757
|
const from = sharedDepth(request.headers.get(HEADER.segments), chain);
|
|
758
|
+
// A boot - X-RSC and no segments - of a document served from a pattern
|
|
759
|
+
// shell: the shell was rendered for no url, and the client hydrates
|
|
760
|
+
// this payload against it, so the hooks are told nothing here either
|
|
761
|
+
// and read the browser's url once hydration is done. A navigation to
|
|
762
|
+
// the same url renders for it, as it is client-rendered, not hydrated.
|
|
763
|
+
const boot = request.headers.get(HEADER.segments) === null;
|
|
764
|
+
const pathname = boot && (await servedFromPatternShell(url, match)) ? null : url.pathname;
|
|
745
765
|
// Proposed by the host, decided by the engine: an interceptor can force a
|
|
746
766
|
// wider render than the client asked for, so what goes back is the depth
|
|
747
767
|
// that came out, never the one that went in.
|
|
@@ -749,7 +769,7 @@ export function createRscHandler(options) {
|
|
|
749
769
|
let stream;
|
|
750
770
|
let segmentDepth;
|
|
751
771
|
try {
|
|
752
|
-
({ stream, segmentDepth } = await engine.handleRscStream(match.route.component, props, layouts, match.route.loadings, match.route.slots, {}, from, url.pathname));
|
|
772
|
+
({ stream, segmentDepth } = await engine.handleRscStream(match.route.component, props, layouts, match.route.loadings, match.route.slots, {}, from, url.pathname, pathname));
|
|
753
773
|
}
|
|
754
774
|
catch (error) {
|
|
755
775
|
// Same reasoning as the document path: what the render recorded is
|
|
@@ -940,7 +960,7 @@ export function createRscHandler(options) {
|
|
|
940
960
|
const state = shellKey === null ? null : await read(`${shellKey}.postponed.json`);
|
|
941
961
|
if (state === null)
|
|
942
962
|
return new Response("Nothing to resume", { status: 404 });
|
|
943
|
-
const { htmlStream } = await engine.handleRscResume(route.route.component, route.params, route.route.layouts.map((component) => ({ component, props: {} })), route.route.loadings, route.route.slots, {}, JSON.parse(state), undefined, shellKey === key ? pathname : "");
|
|
963
|
+
const { htmlStream } = await engine.handleRscResume(route.route.component, route.params, route.route.layouts.map((component) => ({ component, props: {} })), route.route.loadings, route.route.slots, {}, JSON.parse(state), undefined, shellKey === key ? pathname : "", pathname);
|
|
944
964
|
// Carries the build version so a caller holding a cached shell can tell
|
|
945
965
|
// that it no longer belongs to this origin. A shell from an older build
|
|
946
966
|
// does not make the resume fail — it replays against slots that have moved
|
|
@@ -1024,13 +1044,23 @@ export function createRscHandler(options) {
|
|
|
1024
1044
|
// A shell found under the route's pattern was frozen for no particular
|
|
1025
1045
|
// url, so it was rendered with no page key. Handing one over now would
|
|
1026
1046
|
// key the tree differently from the one being resumed.
|
|
1027
|
-
shellKey === key ? url.pathname : ""
|
|
1047
|
+
shellKey === key ? url.pathname : "",
|
|
1048
|
+
// But the url itself, for the hooks: the holes are rendered for it.
|
|
1049
|
+
url.pathname);
|
|
1050
|
+
// A shell stored for the pattern was built without a url, so its title
|
|
1051
|
+
// is the layouts' - the page's generateMetadata reads the params and
|
|
1052
|
+
// was left out. This request has the params.
|
|
1053
|
+
const served = shellKey === key || !engine.resolveMetadata
|
|
1054
|
+
? shell
|
|
1055
|
+
: withHead(shell, await engine
|
|
1056
|
+
.resolveMetadata(route.route.component, route.params, route.route.layouts.map((component) => ({ component, props: {} })))
|
|
1057
|
+
.catch(() => null));
|
|
1028
1058
|
// The shell first, then whatever the resume writes. React's own script
|
|
1029
1059
|
// travels with the resumed segments and moves them into place, so this is
|
|
1030
1060
|
// a plain concatenation and the holes land without hydration.
|
|
1031
1061
|
const body = new ReadableStream({
|
|
1032
1062
|
async start(controller) {
|
|
1033
|
-
controller.enqueue(new TextEncoder().encode(
|
|
1063
|
+
controller.enqueue(new TextEncoder().encode(served));
|
|
1034
1064
|
const reader = htmlStream.getReader();
|
|
1035
1065
|
try {
|
|
1036
1066
|
while (true) {
|
|
@@ -1392,7 +1422,7 @@ export function createRscHandler(options) {
|
|
|
1392
1422
|
const from = refererPath(request.headers.get(HEADER.referer), url.origin, siteHosts);
|
|
1393
1423
|
const match = from ? matchRoute(routes, from) : null;
|
|
1394
1424
|
const page = match
|
|
1395
|
-
? pageContext(match, await propsFor(match, request))
|
|
1425
|
+
? pageContext(match, await propsFor(match, request), from ?? undefined)
|
|
1396
1426
|
: undefined;
|
|
1397
1427
|
// Scoped to this action: revalidate() called anywhere inside it, at any
|
|
1398
1428
|
// depth, marks here and nowhere else — two requests can be in flight and
|