@rshono/core 1.0.0-rc.18 → 1.0.0-rc.19
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 +13 -3
- package/dist/builder/rspack-config.d.ts.map +1 -1
- package/dist/builder/rspack-config.js +5 -1
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/builder/server-only-imports.d.ts +33 -0
- package/dist/builder/server-only-imports.d.ts.map +1 -0
- package/dist/builder/server-only-imports.js +51 -0
- package/dist/builder/server-only-imports.js.map +1 -0
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +18 -9
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +45 -0
- package/dist/cli/dev.js.map +1 -1
- package/dist/deploy/presets.d.ts +8 -0
- package/dist/deploy/presets.d.ts.map +1 -1
- package/dist/deploy/presets.js +1 -0
- package/dist/deploy/presets.js.map +1 -1
- package/dist/router.d.ts +33 -18
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js.map +1 -1
- package/dist/runtime/boundaries.d.ts +11 -4
- package/dist/runtime/boundaries.d.ts.map +1 -1
- package/dist/runtime/boundaries.js.map +1 -1
- package/dist/runtime/context.d.ts +9 -2
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +12 -3
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/entry.client.js +124 -19
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts +7 -0
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +17 -20
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/validate-entries.d.ts +49 -4
- package/dist/runtime/validate-entries.d.ts.map +1 -1
- package/dist/runtime/validate-entries.js +118 -2
- package/dist/runtime/validate-entries.js.map +1 -1
- package/dist/server/prerendered.d.ts +0 -5
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +1 -1
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +8 -1
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +2 -1
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +24 -7
- package/dist/server/ssg.js.map +1 -1
- package/dist/server/static.d.ts.map +1 -1
- package/dist/server/static.js +5 -1
- package/dist/server/static.js.map +1 -1
- package/package.json +2 -2
package/dist/server/ssg.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssg.js","sourceRoot":"","sources":["../../src/server/ssg.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { isPageRoute, type PageRoute, type Route } from '../router.js';\nimport {\n createPageCache,\n ssgFilePath,\n SSG_MANIFEST_FILE,\n toPrerenderedPage,\n VARIANTS,\n type PrerenderedPage,\n type PrerenderVariant,\n} from './prerendered.js';\n\n/**\n * Stand-in origin for a build that declared no `siteUrl`. Obviously wrong rather than a guess, so a page that\n * bakes it into a canonical tag is easy to spot; the build warns as well.\n */\nconst DEFAULT_SSG_ORIGIN = 'http://localhost';\n\n/**\n * Resolves `siteUrl` to the origin prerendering renders against. A path is rejected rather than dropped:\n * `'https://example.com/docs'` means the author expects a base path, which is not supported.\n */\nexport function resolveSiteOrigin(siteUrl: string | undefined): string {\n if (!siteUrl) return DEFAULT_SSG_ORIGIN;\n const parsed = URL.parse(siteUrl);\n if (!parsed || (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')) {\n throw new Error(`[rshono] invalid siteUrl ${JSON.stringify(siteUrl)} — use a full origin, e.g. 'https://example.com'.`);\n }\n if (parsed.pathname !== '/' || parsed.search || parsed.hash) {\n throw new Error(`[rshono] siteUrl ${JSON.stringify(siteUrl)} must be a bare origin — a base path is not supported.`);\n }\n return parsed.origin;\n}\n\n/**\n * A route's path with its params filled in, ready to render and to store.\n *\n * Throws for a pattern `staticPaths` cannot fill and for a set that does not fill it. Both are warned about\n * and skipped by the caller, which already names the route — so these messages are the reason alone, written\n * to be read at the end of that line.\n */\nfunction interpolatePath(pattern: string, params: Record<string, string>): string {\n return pattern\n .split('/')\n .map((segment) => {\n if (!segment.startsWith(':')) {\n if (segment.includes('*')) {\n throw new Error(`wildcard segments are not supported by staticPaths`);\n }\n return segment;\n }\n const name = segment.slice(1);\n if (!/^\\w+$/.test(name)) {\n throw new Error(`optional/regex params are not supported by staticPaths`);\n }\n const value = params[name];\n if (value === undefined) {\n throw new Error(`staticPaths returned a param set without \"${name}\"`);\n }\n return encodeURIComponent(value);\n })\n .join('/');\n}\n\n/** Prerendered pages, keyed by the request that produced them (see {@link readPrerendered}). */\nconst pageCache = createPageCache();\n\n/** One in-flight or settled read of each store's {@link SSG_MANIFEST_FILE}; the file cannot change while the server is up. */\nconst storeIndexes = new Map<string, Promise<ReadonlySet<string> | null>>();\n\n/**\n * What `ssgDir` holds, as {@link ssgFilePath} names it — or `null` where the build left no manifest, which\n * is every build made before there was one. A `null` gates nothing, so those keep the behaviour they had.\n */\nfunction storeIndex(ssgDir: string): Promise<ReadonlySet<string> | null> {\n let pending = storeIndexes.get(ssgDir);\n if (!pending) {\n // One `catch` for both failures worth the same answer: no manifest, and a manifest that is not one.\n pending = readFile(join(ssgDir, SSG_MANIFEST_FILE), 'utf8')\n .then((text) => new Set((JSON.parse(text) as { files?: string[] }).files ?? []) as ReadonlySet<string>)\n .catch(() => null);\n storeIndexes.set(ssgDir, pending);\n }\n return pending;\n}\n\nexport async function readPrerendered(ssgDir: string, requestPath: string, variant: PrerenderVariant = 'html'): Promise<PrerenderedPage | null> {\n // Keyed by what the request carried rather than by the resolved filename, so a hit costs one Map lookup. Safe\n // because only *hits* are cached: an entry exists only if this exact key already passed the checks below.\n const key = `${ssgDir}\\0${variant}\\0${requestPath}`;\n const cached = pageCache.get(key);\n if (cached) return cached;\n\n const relPath = ssgFilePath(requestPath, variant);\n if (relPath === null) return null;\n\n // Before the store is touched: a `render: 'static'` route whose build wrote nothing — no `staticPaths`, a\n // param the build never saw, a page that did not render cleanly — falls through to SSR on every request,\n // and without this each of those pays a failed read first, forever.\n const index = await storeIndex(ssgDir);\n if (index && !index.has(relPath)) return null;\n // Belt and braces over the shared traversal guard: this proves the resolved file is under the root.\n const root = resolve(ssgDir);\n const file = resolve(root, relPath);\n if (!file.startsWith(root + sep)) return null;\n\n // No encoding argument: the bytes are what gets served. Copied out of the Buffer rather than kept as one,\n // because `readFile` can hand back a view into Node's shared pool and this is retained for the process.\n let body: Uint8Array<ArrayBuffer>;\n try {\n body = new Uint8Array(await readFile(file));\n } catch {\n return null;\n }\n\n const page = await toPrerenderedPage(body);\n pageCache.set(key, page);\n return page;\n}\n\ninterface PrerenderOptions {\n routes: readonly Route[];\n fetch: (request: Request) => Response | Promise<Response>;\n ssgDir: string;\n /** The origin absolute URLs in the output are built against — `siteUrl` from `rshono.config.ts`. */\n siteUrl?: string;\n}\n\nexport interface PrerenderResult {\n written: string[];\n skipped: string[];\n}\n\n/**\n * Records what the pass wrote, beside what it wrote. Written by the same pass for the same reason\n * {@link ssgFilePath} is one function: an index that disagrees with the store is invisible, so the two are\n * produced together or not at all.\n */\nfunction writeManifest(ssgDir: string, files: readonly string[]): void {\n mkdirSync(ssgDir, { recursive: true });\n writeFileSync(join(ssgDir, SSG_MANIFEST_FILE), `${JSON.stringify({ files }, null, 2)}\\n`);\n}\n\n/**\n * How many paths are rendered at once.\n *\n * A prerender pass spends its time inside the app — a page's own data fetching is what each render awaits —\n * so a few hundred `staticPaths` entries rendered one at a time pay all of that latency in series.\n * Unbounded is the other wrong answer: it points the whole site at the app's database in one go. Eight keeps\n * a build's peak load recognisable while hiding most of the wait.\n */\nconst RENDER_CONCURRENCY = 8;\n\n/**\n * `items.map(run)` with at most `limit` running at once, results in input order.\n *\n * A worker pool rather than fixed batches: a batch is only as fast as its slowest member, so one slow page\n * would idle the rest of its batch.\n */\nasync function mapBounded<T, R>(items: readonly T[], limit: number, run: (item: T) => Promise<R>): Promise<R[]> {\n const results = new Array<R>(items.length);\n let next = 0;\n const worker = async (): Promise<void> => {\n for (let index = next++; index < items.length; index = next++) results[index] = await run(items[index]);\n };\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));\n return results;\n}\n\n/**\n * One representation of a path, as the app answered for it at build time. Discriminated on `ok` because both\n * callers have to tell \"the app rendered this\" from \"it did not\", and only one cares why.\n */\ntype RenderedVariant = { ok: true; body: string } | { ok: false; reason: string };\n\nasync function renderVariant(fetch: PrerenderOptions['fetch'], url: string, variant: PrerenderVariant): Promise<RenderedVariant> {\n const response = await fetch(new Request(url, { headers: VARIANTS[variant].headers }));\n if (response.status !== 200) return { ok: false, reason: `${response.status}` };\n if (!(response.headers.get('Content-Type') ?? '').includes(VARIANTS[variant].contentType)) {\n return { ok: false, reason: `a non-${VARIANTS[variant].contentType} response` };\n }\n return { ok: true, body: await response.text() };\n}\n\n/** A path the pass will render, resolved far enough that nothing left can fail the build. */\ninterface PrerenderTarget {\n path: string;\n /** Where a request for it will look — {@link ssgFilePath}, resolved before the render rather than after. */\n relPath: string;\n}\n\nexport async function prerenderStaticRoutes(options: PrerenderOptions): Promise<PrerenderResult> {\n const { routes, fetch, ssgDir } = options;\n const staticRoutes = routes.filter((r): r is PageRoute => isPageRoute(r) && r.render === 'static');\n const origin = resolveSiteOrigin(options.siteUrl);\n\n if (staticRoutes.length > 0 && !options.siteUrl) {\n console.warn(\n ` ⚠ No siteUrl in rshono.config — prerendered pages are built against ${DEFAULT_SSG_ORIGIN}, so any absolute URL\\n` +\n ` they derive from a page's \\`url\\` prop (canonical tags, og:url, absolute links) will point there.`,\n );\n }\n\n const written: string[] = [];\n const skipped: string[] = [];\n /** Every file written, as the reader names it — {@link writeManifest}. */\n const files: string[] = [];\n\n /** Every path to render, in route order, each one once. Built before anything renders — see below. */\n const targets: PrerenderTarget[] = [];\n /** So a `staticPaths` entry that repeats — or that a second route also produces — is rendered once. */\n const queued = new Set<string>();\n\n for (const route of staticRoutes) {\n let paths: string[];\n if (!/[:*]/.test(route.path)) {\n paths = [route.path];\n } else {\n if (!route.staticPaths) {\n console.warn(` ⚠ Static route \"${route.path}\" has params but no staticPaths — will SSR per request.`);\n skipped.push(route.path);\n continue;\n }\n try {\n paths = (await route.staticPaths()).map((params) => interpolatePath(route.path, params));\n } catch (error) {\n // A route whose paths cannot be computed — a wildcard or a regex/optional param, which `staticPaths`\n // has no way to fill, or a set it filled wrongly — is unprerenderable, not unservable. It gets the\n // same answer as the branch above rather than killing a build the route would have survived: the\n // page is still there, rendered per request.\n const reason = error instanceof Error ? error.message : String(error);\n console.warn(` ⚠ Static route \"${route.path}\" will SSR per request — ${reason.replace(/\\.$/, '')}.`);\n skipped.push(route.path);\n continue;\n }\n }\n\n let duplicates = 0;\n for (const path of paths) {\n if (queued.has(path)) {\n duplicates++;\n continue;\n }\n queued.add(path);\n // Resolved *before* the render, so a path no file can hold fails the build naming the path, rather than\n // after the work and as a bare `join(dir, null)` TypeError. The same call answers for the reader, which\n // is the whole point: a page written under a name the request path never resolves to is a page the build\n // reports as prerendered and nothing ever serves. Resolved in this pass rather than the next one for a\n // second reason too: which of several bad paths fails the build should not depend on render order.\n const relPath = ssgFilePath(path, 'html');\n if (relPath === null) {\n throw new Error(\n `Cannot prerender \"${path}\" for route \"${route.path}\": a path segment is \".\" or \"..\", or holds a ` +\n `character a portable file name cannot — one of \\\\ / : * ? \" < > | or a control character.`,\n );\n }\n targets.push({ path, relPath });\n }\n if (duplicates > 0) {\n console.warn(` ⚠ Static route \"${route.path}\" repeated ${duplicates} path${duplicates === 1 ? '' : 's'} — each page is prerendered once.`);\n }\n }\n\n const outcomes = await mapBounded(targets, RENDER_CONCURRENCY, async ({ path, relPath }) => {\n /** Buffered, so a concurrent pass logs in the same order a serial one did. */\n const warnings: string[] = [];\n const document = await renderVariant(fetch, origin + path, 'html');\n if (!document.ok) {\n warnings.push(` ⚠ \"${path}\" rendered ${document.reason} at build time — skipping, will SSR per request.`);\n return { path, ok: false as const, files: [], warnings };\n }\n\n // Both representations of a page share its directory and differ only in the file name.\n const pageDir = join(ssgDir, dirname(relPath));\n const wrote: string[] = [];\n const write = (variant: PrerenderVariant, body: string) => {\n mkdirSync(pageDir, { recursive: true });\n writeFileSync(join(pageDir, VARIANTS[variant].file), body);\n // `ssgFilePath` again rather than the `join` above: the manifest is read against what a *request*\n // resolves to, which is that function's output and not a filesystem path.\n wrote.push(ssgFilePath(path, variant)!);\n };\n write('html', document.body);\n\n // The soft-navigation representation of the same page. Best-effort: the document is valid on its own, and\n // serving falls back to rendering the flight payload per request.\n const flight = await renderVariant(fetch, origin + path, 'flight');\n if (flight.ok) {\n write('flight', flight.body);\n } else {\n warnings.push(` ⚠ \"${path}\" produced no flight payload — soft navigations to it will render per request.`);\n }\n\n return { path, ok: true as const, files: wrote, warnings };\n });\n\n // Folded back in target order rather than completion order, so a concurrent pass writes the same manifest\n // and prints the same log a serial one did.\n for (const outcome of outcomes) {\n for (const warning of outcome.warnings) console.warn(warning);\n if (!outcome.ok) {\n skipped.push(outcome.path);\n continue;\n }\n files.push(...outcome.files);\n written.push(outcome.path);\n }\n\n // Only where the app has static routes at all: an empty manifest would be a store, and a build with\n // nothing to prerender should leave no `ssg/` directory for a preset to carry around.\n if (staticRoutes.length > 0) writeManifest(ssgDir, files);\n\n return { written, skipped };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ssg.js","sourceRoot":"","sources":["../../src/server/ssg.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { isPageRoute, type PageRoute, type Route } from '../router.js';\nimport {\n createPageCache,\n ssgFilePath,\n SSG_MANIFEST_FILE,\n toPrerenderedPage,\n VARIANTS,\n type PrerenderedPage,\n type PrerenderVariant,\n} from './prerendered.js';\n\n/**\n * Stand-in origin for a build that declared no `siteUrl`. Obviously wrong rather than a guess, so a page that\n * bakes it into a canonical tag is easy to spot; the build warns as well.\n */\nconst DEFAULT_SSG_ORIGIN = 'http://localhost';\n\n/**\n * Resolves `siteUrl` to the origin prerendering renders against. A path is rejected rather than dropped:\n * `'https://example.com/docs'` means the author expects a base path, which is not supported.\n */\nexport function resolveSiteOrigin(siteUrl: string | undefined): string {\n if (!siteUrl) return DEFAULT_SSG_ORIGIN;\n const parsed = URL.parse(siteUrl);\n if (!parsed || (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')) {\n throw new Error(`[rshono] invalid siteUrl ${JSON.stringify(siteUrl)} — use a full origin, e.g. 'https://example.com'.`);\n }\n if (parsed.pathname !== '/' || parsed.search || parsed.hash) {\n throw new Error(`[rshono] siteUrl ${JSON.stringify(siteUrl)} must be a bare origin — a base path is not supported.`);\n }\n return parsed.origin;\n}\n\n/**\n * A route's path with its params filled in, ready to render and to store.\n *\n * Throws for a pattern `staticPaths` cannot fill and for a set that does not fill it. Both are warned about\n * and skipped by the caller, which already names the route — so these messages are the reason alone, written\n * to be read at the end of that line.\n */\nfunction interpolatePath(pattern: string, params: Record<string, string>): string {\n return pattern\n .split('/')\n .map((segment) => {\n if (!segment.startsWith(':')) {\n if (segment.includes('*')) {\n throw new Error(`wildcard segments are not supported by staticPaths`);\n }\n return segment;\n }\n const name = segment.slice(1);\n if (!/^\\w+$/.test(name)) {\n throw new Error(`optional/regex params are not supported by staticPaths`);\n }\n const value = params[name];\n if (value === undefined) {\n throw new Error(`staticPaths returned a param set without \"${name}\"`);\n }\n return encodeURIComponent(value);\n })\n .join('/');\n}\n\n/** Prerendered pages, keyed by the request that produced them (see {@link readPrerendered}). */\nconst pageCache = createPageCache();\n\n/** One in-flight or settled read of each store's {@link SSG_MANIFEST_FILE}; the file cannot change while the server is up. */\nconst storeIndexes = new Map<string, Promise<ReadonlySet<string> | null>>();\n\n/**\n * What `ssgDir` holds, as {@link ssgFilePath} names it — or `null` where the build left no manifest, which\n * is every build made before there was one. A `null` gates nothing, so those keep the behaviour they had.\n */\nfunction storeIndex(ssgDir: string): Promise<ReadonlySet<string> | null> {\n let pending = storeIndexes.get(ssgDir);\n if (!pending) {\n // One `catch` for both failures worth the same answer: no manifest, and a manifest that is not one.\n pending = readFile(join(ssgDir, SSG_MANIFEST_FILE), 'utf8')\n .then((text) => new Set((JSON.parse(text) as { files?: string[] }).files ?? []) as ReadonlySet<string>)\n .catch(() => null);\n storeIndexes.set(ssgDir, pending);\n }\n return pending;\n}\n\nexport async function readPrerendered(ssgDir: string, requestPath: string, variant: PrerenderVariant = 'html'): Promise<PrerenderedPage | null> {\n // Keyed by what the request carried rather than by the resolved filename, so a hit costs one Map lookup. Safe\n // because only *hits* are cached: an entry exists only if this exact key already passed the checks below.\n const key = `${ssgDir}\\0${variant}\\0${requestPath}`;\n const cached = pageCache.get(key);\n if (cached) return cached;\n\n const relPath = ssgFilePath(requestPath, variant);\n if (relPath === null) return null;\n\n // Before the store is touched: a `render: 'static'` route whose build wrote nothing — no `staticPaths`, a\n // param the build never saw, a page that did not render cleanly — falls through to SSR on every request,\n // and without this each of those pays a failed read first, forever.\n const index = await storeIndex(ssgDir);\n if (index && !index.has(relPath)) return null;\n // Belt and braces over the shared traversal guard: this proves the resolved file is under the root.\n const root = resolve(ssgDir);\n const file = resolve(root, relPath);\n if (!file.startsWith(root + sep)) return null;\n\n // No encoding argument: the bytes are what gets served. Copied out of the Buffer rather than kept as one,\n // because `readFile` can hand back a view into Node's shared pool and this is retained for the process.\n let body: Uint8Array<ArrayBuffer>;\n try {\n body = new Uint8Array(await readFile(file));\n } catch {\n return null;\n }\n\n const page = await toPrerenderedPage(body);\n pageCache.set(key, page);\n return page;\n}\n\ninterface PrerenderOptions {\n routes: readonly Route[];\n fetch: (request: Request) => Response | Promise<Response>;\n ssgDir: string;\n /** The origin absolute URLs in the output are built against — `siteUrl` from `rshono.config.ts`. */\n siteUrl?: string;\n}\n\nexport interface PrerenderResult {\n written: string[];\n skipped: string[];\n}\n\n/**\n * Records what the pass wrote, beside what it wrote. Written by the same pass for the same reason\n * {@link ssgFilePath} is one function: an index that disagrees with the store is invisible, so the two are\n * produced together or not at all.\n */\nfunction writeManifest(ssgDir: string, files: readonly string[]): void {\n mkdirSync(ssgDir, { recursive: true });\n writeFileSync(join(ssgDir, SSG_MANIFEST_FILE), `${JSON.stringify({ files }, null, 2)}\\n`);\n}\n\n/**\n * How many paths are rendered at once.\n *\n * A prerender pass spends its time inside the app — a page's own data fetching is what each render awaits —\n * so a few hundred `staticPaths` entries rendered one at a time pay all of that latency in series.\n * Unbounded is the other wrong answer: it points the whole site at the app's database in one go. Eight keeps\n * a build's peak load recognisable while hiding most of the wait.\n */\nconst RENDER_CONCURRENCY = 8;\n\n/**\n * `items.map(run)` with at most `limit` running at once, results in input order.\n *\n * A worker pool rather than fixed batches: a batch is only as fast as its slowest member, so one slow page\n * would idle the rest of its batch.\n */\nasync function mapBounded<T, R>(items: readonly T[], limit: number, run: (item: T) => Promise<R>): Promise<R[]> {\n const results = new Array<R>(items.length);\n let next = 0;\n const worker = async (): Promise<void> => {\n for (let index = next++; index < items.length; index = next++) results[index] = await run(items[index]);\n };\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));\n return results;\n}\n\n/**\n * One representation of a path, as the app answered for it at build time. Discriminated on `ok` because both\n * callers have to tell \"the app rendered this\" from \"it did not\", and only one cares why.\n *\n * `failed` splits the second case in two. A 404, a 3xx or a payload of the wrong type is a page this pass\n * cannot *store*, and it still serves per request — the skip is honest. A 5xx is the app throwing, and this\n * pass renders a page exactly as a request does, so per request it will throw again: skipping it prints\n * \"will SSR per request\" over a route that will 500 forever, and exits 0.\n */\ntype RenderedVariant = { ok: true; body: string } | { ok: false; reason: string; failed: boolean };\n\nasync function renderVariant(fetch: PrerenderOptions['fetch'], url: string, variant: PrerenderVariant): Promise<RenderedVariant> {\n const response = await fetch(new Request(url, { headers: VARIANTS[variant].headers }));\n if (response.status !== 200) return { ok: false, reason: `${response.status}`, failed: response.status >= 500 };\n if (!(response.headers.get('Content-Type') ?? '').includes(VARIANTS[variant].contentType)) {\n return { ok: false, reason: `a non-${VARIANTS[variant].contentType} response`, failed: false };\n }\n return { ok: true, body: await response.text() };\n}\n\n/** A path the pass will render, resolved far enough that nothing left can fail the build. */\ninterface PrerenderTarget {\n path: string;\n /** Where a request for it will look — {@link ssgFilePath}, resolved before the render rather than after. */\n relPath: string;\n}\n\nexport async function prerenderStaticRoutes(options: PrerenderOptions): Promise<PrerenderResult> {\n const { routes, fetch, ssgDir } = options;\n const staticRoutes = routes.filter((r): r is PageRoute => isPageRoute(r) && r.render === 'static');\n const origin = resolveSiteOrigin(options.siteUrl);\n\n if (staticRoutes.length > 0 && !options.siteUrl) {\n console.warn(\n ` ⚠ No siteUrl in rshono.config — prerendered pages are built against ${DEFAULT_SSG_ORIGIN}, so any absolute URL\\n` +\n ` they derive from a page's \\`url\\` prop (canonical tags, og:url, absolute links) will point there.`,\n );\n }\n\n const written: string[] = [];\n const skipped: string[] = [];\n /** Every file written, as the reader names it — {@link writeManifest}. */\n const files: string[] = [];\n\n /** Every path to render, in route order, each one once. Built before anything renders — see below. */\n const targets: PrerenderTarget[] = [];\n /** So a `staticPaths` entry that repeats — or that a second route also produces — is rendered once. */\n const queued = new Set<string>();\n\n for (const route of staticRoutes) {\n let paths: string[];\n if (!/[:*]/.test(route.path)) {\n paths = [route.path];\n } else {\n if (!route.staticPaths) {\n console.warn(` ⚠ Static route \"${route.path}\" has params but no staticPaths — will SSR per request.`);\n skipped.push(route.path);\n continue;\n }\n try {\n paths = (await route.staticPaths()).map((params) => interpolatePath(route.path, params));\n } catch (error) {\n // A route whose paths cannot be computed — a wildcard or a regex/optional param, which `staticPaths`\n // has no way to fill, or a set it filled wrongly — is unprerenderable, not unservable. It gets the\n // same answer as the branch above rather than killing a build the route would have survived: the\n // page is still there, rendered per request.\n const reason = error instanceof Error ? error.message : String(error);\n console.warn(` ⚠ Static route \"${route.path}\" will SSR per request — ${reason.replace(/\\.$/, '')}.`);\n skipped.push(route.path);\n continue;\n }\n }\n\n let duplicates = 0;\n for (const path of paths) {\n if (queued.has(path)) {\n duplicates++;\n continue;\n }\n queued.add(path);\n // Resolved *before* the render, so a path no file can hold fails the build naming the path, rather than\n // after the work and as a bare `join(dir, null)` TypeError. The same call answers for the reader, which\n // is the whole point: a page written under a name the request path never resolves to is a page the build\n // reports as prerendered and nothing ever serves. Resolved in this pass rather than the next one for a\n // second reason too: which of several bad paths fails the build should not depend on render order.\n const relPath = ssgFilePath(path, 'html');\n if (relPath === null) {\n throw new Error(\n `[rshono] Cannot prerender \"${path}\" for route \"${route.path}\": a path segment is \".\" or \"..\", or holds a ` +\n `character a portable file name cannot — one of \\\\ / : * ? \" < > | or a control character.`,\n );\n }\n targets.push({ path, relPath });\n }\n if (duplicates > 0) {\n console.warn(` ⚠ Static route \"${route.path}\" repeated ${duplicates} path${duplicates === 1 ? '' : 's'} — each page is prerendered once.`);\n }\n }\n\n const outcomes = await mapBounded(targets, RENDER_CONCURRENCY, async ({ path, relPath }) => {\n /** Buffered, so a concurrent pass logs in the same order a serial one did. */\n const warnings: string[] = [];\n const document = await renderVariant(fetch, origin + path, 'html');\n if (!document.ok) {\n // A 5xx fails the build instead of being warned about — see {@link RenderedVariant}.\n if (!document.failed) warnings.push(` ⚠ \"${path}\" rendered ${document.reason} at build time — skipping, will SSR per request.`);\n return { path, ok: false as const, files: [], warnings, failure: document.failed ? document.reason : undefined };\n }\n\n // Both representations of a page share its directory and differ only in the file name.\n const pageDir = join(ssgDir, dirname(relPath));\n const wrote: string[] = [];\n const write = (variant: PrerenderVariant, body: string) => {\n mkdirSync(pageDir, { recursive: true });\n writeFileSync(join(pageDir, VARIANTS[variant].file), body);\n // `ssgFilePath` again rather than the `join` above: the manifest is read against what a *request*\n // resolves to, which is that function's output and not a filesystem path.\n wrote.push(ssgFilePath(path, variant)!);\n };\n write('html', document.body);\n\n // The soft-navigation representation of the same page. Best-effort: the document is valid on its own, and\n // serving falls back to rendering the flight payload per request.\n const flight = await renderVariant(fetch, origin + path, 'flight');\n if (flight.ok) {\n write('flight', flight.body);\n } else {\n // Not fatal the way a failed *document* is, even for a 5xx: the page is on disk and serves, and only\n // soft navigation to it degrades to rendering per request. The reason is named because the two cases\n // want different things done about them.\n warnings.push(` ⚠ \"${path}\" produced no flight payload (${flight.reason}) — soft navigations to it will render per request.`);\n }\n\n return { path, ok: true as const, files: wrote, warnings, failure: undefined };\n });\n\n // Folded back in target order rather than completion order, so a concurrent pass writes the same manifest\n // and prints the same log a serial one did.\n const failures: string[] = [];\n for (const outcome of outcomes) {\n for (const warning of outcome.warnings) console.warn(warning);\n if (outcome.failure !== undefined) failures.push(`\"${outcome.path}\" rendered ${outcome.failure}`);\n if (!outcome.ok) {\n skipped.push(outcome.path);\n continue;\n }\n files.push(...outcome.files);\n written.push(outcome.path);\n }\n\n // Raised together, and in target order, so which of several failing pages is reported does not depend on\n // which render finished first. The render's own error is already in the build log above: the framework's\n // `onError` reported it when it turned the throw into the 500 counted here.\n if (failures.length > 0) {\n throw new Error(\n `[rshono] ${failures.length} page${failures.length === 1 ? '' : 's'} failed to render while prerendering:\\n` +\n failures.map((failure) => ` • ${failure}`).join('\\n') +\n '\\n Prerendering renders a page the way a request does, so this is not a build-only failure — the route' +\n '\\n would answer the same status per request. The error it threw is logged above.',\n );\n }\n\n // Only where the app has static routes at all: an empty manifest would be a store, and a build with\n // nothing to prerender should leave no `ssg/` directory for a preset to carry around.\n if (staticRoutes.length > 0) writeManifest(ssgDir, files);\n\n return { written, skipped };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAe5B,UAAU,aAAa;IACrB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAe5B,UAAU,aAAa;IACrB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAelE;AAED,yGAAyG;AACzG,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,aAAa,GAAG,iBAAiB,CAStF"}
|
package/dist/server/static.js
CHANGED
|
@@ -15,7 +15,11 @@ export function createStaticAssetsApp(options) {
|
|
|
15
15
|
const app = new Hono();
|
|
16
16
|
// `GET` alone: Hono dispatches a `HEAD` as a `GET` and strips the body, so a `HEAD` registration beside it
|
|
17
17
|
// is never reached — see `HTTPMethod`.
|
|
18
|
-
|
|
18
|
+
// The 404 carries a `Cache-Control` of its own because `cacheControl` above returns early for it, and a
|
|
19
|
+
// 404 is heuristically cacheable under RFC 9111 — the same reasoning as `plainNotFound`'s, and it matters
|
|
20
|
+
// most here: during a rolling deploy an old instance 404s a chunk the new one has, and without this a
|
|
21
|
+
// shared cache may store that answer for a content-hashed URL that is about to become valid.
|
|
22
|
+
app.get('/*', cacheControl(isDev), serveStatic({ root, rewriteRequestPath: (path) => path.replace(/^\/_static/, '') }), (c) => c.text('Not Found', 404, { 'cache-control': 'private, no-cache' }));
|
|
19
23
|
return app;
|
|
20
24
|
}
|
|
21
25
|
/** Middleware serving the app's `public/` files verbatim at the web root, for paths no route claimed. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAE7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,IAAI,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO;QACzD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CACf,eAAe,EACf,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,qBAAqB,CACrH,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AASD,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CAAC,OAAsB;IAC1D,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,2GAA2G;IAC3G,uCAAuC;IACvC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAC5H,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAE7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,IAAI,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO;QACzD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CACf,eAAe,EACf,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,qBAAqB,CACrH,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AASD,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CAAC,OAAsB;IAC1D,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,2GAA2G;IAC3G,uCAAuC;IACvC,wGAAwG;IACxG,0GAA0G;IAC1G,sGAAsG;IACtG,6FAA6F;IAC7F,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAC5H,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,EAAE,eAAe,EAAE,mBAAmB,EAAE,CAAC,CACnE,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,oBAAoB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAiB;IACjE,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACpC,IAAI,MAAM,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;YACnF,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { serveStatic } from '@hono/node-server/serve-static';\nimport type { MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono';\n\nconst CONTENT_HASHED = /\\.[0-9a-f]{8,}\\./;\n\nfunction cacheControl(isDev: boolean): MiddlewareHandler {\n return async (c, next) => {\n await next();\n if (c.res.status !== 200 && c.res.status !== 206) return;\n c.res.headers.set(\n 'Cache-Control',\n isDev ? 'no-cache' : CONTENT_HASHED.test(c.req.path) ? 'public, max-age=31536000, immutable' : 'public, max-age=300',\n );\n };\n}\n\ninterface StaticOptions {\n /** Directory the files are read from. */\n root: string;\n /** Dev serves revalidated (`no-cache`); a build serves hashed files as immutable. */\n isDev: boolean;\n}\n\n/** A sub-app serving the hashed client bundle, to be mounted at `/_static`. */\nexport function createStaticAssetsApp(options: StaticOptions): Hono {\n const { root, isDev } = options;\n const app = new Hono();\n\n // `GET` alone: Hono dispatches a `HEAD` as a `GET` and strips the body, so a `HEAD` registration beside it\n // is never reached — see `HTTPMethod`.\n // The 404 carries a `Cache-Control` of its own because `cacheControl` above returns early for it, and a\n // 404 is heuristically cacheable under RFC 9111 — the same reasoning as `plainNotFound`'s, and it matters\n // most here: during a rolling deploy an old instance 404s a chunk the new one has, and without this a\n // shared cache may store that answer for a content-hashed URL that is about to become valid.\n app.get('/*', cacheControl(isDev), serveStatic({ root, rewriteRequestPath: (path) => path.replace(/^\\/_static/, '') }), (c) =>\n c.text('Not Found', 404, { 'cache-control': 'private, no-cache' }),\n );\n\n return app;\n}\n\n/** Middleware serving the app's `public/` files verbatim at the web root, for paths no route claimed. */\nexport function createPublicFallback({ root, isDev }: StaticOptions): MiddlewareHandler {\n const serve = serveStatic({ root });\n return async (c, next) => {\n const result = await serve(c, next);\n if (result instanceof Response && (result.status === 200 || result.status === 206)) {\n result.headers.set('Cache-Control', isDev ? 'no-cache' : 'public, max-age=300');\n }\n return result;\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rshono/core",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.19",
|
|
4
4
|
"description": "Minimalist web framework — Hono + Rspack + React Server Components",
|
|
5
5
|
"author": "Lasse <lasse@lassetange.com> (https://www.lassetange.com)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@hono/node-server": "^2.1.1",
|
|
55
|
-
"@rspack/core": "2.2.
|
|
55
|
+
"@rspack/core": "2.2.2",
|
|
56
56
|
"@rspack/plugin-react-refresh": "2.0.2",
|
|
57
57
|
"react-refresh": "0.18.0",
|
|
58
58
|
"react-server-dom-rspack": "0.1.0"
|