@rsc-kit/core 0.29.3 → 0.29.5
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/export.js +6 -0
- package/dist/export.js.map +1 -1
- package/dist/files.d.ts +20 -0
- package/dist/files.js +53 -0
- package/dist/files.js.map +1 -1
- package/dist/host.js +18 -2
- package/dist/host.js.map +1 -1
- package/dist/vite.js +67 -9
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/dist/vite.js
CHANGED
|
@@ -1705,7 +1705,11 @@ async function prerenderAfterBundles(bundle, staticDir, assetsDir, knownActions
|
|
|
1705
1705
|
const writesSitemap = manifest.apis?.some((api) => api.name === "app/sitemap.xml/route");
|
|
1706
1706
|
const hasSitemapFile = rootFiles.includes("sitemap.xml");
|
|
1707
1707
|
if (!writesSitemap && !hasSitemapFile) {
|
|
1708
|
-
|
|
1708
|
+
// The source first, then the app itself: a metadataBase computed from
|
|
1709
|
+
// the environment - new URL(process.env.SITE_URL) - is not a literal the
|
|
1710
|
+
// source can be read for, but the bundle is loaded by now and knows it.
|
|
1711
|
+
const base = rootMetadataBase(join(sourceDir, "app")) ??
|
|
1712
|
+
(await loadedMetadataBase(engine, manifest));
|
|
1709
1713
|
if (base) {
|
|
1710
1714
|
const xml = automaticSitemap(results, manifest.routes, base);
|
|
1711
1715
|
const stored = JSON.stringify({
|
|
@@ -1728,7 +1732,9 @@ async function prerenderAfterBundles(bundle, staticDir, assetsDir, knownActions
|
|
|
1728
1732
|
line: " - /sitemap.xml",
|
|
1729
1733
|
bytes: null,
|
|
1730
1734
|
extra: [
|
|
1731
|
-
|
|
1735
|
+
rootMentionsMetadataBase(join(sourceDir, "app"))
|
|
1736
|
+
? " not written: the root layout's metadataBase gave no url at build time - is the variable it reads set for the build?"
|
|
1737
|
+
: " not written: the root layout has no metadataBase to make the urls absolute",
|
|
1732
1738
|
],
|
|
1733
1739
|
});
|
|
1734
1740
|
}
|
|
@@ -1830,8 +1836,6 @@ ${legend(counted)}
|
|
|
1830
1836
|
"reachable from the build. Give it that, or mark the read with `await connection()`\n" +
|
|
1831
1837
|
"so the page renders per request and the rest of it is still stored.");
|
|
1832
1838
|
}
|
|
1833
|
-
if (output === "export")
|
|
1834
|
-
await exportAfterPrerender(results, staticDir, assetsDir);
|
|
1835
1839
|
// The urls whose answer cannot change until the next build. The service
|
|
1836
1840
|
// worker serves these from its cache first rather than asking the network
|
|
1837
1841
|
// and falling back — see writeServiceWorker.
|
|
@@ -1916,20 +1920,41 @@ function weighClientJs(assetsDir) {
|
|
|
1916
1920
|
* page that loads and then stays empty forever.
|
|
1917
1921
|
*/
|
|
1918
1922
|
async function exportAfterPrerender(results, staticDir, assetsDir) {
|
|
1919
|
-
const [{ exportSite, NotExportable }, { writeTo, prerenderedFrom,
|
|
1923
|
+
const [{ exportSite, NotExportable }, { writeTo, prerenderedFrom, copyPublic, exportStoredAnswers },] = await Promise.all([import("./export.js"), import("./files.js")]);
|
|
1920
1924
|
try {
|
|
1921
1925
|
const { pages, refused } = await exportSite({
|
|
1922
1926
|
results,
|
|
1923
1927
|
read: prerenderedFrom(staticDir),
|
|
1924
1928
|
write: writeTo(exportPath),
|
|
1925
1929
|
manifest: routeManifest(),
|
|
1926
|
-
|
|
1930
|
+
// Every file a server would have answered as a file: the app's own
|
|
1931
|
+
// public/ - which Nitro copies itself, so it is not in the client
|
|
1932
|
+
// output - and then the client output, not only assets/: the icons and
|
|
1933
|
+
// share image, the web manifest, the service worker.
|
|
1934
|
+
assets: async () => {
|
|
1935
|
+
const own = join(projectRoot, "public");
|
|
1936
|
+
if (existsSync(own))
|
|
1937
|
+
await copyPublic(own, exportPath)();
|
|
1938
|
+
await copyPublic(assetsDir, exportPath)();
|
|
1939
|
+
},
|
|
1927
1940
|
force: process.env.RSC_EXPORT_FORCE === "1",
|
|
1928
1941
|
});
|
|
1929
1942
|
console.log(`\n Exported ${pages} page${pages === 1 ? "" : "s"} to ${relative(projectRoot, exportPath)}`);
|
|
1930
1943
|
if (refused.length > 0) {
|
|
1931
1944
|
console.log(` Left out ${refused.length}: ${refused.map((r) => r.url).join(", ")}`);
|
|
1932
1945
|
}
|
|
1946
|
+
// Stored route.ts answers - robots.txt, sitemap.xml, a JSON feed - as
|
|
1947
|
+
// the files they are. A static host types a file by its extension, so an
|
|
1948
|
+
// answer at a url without one cannot keep its content type: said, not
|
|
1949
|
+
// written as something it was not.
|
|
1950
|
+
const answers = await exportStoredAnswers(staticDir, exportPath);
|
|
1951
|
+
if (answers.written.length > 0) {
|
|
1952
|
+
console.log(` Exported ${answers.written.length} route answer${answers.written.length === 1 ? "" : "s"}: ${answers.written.join(", ")}`);
|
|
1953
|
+
}
|
|
1954
|
+
if (answers.skipped.length > 0) {
|
|
1955
|
+
console.log(` Left out ${answers.skipped.length} route answer${answers.skipped.length === 1 ? "" : "s"}: ` +
|
|
1956
|
+
answers.skipped.map((s) => `${s.url} (${s.why})`).join(", "));
|
|
1957
|
+
}
|
|
1933
1958
|
}
|
|
1934
1959
|
catch (error) {
|
|
1935
1960
|
if (!(error instanceof NotExportable))
|
|
@@ -2540,6 +2565,28 @@ function discover(dir) {
|
|
|
2540
2565
|
* generateStaticParams is detected by reading. A `new URL('…')` or a string
|
|
2541
2566
|
* literal; anything computed is not seen, and rscKit({ hosts }) says it.
|
|
2542
2567
|
*/
|
|
2568
|
+
/** The root layout's metadataBase as the loaded app has it, whatever it was computed from. */
|
|
2569
|
+
async function loadedMetadataBase(engine, manifest) {
|
|
2570
|
+
const resolve = engine
|
|
2571
|
+
.resolveMetadata;
|
|
2572
|
+
const root = manifest.routes.find((r) => r.layouts?.length)?.layouts?.[0];
|
|
2573
|
+
if (!resolve || !root)
|
|
2574
|
+
return null;
|
|
2575
|
+
try {
|
|
2576
|
+
const base = (await resolve(root, {}, []))?.metadataBase;
|
|
2577
|
+
return base ? String(base) : null;
|
|
2578
|
+
}
|
|
2579
|
+
catch {
|
|
2580
|
+
return null;
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
/** Whether the root layout sets a metadataBase at all, literal or not. */
|
|
2584
|
+
function rootMentionsMetadataBase(appDir) {
|
|
2585
|
+
const layout = ["layout.tsx", "layout.jsx", "layout.ts", "layout.js"]
|
|
2586
|
+
.map((name) => join(appDir, name))
|
|
2587
|
+
.find((file) => existsSync(file));
|
|
2588
|
+
return layout ? /\bmetadataBase\b/.test(readFileSync(layout, "utf-8")) : false;
|
|
2589
|
+
}
|
|
2543
2590
|
function rootMetadataBase(appDir) {
|
|
2544
2591
|
const layout = ["layout.tsx", "layout.jsx", "layout.ts", "layout.js"]
|
|
2545
2592
|
.map((name) => join(appDir, name))
|
|
@@ -5029,7 +5076,7 @@ export async function handleRsc(
|
|
|
5029
5076
|
* export. Parsed by splitting rather than matching, because this function is
|
|
5030
5077
|
* emitted into a template literal where a regex would need double escaping.
|
|
5031
5078
|
*/
|
|
5032
|
-
function clientReferenceNames(payload: string): string[] {
|
|
5079
|
+
export function clientReferenceNames(payload: string): string[] {
|
|
5033
5080
|
const names = new Set<string>()
|
|
5034
5081
|
|
|
5035
5082
|
// A string React has already sent is referenced by row - "$1" for the
|
|
@@ -5038,8 +5085,12 @@ function clientReferenceNames(payload: string): string[] {
|
|
|
5038
5085
|
// way and has to be looked up, or the refusal names a component "$1".
|
|
5039
5086
|
const strings = new Map<string, string>()
|
|
5040
5087
|
|
|
5088
|
+
// Row ids are hexadecimal: row 26 is "1a", referenced as "$1a". Matched
|
|
5089
|
+
// as decimal, every reference past row 9 stayed unresolved, read as an
|
|
5090
|
+
// app's client component, and a page with nothing interactive on it
|
|
5091
|
+
// shipped the whole runtime.
|
|
5041
5092
|
for (const line of payload.split('\\n')) {
|
|
5042
|
-
const match = /^(
|
|
5093
|
+
const match = /^([0-9a-f]+):"(.*)"$/.exec(line)
|
|
5043
5094
|
if (match) strings.set('$' + match[1], match[2]!)
|
|
5044
5095
|
}
|
|
5045
5096
|
|
|
@@ -5058,7 +5109,9 @@ function clientReferenceNames(payload: string): string[] {
|
|
|
5058
5109
|
* A page with one needs the runtime to submit it.
|
|
5059
5110
|
*/
|
|
5060
5111
|
export function hasServerReference(payload: string): boolean {
|
|
5061
|
-
|
|
5112
|
+
// Hexadecimal row ids, as above: a server reference in row 1a was missed,
|
|
5113
|
+
// and its page stored without the runtime its form needs.
|
|
5114
|
+
return /^[0-9a-f]+:\\{"id":"[^"]+","bound":/m.test(payload)
|
|
5062
5115
|
}
|
|
5063
5116
|
|
|
5064
5117
|
// Flight payload only (worker: rsc-payload — build-time).
|
|
@@ -7290,6 +7343,11 @@ export function rscKit(options = {}) {
|
|
|
7290
7343
|
if (offline) {
|
|
7291
7344
|
writeServiceWorker(clientOut ?? publicAssetsDir, frozen, offlineFallback(frozen, results), staticDir);
|
|
7292
7345
|
}
|
|
7346
|
+
// Last, once the client output is complete: the icons, the share
|
|
7347
|
+
// image, the web manifest and the service worker are written above,
|
|
7348
|
+
// after the prerender, and an export taken any earlier left them out.
|
|
7349
|
+
if (output === "export")
|
|
7350
|
+
await exportAfterPrerender(results, staticDir, clientOut ?? publicAssetsDir);
|
|
7293
7351
|
},
|
|
7294
7352
|
configResolved(config) {
|
|
7295
7353
|
// A build that is not a production build cannot work here, and the
|