@rsc-kit/core 0.20.2 → 0.20.4
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/earlyHints.d.ts +17 -0
- package/dist/earlyHints.js +65 -0
- package/dist/earlyHints.js.map +1 -0
- package/dist/host.d.ts +10 -4
- package/dist/host.js +54 -2
- package/dist/host.js.map +1 -1
- package/dist/js/DefaultRouteError.js +8 -3
- package/dist/js/DefaultRouteError.js.map +1 -1
- package/dist/js/Link.d.ts +1 -1
- package/dist/js/Link.js +20 -2
- package/dist/js/Link.js.map +1 -1
- package/dist/js/createViteRscApp.js +13 -4
- package/dist/js/createViteRscApp.js.map +1 -1
- package/dist/js/earlyClicks.d.ts +26 -0
- package/dist/js/earlyClicks.js +46 -0
- package/dist/js/earlyClicks.js.map +1 -0
- package/dist/js/navigate.js +33 -10
- package/dist/js/navigate.js.map +1 -1
- package/dist/js/staleAssets.d.ts +10 -0
- package/dist/js/staleAssets.js +27 -6
- package/dist/js/staleAssets.js.map +1 -1
- package/dist/js/viewportPrefetch.d.ts +21 -0
- package/dist/js/viewportPrefetch.js +67 -0
- package/dist/js/viewportPrefetch.js.map +1 -0
- package/dist/vite.js +97 -3
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/dist/vite.js
CHANGED
|
@@ -2264,7 +2264,6 @@ const NITRO_HANDLER_OPTIONS = ` props: (match, request) => ({
|
|
|
2264
2264
|
...match.params,
|
|
2265
2265
|
...Object.fromEntries(new URL(request.url).searchParams),
|
|
2266
2266
|
}),
|
|
2267
|
-
version: process.env.RSC_BUILD_VERSION,
|
|
2268
2267
|
// A built server gzips what it answers, where the runtime can; the dev
|
|
2269
2268
|
// server answers raw, which is what a person reading a response wants.
|
|
2270
2269
|
compress: import.meta.env.PROD,
|
|
@@ -2394,6 +2393,7 @@ import { LoadingBoundary } from ${JSON.stringify(join(packageDir, "js/LoadingBou
|
|
|
2394
2393
|
import { DocumentTitle } from ${JSON.stringify(join(packageDir, "js/DocumentTitle"))}
|
|
2395
2394
|
import { SlotBoundary } from ${JSON.stringify(join(packageDir, "js/SlotBoundary"))}
|
|
2396
2395
|
import { RouteErrorBoundary } from ${JSON.stringify(join(packageDir, "js/RouteErrorBoundary"))}
|
|
2396
|
+
import __rsc_assets from 'virtual:vite-rsc/assets-manifest'
|
|
2397
2397
|
import { sectionComponent } from ${JSON.stringify(join(packageDir, "js/section"))}
|
|
2398
2398
|
import { PathnameProvider } from ${JSON.stringify(join(packageDir, "js/PathnameProvider"))}
|
|
2399
2399
|
import { DefaultRouteError } from ${JSON.stringify(join(packageDir, "js/DefaultRouteError"))}
|
|
@@ -2660,6 +2660,69 @@ export function manifest(): any {
|
|
|
2660
2660
|
return ${JSON.stringify(routeManifest())}
|
|
2661
2661
|
}
|
|
2662
2662
|
|
|
2663
|
+
/**
|
|
2664
|
+
* The stylesheet and the client entry every document of this build links,
|
|
2665
|
+
* from the build's own manifest, for the host's Link header - a CDN sends
|
|
2666
|
+
* it ahead as 103 Early Hints. The root layout's stylesheet is the one the
|
|
2667
|
+
* document carries; the entry's own is usually empty, and either way both
|
|
2668
|
+
* are named. See earlyHints.ts.
|
|
2669
|
+
*/
|
|
2670
|
+
export function criticalAssets(): { styles: string[]; modules: string[]; fonts: string[] } {
|
|
2671
|
+
// Nothing to send ahead in development: the entry is Vite's own url, and
|
|
2672
|
+
// there is no CDN in front to hint.
|
|
2673
|
+
if (import.meta.env.DEV) return { styles: [], modules: [], fonts: [] }
|
|
2674
|
+
|
|
2675
|
+
const manifest = __rsc_assets as {
|
|
2676
|
+
clientEntryUrl?: string
|
|
2677
|
+
clientEntryDeps?: { css?: string[] }
|
|
2678
|
+
serverResources?: Record<string, { css?: string[] }>
|
|
2679
|
+
}
|
|
2680
|
+
const styles = new Set<string>(manifest.clientEntryDeps?.css ?? [])
|
|
2681
|
+
|
|
2682
|
+
const rootLayouts = ['app/layout.tsx', 'app/layout.jsx', 'app/layout.ts', 'app/layout.js']
|
|
2683
|
+
|
|
2684
|
+
for (const [file, resources] of Object.entries(manifest.serverResources ?? {})) {
|
|
2685
|
+
if (rootLayouts.some((name) => file === name || file.endsWith('/' + name))) {
|
|
2686
|
+
for (const href of resources.css ?? []) styles.add(href)
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
return {
|
|
2691
|
+
styles: [...styles],
|
|
2692
|
+
modules: manifest.clientEntryUrl ? [manifest.clientEntryUrl] : [],
|
|
2693
|
+
fonts: [],
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
let cachedBuildId: string | null = null
|
|
2698
|
+
|
|
2699
|
+
/**
|
|
2700
|
+
* What this build's client is, as a short id.
|
|
2701
|
+
*
|
|
2702
|
+
* Derived from the bootstrap script the document ships - the hashed name of
|
|
2703
|
+
* the browser entry, which changes with the client references and chunks
|
|
2704
|
+
* it maps - so two builds whose browsers would disagree never share one.
|
|
2705
|
+
* The host puts it on every answer and compares it against what a client
|
|
2706
|
+
* says it is running; a mismatch on a payload request is a 409, and the
|
|
2707
|
+
* client loads the document instead. Read once, on demand, because the
|
|
2708
|
+
* bootstrap content is a build product this bundle only reaches at runtime.
|
|
2709
|
+
*/
|
|
2710
|
+
export async function buildId(): Promise<string> {
|
|
2711
|
+
if (cachedBuildId !== null) return cachedBuildId
|
|
2712
|
+
|
|
2713
|
+
const content: string = await (import.meta as any).viteRsc.loadBootstrapScriptContent('index')
|
|
2714
|
+
let hash = 2166136261
|
|
2715
|
+
|
|
2716
|
+
for (let i = 0; i < content.length; i++) {
|
|
2717
|
+
hash ^= content.charCodeAt(i)
|
|
2718
|
+
hash = Math.imul(hash, 16777619) >>> 0
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
cachedBuildId = hash.toString(16).padStart(8, '0')
|
|
2722
|
+
|
|
2723
|
+
return cachedBuildId
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2663
2726
|
/**
|
|
2664
2727
|
* For each server action id, whether a client built it. The build asks after
|
|
2665
2728
|
* the bundle exists, because the answer is a mark on the loaded function and
|
|
@@ -3206,6 +3269,15 @@ async function renderTree(
|
|
|
3206
3269
|
if (md.description != null) head.push(createElement('meta', { key: '__d', name: 'description', content: String(md.description) }))
|
|
3207
3270
|
// The name only, never the version - see the identify option.
|
|
3208
3271
|
if (manifest().build?.identify) head.push(createElement('meta', { key: '__g', name: 'generator', content: 'rsc-kit' }))
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
// Which build this document is, for the client to say on every navigation
|
|
3275
|
+
// - read from the document rather than learned from the first answer,
|
|
3276
|
+
// because a document a service worker served from its cache is the last
|
|
3277
|
+
// build's while the answers are this one's. An id, not a version number.
|
|
3278
|
+
if (bootstrap) head.push(createElement('meta', { key: '__v', name: 'rsc-kit:build', content: await buildId() }))
|
|
3279
|
+
|
|
3280
|
+
if (md) {
|
|
3209
3281
|
|
|
3210
3282
|
// robots is a string, or the object Next takes: index and follow as
|
|
3211
3283
|
// their no- forms, the flags by name, the limits as name:value. googleBot
|
|
@@ -4437,6 +4509,8 @@ async function serve(request: Request): Promise<Response> {
|
|
|
4437
4509
|
handleApiRoute,
|
|
4438
4510
|
resolveMetadata,
|
|
4439
4511
|
runRouteMiddleware,
|
|
4512
|
+
buildId,
|
|
4513
|
+
criticalAssets,
|
|
4440
4514
|
} as never,
|
|
4441
4515
|
${NITRO_HANDLER_OPTIONS}${NITRO_PRERENDERED} maxActionBody: ${maxActionBody === undefined ? "undefined" : String(maxActionBody)},
|
|
4442
4516
|
})
|
|
@@ -4520,6 +4594,7 @@ function generateEntrySsr() {
|
|
|
4520
4594
|
const fallbackReport = join(packageDir, "js/fallbackReport");
|
|
4521
4595
|
const redirectDigestModule = join(packageDir, "redirectDigest");
|
|
4522
4596
|
const notFoundModule = join(packageDir, "notFound");
|
|
4597
|
+
const earlyClicks = join(packageDir, "js/earlyClicks");
|
|
4523
4598
|
return `// GENERATED by rscKit() — do not edit.
|
|
4524
4599
|
import { createFromReadableStream } from '@vitejs/plugin-rsc/ssr'
|
|
4525
4600
|
import { renderToReadableStream, resume } from 'react-dom/server.edge'
|
|
@@ -4529,6 +4604,7 @@ import { noteFallback } from ${JSON.stringify(request)}
|
|
|
4529
4604
|
import { cancelledByConsumer, caughtByLoading } from ${JSON.stringify(fallbackReport)}
|
|
4530
4605
|
import { parseRedirectDigest } from ${JSON.stringify(redirectDigestModule)}
|
|
4531
4606
|
import { isNotFoundDigest } from ${JSON.stringify(notFoundModule)}
|
|
4607
|
+
import { EARLY_CLICKS } from ${JSON.stringify(earlyClicks)}
|
|
4532
4608
|
|
|
4533
4609
|
// Set only by the dev server. @vitejs/plugin-rsc emits its bootstrap and CSS
|
|
4534
4610
|
// links root-relative in dev, which would send the browser to the host for
|
|
@@ -4547,8 +4623,11 @@ export async function handleSsr(
|
|
|
4547
4623
|
// Without the bootstrap the page ships no client runtime at all: no React,
|
|
4548
4624
|
// no Flight client, no router. HTML only. A page with nothing interactive on
|
|
4549
4625
|
// it has no use for 70kB of hydration.
|
|
4626
|
+
// The click listener first, then the runtime's import: a tap in the
|
|
4627
|
+
// seconds before the runtime hydrates is held for it rather than given
|
|
4628
|
+
// to the browser as a document load. See earlyClicks.ts.
|
|
4550
4629
|
const bootstrapScriptContent = bootstrap
|
|
4551
|
-
? await (import.meta as any).viteRsc.loadBootstrapScriptContent('index')
|
|
4630
|
+
? EARLY_CLICKS + (await (import.meta as any).viteRsc.loadBootstrapScriptContent('index'))
|
|
4552
4631
|
: undefined
|
|
4553
4632
|
|
|
4554
4633
|
// Without an onError handler React rejects each abortable task on its own,
|
|
@@ -4590,7 +4669,7 @@ export async function handleSsrPrerender(
|
|
|
4590
4669
|
const bootstrapScriptContent =
|
|
4591
4670
|
options.bootstrap === false
|
|
4592
4671
|
? undefined
|
|
4593
|
-
: await (import.meta as any).viteRsc.loadBootstrapScriptContent('index')
|
|
4672
|
+
: EARLY_CLICKS + (await (import.meta as any).viteRsc.loadBootstrapScriptContent('index'))
|
|
4594
4673
|
|
|
4595
4674
|
const { prelude, postponed } = await prerender(root as any, {
|
|
4596
4675
|
bootstrapScriptContent,
|
|
@@ -5420,6 +5499,21 @@ export function rscKit(options = {}) {
|
|
|
5420
5499
|
if (typeof nitro.options.compressPublicAssets !== "object")
|
|
5421
5500
|
nitro.options.compressPublicAssets = true;
|
|
5422
5501
|
nitro.options.virtual ??= {};
|
|
5502
|
+
// The names of functions survive Nitro's bundle. The pages were
|
|
5503
|
+
// prerendered against Vite's own server bundles, where a dependency
|
|
5504
|
+
// is loaded from node_modules under the names it was written with;
|
|
5505
|
+
// Nitro then bundles that dependency into the server, and renames a
|
|
5506
|
+
// function whose name collides with another's - J becomes J2 - and
|
|
5507
|
+
// `name` follows the identifier. React's resume of a stored shell
|
|
5508
|
+
// compares the component names it recorded with the ones it meets,
|
|
5509
|
+
// and a renamed one is "Expected the resume to render <J> in this
|
|
5510
|
+
// slot but instead it rendered <J2>", on every request, with the
|
|
5511
|
+
// hole rendered in the browser instead. keepNames pins `name` to
|
|
5512
|
+
// what the source said, whatever the identifier became.
|
|
5513
|
+
nitro.options.rollupConfig = {
|
|
5514
|
+
...(nitro.options.rollupConfig ?? {}),
|
|
5515
|
+
output: { keepNames: true, ...(nitro.options.rollupConfig?.output ?? {}) },
|
|
5516
|
+
};
|
|
5423
5517
|
// A polyfill a dependency checks for at module evaluation, loaded
|
|
5424
5518
|
// before any service. The bundler places an external import after
|
|
5425
5519
|
// the chunk imports of the module that had it, whatever the source
|