@funstack/static 0.0.9 → 0.0.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/README.md +2 -0
- package/dist/docs/GettingStarted.md +2 -0
- package/dist/docs/MigratingFromViteSPA.md +1 -1
- package/dist/entries/rsc-client.d.mts +0 -1
- package/dist/rsc/defer.d.mts +0 -1
- package/dist/rsc/defer.d.mts.map +1 -1
- package/dist/rsc/defer.mjs +2 -5
- package/dist/rsc/defer.mjs.map +1 -1
- package/dist/rsc/entry.mjs +1 -1
- package/dist/rsc/entry.mjs.map +1 -1
- package/dist/rsc-client/clientWrapper.d.mts +5 -1
- package/dist/rsc-client/clientWrapper.d.mts.map +1 -1
- package/dist/rsc-client/clientWrapper.mjs +12 -12
- package/dist/rsc-client/clientWrapper.mjs.map +1 -1
- package/dist/ssr/entry.d.mts.map +1 -1
- package/dist/ssr/entry.mjs +11 -3
- package/dist/ssr/entry.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/rsc-client/entry.d.mts +0 -1
package/README.md
CHANGED
|
@@ -169,6 +169,8 @@ If you use AI coding assistants like [Claude Code](https://docs.anthropic.com/en
|
|
|
169
169
|
|
|
170
170
|
```bash
|
|
171
171
|
npx funstack-static-skill-installer
|
|
172
|
+
# or, if you use skills CLI (https://skills.sh/)
|
|
173
|
+
npx skills add uhyo/funstack-static
|
|
172
174
|
```
|
|
173
175
|
|
|
174
176
|
This registers the `funstack-static-knowledge` skill, which provides your AI assistant with API references, best practices, and architectural guidance for FUNSTACK Static.
|
|
@@ -27,7 +27,7 @@ Or with pnpm:
|
|
|
27
27
|
pnpm add @funstack/static
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
**Hint:** at this point, a skill installer command is available to add FUNSTACK Static knowledge to your AI agents. Run `npx funstack-static-skill-installer` or
|
|
30
|
+
**Hint:** at this point, a skill installer command is available to add FUNSTACK Static knowledge to your AI agents. Run `npx funstack-static-skill-installer` (or `npx skills add uhyo/funstack-static` if you use [skills CLI](https://skills.sh/)) to add the skill. Then you can ask your AI assistant for help with the migration!
|
|
31
31
|
|
|
32
32
|
## Step 2: Update Vite Config
|
|
33
33
|
|
package/dist/rsc/defer.d.mts
CHANGED
package/dist/rsc/defer.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defer.d.mts","names":[],"sources":["../../src/rsc/defer.tsx"],"mappings":";;;UAMiB,UAAA;EACf,KAAA,EAAO,eAAA;EACP,IAAA;EACA,YAAA,GAAe,OAAA;AAAA;;;;UAMA,YAAA;EANf;;;;AAMF;EAME,IAAA;AAAA;AAAA,UAGe,gBAAA,SAAyB,UAAA;EACxC,KAAA,EAAO,OAAA,CAAQ,eAAA;IAAmB,KAAA;EAAA;EAClC,YAAA,EAAc,OAAA;AAAA;AAAA,KAGX,eAAA;EAEC,KAAA;EACA,OAAA,EAAS,YAAA;AAAA;EAGT,KAAA;EACA,MAAA,EAAQ,cAAA,CAAe,UAAA;AAAA;EAGvB,KAAA;
|
|
1
|
+
{"version":3,"file":"defer.d.mts","names":[],"sources":["../../src/rsc/defer.tsx"],"mappings":";;;UAMiB,UAAA;EACf,KAAA,EAAO,eAAA;EACP,IAAA;EACA,YAAA,GAAe,OAAA;AAAA;;;;UAMA,YAAA;EANf;;;;AAMF;EAME,IAAA;AAAA;AAAA,UAGe,gBAAA,SAAyB,UAAA;EACxC,KAAA,EAAO,OAAA,CAAQ,eAAA;IAAmB,KAAA;EAAA;EAClC,YAAA,EAAc,OAAA;AAAA;AAAA,KAGX,eAAA;EAEC,KAAA;EACA,OAAA,EAAS,YAAA;AAAA;EAGT,KAAA;EACA,MAAA,EAAQ,cAAA,CAAe,UAAA;AAAA;EAGvB,KAAA;AAAA;EAGA,KAAA;EACA,KAAA;AAAA;AAAA,cAeO,aAAA;EAAA;EAGX,QAAA,CAAS,OAAA,EAAS,YAAA,EAAc,EAAA,UAAY,IAAA;EAI5C,IAAA,CAAK,EAAA,WAAa,gBAAA;EAkClB,GAAA,CAAI,EAAA;EAnES;;;;EA2EN,OAAA,CAAA,GAAO,cAAA;;;;;;;;;;;;AAjDhB;;;;iBAuHgB,KAAA,CACd,OAAA,EAAS,YAAA,EACT,OAAA,GAAU,YAAA,GACT,SAAA"}
|
package/dist/rsc/defer.mjs
CHANGED
|
@@ -39,11 +39,8 @@ var DeferRegistry = class {
|
|
|
39
39
|
};
|
|
40
40
|
const drainPromise = drainStream(stream2);
|
|
41
41
|
entry.drainPromise = drainPromise;
|
|
42
|
-
drainPromise.then((
|
|
43
|
-
entry.state = {
|
|
44
|
-
state: "ready",
|
|
45
|
-
data
|
|
46
|
-
};
|
|
42
|
+
drainPromise.then(() => {
|
|
43
|
+
entry.state = { state: "ready" };
|
|
47
44
|
}, (error) => {
|
|
48
45
|
entry.state = {
|
|
49
46
|
state: "error",
|
package/dist/rsc/defer.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defer.mjs","names":["#registry","#loadEntry"],"sources":["../../src/rsc/defer.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\nimport { renderToReadableStream } from \"@vitejs/plugin-rsc/react/rsc\";\nimport { DeferredComponent } from \"#rsc-client\";\nimport { drainStream } from \"../util/drainStream\";\nimport { getPayloadIDFor } from \"./rscModule\";\n\nexport interface DeferEntry {\n state: DeferEntryState;\n name?: string;\n drainPromise?: Promise<string>;\n}\n\n/**\n * Options for the defer function.\n */\nexport interface DeferOptions {\n /**\n * Optional name for debugging purposes.\n * In development: included in the RSC payload file name.\n * In production: logged when the payload file is emitted.\n */\n name?: string;\n}\n\nexport interface LoadedDeferEntry extends DeferEntry {\n state: Exclude<DeferEntryState, { state: \"pending\" }>;\n drainPromise: Promise<string>;\n}\n\ntype DeferEntryState =\n | {\n state: \"pending\";\n element: ReactElement;\n }\n | {\n state: \"streaming\";\n stream: ReadableStream<Uint8Array>;\n }\n | {\n state: \"ready\";\n
|
|
1
|
+
{"version":3,"file":"defer.mjs","names":["#registry","#loadEntry"],"sources":["../../src/rsc/defer.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\nimport { renderToReadableStream } from \"@vitejs/plugin-rsc/react/rsc\";\nimport { DeferredComponent } from \"#rsc-client\";\nimport { drainStream } from \"../util/drainStream\";\nimport { getPayloadIDFor } from \"./rscModule\";\n\nexport interface DeferEntry {\n state: DeferEntryState;\n name?: string;\n drainPromise?: Promise<string>;\n}\n\n/**\n * Options for the defer function.\n */\nexport interface DeferOptions {\n /**\n * Optional name for debugging purposes.\n * In development: included in the RSC payload file name.\n * In production: logged when the payload file is emitted.\n */\n name?: string;\n}\n\nexport interface LoadedDeferEntry extends DeferEntry {\n state: Exclude<DeferEntryState, { state: \"pending\" }>;\n drainPromise: Promise<string>;\n}\n\ntype DeferEntryState =\n | {\n state: \"pending\";\n element: ReactElement;\n }\n | {\n state: \"streaming\";\n stream: ReadableStream<Uint8Array>;\n }\n | {\n state: \"ready\";\n }\n | {\n state: \"error\";\n error: unknown;\n };\n\n/**\n * Sanitizes a name for use in file paths.\n * Replaces non-alphanumeric characters with underscores and limits length.\n */\nfunction sanitizeName(name: string): string {\n return name\n .replace(/[^a-zA-Z0-9_-]/g, \"_\")\n .replace(/_+/g, \"_\")\n .replace(/^_|_$/g, \"\")\n .slice(0, 50);\n}\n\nexport class DeferRegistry {\n #registry = new Map<string, DeferEntry>();\n\n register(element: ReactElement, id: string, name?: string) {\n this.#registry.set(id, { state: { element, state: \"pending\" }, name });\n }\n\n load(id: string): LoadedDeferEntry | undefined {\n const entry = this.#registry.get(id);\n if (!entry) {\n return undefined;\n }\n return this.#loadEntry(entry);\n }\n\n #loadEntry(entry: DeferEntry): LoadedDeferEntry {\n const { state } = entry;\n switch (state.state) {\n case \"pending\": {\n const stream = renderToReadableStream<ReactNode>(state.element);\n const [stream1, stream2] = stream.tee();\n entry.state = { state: \"streaming\", stream: stream1 };\n const drainPromise = drainStream(stream2);\n entry.drainPromise = drainPromise;\n drainPromise.then(\n () => {\n entry.state = { state: \"ready\" };\n },\n (error) => {\n entry.state = { state: \"error\", error };\n },\n );\n return entry as LoadedDeferEntry;\n }\n case \"streaming\":\n case \"ready\":\n case \"error\":\n return entry as LoadedDeferEntry;\n }\n }\n\n has(id: string): boolean {\n return this.#registry.has(id);\n }\n\n /**\n * Iterates over all entries in parallel.\n * Yields results as each stream completes.\n */\n async *loadAll() {\n const errors: unknown[] = [];\n\n // Phase 1: Start all entries loading and collect drain promises.\n // We use drain promises (which drain stream2 from tee) instead of\n // draining stream1 directly, because stream1 may have been locked\n // by createFromReadableStream during SSR.\n const loadedEntries = Array.from(this.#registry, ([id, entry]) => {\n const loaded = this.#loadEntry(entry);\n return [id, loaded.drainPromise, entry.name] as const;\n });\n\n if (loadedEntries.length === 0) return;\n\n type Result = { id: string; data: string; name?: string };\n\n // Completion queue\n const completed: Array<Result | { error: unknown }> = [];\n let waiting: (() => void) | undefined;\n let remainingCount = loadedEntries.length;\n\n const onComplete = (result: Result | { error: unknown }) => {\n completed.push(result);\n remainingCount--;\n waiting?.();\n };\n\n // Phase 2: Await drain promises\n for (const [id, drainPromise, name] of loadedEntries) {\n drainPromise.then(\n (data) => onComplete({ id, data, name }),\n (error) => onComplete({ error }),\n );\n }\n\n // Phase 3: Yield from queue as results arrive\n while (remainingCount > 0 || completed.length > 0) {\n if (completed.length === 0) {\n await new Promise<void>((r) => {\n waiting = r;\n });\n waiting = undefined;\n }\n for (const result of completed.splice(0)) {\n if (\"error\" in result) {\n errors.push(result.error);\n } else {\n yield result;\n }\n }\n }\n\n if (errors.length > 0) {\n throw new AggregateError(errors);\n }\n }\n}\n\nexport const deferRegistry = new DeferRegistry();\n\n/**\n * Renders given Server Component into a separate RSC payload.\n *\n * During the client side rendering, fetching of the payload will be\n * deferred until the returned ReactNode is actually rendered.\n *\n * @param element - The React element to defer.\n * @param options - Optional configuration for the deferred payload.\n * @returns A ReactNode that virtually contains the result of rendering the given component.\n */\nexport function defer(\n element: ReactElement,\n options?: DeferOptions,\n): ReactNode {\n const name = options?.name;\n const sanitizedName = name ? sanitizeName(name) : undefined;\n const rawId = sanitizedName\n ? `${sanitizedName}-${crypto.randomUUID()}`\n : crypto.randomUUID();\n const id = getPayloadIDFor(rawId);\n deferRegistry.register(element, id, name);\n\n return <DeferredComponent moduleID={id} />;\n}\n"],"mappings":";;;;;;;;;;;AAkDA,SAAS,aAAa,MAAsB;AAC1C,QAAO,KACJ,QAAQ,mBAAmB,IAAI,CAC/B,QAAQ,OAAO,IAAI,CACnB,QAAQ,UAAU,GAAG,CACrB,MAAM,GAAG,GAAG;;AAGjB,IAAa,gBAAb,MAA2B;CACzB,4BAAY,IAAI,KAAyB;CAEzC,SAAS,SAAuB,IAAY,MAAe;AACzD,QAAKA,SAAU,IAAI,IAAI;GAAE,OAAO;IAAE;IAAS,OAAO;IAAW;GAAE;GAAM,CAAC;;CAGxE,KAAK,IAA0C;EAC7C,MAAM,QAAQ,MAAKA,SAAU,IAAI,GAAG;AACpC,MAAI,CAAC,MACH;AAEF,SAAO,MAAKC,UAAW,MAAM;;CAG/B,WAAW,OAAqC;EAC9C,MAAM,EAAE,UAAU;AAClB,UAAQ,MAAM,OAAd;GACE,KAAK,WAAW;IAEd,MAAM,CAAC,SAAS,WADD,uBAAkC,MAAM,QAAQ,CAC7B,KAAK;AACvC,UAAM,QAAQ;KAAE,OAAO;KAAa,QAAQ;KAAS;IACrD,MAAM,eAAe,YAAY,QAAQ;AACzC,UAAM,eAAe;AACrB,iBAAa,WACL;AACJ,WAAM,QAAQ,EAAE,OAAO,SAAS;QAEjC,UAAU;AACT,WAAM,QAAQ;MAAE,OAAO;MAAS;MAAO;MAE1C;AACD,WAAO;;GAET,KAAK;GACL,KAAK;GACL,KAAK,QACH,QAAO;;;CAIb,IAAI,IAAqB;AACvB,SAAO,MAAKD,SAAU,IAAI,GAAG;;;;;;CAO/B,OAAO,UAAU;EACf,MAAM,SAAoB,EAAE;EAM5B,MAAM,gBAAgB,MAAM,KAAK,MAAKA,WAAY,CAAC,IAAI,WAAW;AAEhE,UAAO;IAAC;IADO,MAAKC,UAAW,MAAM,CAClB;IAAc,MAAM;IAAK;IAC5C;AAEF,MAAI,cAAc,WAAW,EAAG;EAKhC,MAAM,YAAgD,EAAE;EACxD,IAAI;EACJ,IAAI,iBAAiB,cAAc;EAEnC,MAAM,cAAc,WAAwC;AAC1D,aAAU,KAAK,OAAO;AACtB;AACA,cAAW;;AAIb,OAAK,MAAM,CAAC,IAAI,cAAc,SAAS,cACrC,cAAa,MACV,SAAS,WAAW;GAAE;GAAI;GAAM;GAAM,CAAC,GACvC,UAAU,WAAW,EAAE,OAAO,CAAC,CACjC;AAIH,SAAO,iBAAiB,KAAK,UAAU,SAAS,GAAG;AACjD,OAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,IAAI,SAAe,MAAM;AAC7B,eAAU;MACV;AACF,cAAU;;AAEZ,QAAK,MAAM,UAAU,UAAU,OAAO,EAAE,CACtC,KAAI,WAAW,OACb,QAAO,KAAK,OAAO,MAAM;OAEzB,OAAM;;AAKZ,MAAI,OAAO,SAAS,EAClB,OAAM,IAAI,eAAe,OAAO;;;AAKtC,MAAa,gBAAgB,IAAI,eAAe;;;;;;;;;;;AAYhD,SAAgB,MACd,SACA,SACW;CACX,MAAM,OAAO,SAAS;CACtB,MAAM,gBAAgB,OAAO,aAAa,KAAK,GAAG;CAIlD,MAAM,KAAK,gBAHG,gBACV,GAAG,cAAc,GAAG,OAAO,YAAY,KACvC,OAAO,YAAY,CACU;AACjC,eAAc,SAAS,SAAS,IAAI,KAAK;AAEzC,QAAO,oBAAC,qBAAkB,UAAU,KAAM"}
|
package/dist/rsc/entry.mjs
CHANGED
|
@@ -150,7 +150,7 @@ async function serveRSC(request) {
|
|
|
150
150
|
"Server-Timing": timings.join(", ")
|
|
151
151
|
}
|
|
152
152
|
});
|
|
153
|
-
case "ready": return new Response(
|
|
153
|
+
case "ready": return new Response(await entry.drainPromise, {
|
|
154
154
|
status: 200,
|
|
155
155
|
headers: {
|
|
156
156
|
"content-type": "text/x-component;charset=utf-8",
|
package/dist/rsc/entry.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.mjs","names":["ssrEnabled"],"sources":["../../src/rsc/entry.tsx"],"sourcesContent":["import \"./defer\";\nimport { renderToReadableStream } from \"@vitejs/plugin-rsc/rsc\";\nimport { devMainRscPath } from \"./request\";\nimport { generateAppMarker } from \"./marker\";\nimport { deferRegistry } from \"./defer\";\nimport { extractIDFromModulePath } from \"./rscModule\";\nimport { stripBasePath } from \"../util/basePath\";\nimport { urlPathToFileCandidates } from \"../util/urlPath\";\nimport { resolveRoot, resolveApp } from \"./resolveEntry\";\nimport type { EntryDefinition, GetEntriesResult } from \"../entryDefinition\";\n\nexport type RscPayload = {\n root: React.ReactNode;\n};\n\nexport type EntryBuildResult = {\n path: string;\n html: ReadableStream<Uint8Array>;\n appRsc: ReadableStream<Uint8Array>;\n};\n\nimport { ssr as ssrEnabled } from \"virtual:funstack/config\";\n\nasync function loadEntriesList(): Promise<EntryDefinition[]> {\n const getEntries = (await import(\"virtual:funstack/entries\")).default;\n const result: GetEntriesResult = getEntries();\n const entries: EntryDefinition[] = [];\n for await (const entry of result) {\n entries.push(entry);\n }\n return entries;\n}\n\n/**\n * Find the entry matching a URL path from a list of entries.\n */\nfunction findEntryForUrlPath(\n entries: EntryDefinition[],\n urlPath: string,\n): EntryDefinition | undefined {\n const candidates = urlPathToFileCandidates(urlPath);\n for (const candidate of candidates) {\n const entry = entries.find((e) => e.path === candidate);\n if (entry) {\n return entry;\n }\n }\n return undefined;\n}\n\n/**\n * Renders a single entry to an HTML response.\n */\nasync function renderEntryToResponse(\n entry: EntryDefinition,\n timings: string[],\n): Promise<Response> {\n const marker = generateAppMarker();\n\n const resolveStart = performance.now();\n const Root = await resolveRoot(entry.root);\n const appNode = await resolveApp(entry.app);\n timings.push(`resolve;dur=${performance.now() - resolveStart}`);\n\n const ssrModuleStart = performance.now();\n const ssrEntryModule = await import.meta.viteRsc.loadModule<\n typeof import(\"../ssr/entry\")\n >(\"ssr\");\n timings.push(`ssr-module;dur=${performance.now() - ssrModuleStart}`);\n\n if (ssrEnabled) {\n // SSR on: single RSC stream with full tree\n const rscStart = performance.now();\n const rootRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n timings.push(`rsc;dur=${performance.now() - rscStart}`);\n\n const ssrStart = performance.now();\n const ssrResult = await ssrEntryModule.renderHTML(rootRscStream, {\n appEntryMarker: marker,\n build: false,\n ssr: true,\n deferRegistry,\n });\n timings.push(`ssr;dur=${performance.now() - ssrStart}`);\n\n return new Response(ssrResult.stream, {\n status: ssrResult.status,\n headers: {\n \"Content-type\": \"text/html\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n } else {\n // SSR off: shell RSC for SSR, full RSC for client\n const rscStart = performance.now();\n const shellRscStream = renderToReadableStream<RscPayload>({\n root: (\n <Root>\n <span id={marker} />\n </Root>\n ),\n });\n const clientRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n timings.push(`rsc;dur=${performance.now() - rscStart}`);\n\n const ssrStart = performance.now();\n const ssrResult = await ssrEntryModule.renderHTML(shellRscStream, {\n appEntryMarker: marker,\n build: false,\n ssr: false,\n clientRscStream,\n });\n timings.push(`ssr;dur=${performance.now() - ssrStart}`);\n\n return new Response(ssrResult.stream, {\n status: ssrResult.status,\n headers: {\n \"Content-type\": \"text/html\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n}\n\n/**\n * Entrypoint to serve HTML response in dev environment.\n * Accepts a Request to determine which entry to render based on URL path.\n */\nexport async function serveHTML(request: Request): Promise<Response> {\n const timings: string[] = [];\n\n const entriesStart = performance.now();\n const entries = await loadEntriesList();\n timings.push(`entries;dur=${performance.now() - entriesStart}`);\n\n const url = new URL(request.url);\n const urlPath = stripBasePath(url.pathname);\n let entry = findEntryForUrlPath(entries, urlPath);\n\n // SPA fallback: if no entry matched, fall back to index.html or index.htm entry\n if (!entry) {\n entry = entries.find(\n (e) => e.path === \"index.html\" || e.path === \"index.htm\",\n );\n }\n\n if (!entry) {\n return new Response(\"Not Found\", {\n status: 404,\n headers: { \"Content-type\": \"text/plain\" },\n });\n }\n\n return renderEntryToResponse(entry, timings);\n}\n\nclass ServeRSCError extends Error {\n status: 404 | 500;\n constructor(message: string, status: 404 | 500) {\n super(message);\n this.name = \"ServeRSCError\";\n this.status = status;\n }\n}\n\nexport function isServeRSCError(error: unknown): error is ServeRSCError {\n return error instanceof Error && error.name === \"ServeRSCError\";\n}\n\n/**\n * Serves an RSC stream response\n */\nexport async function serveRSC(request: Request): Promise<Response> {\n const timings: string[] = [];\n const url = new URL(request.url);\n const pathname = stripBasePath(url.pathname);\n if (pathname === devMainRscPath) {\n // root RSC stream is requested (HMR re-fetch always sends full tree)\n // For HMR, re-render the first entry (single-entry mode) or index.html entry\n const entriesStart = performance.now();\n const entries = await loadEntriesList();\n timings.push(`entries;dur=${performance.now() - entriesStart}`);\n\n // Use the first entry for HMR re-fetch\n const entry = entries[0];\n if (!entry) {\n throw new ServeRSCError(\"No entries defined\", 404);\n }\n\n const resolveStart = performance.now();\n const Root = await resolveRoot(entry.root);\n const appNode = await resolveApp(entry.app);\n timings.push(`resolve;dur=${performance.now() - resolveStart}`);\n\n const rscStart = performance.now();\n const rootRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n timings.push(`rsc;dur=${performance.now() - rscStart}`);\n\n return new Response(rootRscStream, {\n status: 200,\n headers: {\n \"content-type\": \"text/x-component;charset=utf-8\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n\n const moduleId = extractIDFromModulePath(pathname);\n if (!moduleId) {\n throw new ServeRSCError(`Invalid RSC module path: ${pathname}`, 404);\n }\n\n const deferLoadStart = performance.now();\n const entry = deferRegistry.load(moduleId);\n if (!entry) {\n throw new ServeRSCError(`RSC component not found: ${moduleId}`, 404);\n }\n timings.push(`defer-load;dur=${performance.now() - deferLoadStart}`);\n\n const { state } = entry;\n switch (state.state) {\n case \"streaming\": {\n return new Response(state.stream, {\n status: 200,\n headers: {\n \"content-type\": \"text/x-component;charset=utf-8\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n case \"ready\": {\n return new Response(state.data, {\n status: 200,\n headers: {\n \"content-type\": \"text/x-component;charset=utf-8\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n case \"error\": {\n throw new ServeRSCError(\n `Failed to load RSC component: ${state.error}`,\n 500,\n );\n }\n }\n}\n\n/**\n * Build handler — iterates over all entries and returns per-entry results\n * along with the shared defer registry.\n */\nexport async function build() {\n const getEntries = (await import(\"virtual:funstack/entries\")).default;\n\n const ssrEntryModule = await import.meta.viteRsc.loadModule<\n typeof import(\"../ssr/entry\")\n >(\"ssr\");\n\n const results: EntryBuildResult[] = [];\n for await (const entry of getEntries()) {\n const Root = await resolveRoot(entry.root);\n const appNode = await resolveApp(entry.app);\n\n const marker = generateAppMarker();\n\n let rootRscStream: ReadableStream<Uint8Array>;\n let appRscStream: ReadableStream<Uint8Array>;\n\n if (ssrEnabled) {\n // SSR on: both streams have full tree\n rootRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n appRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n } else {\n // SSR off: root stream has shell, app stream has App only\n rootRscStream = renderToReadableStream<RscPayload>({\n root: (\n <Root>\n <span id={marker} />\n </Root>\n ),\n });\n appRscStream = renderToReadableStream<RscPayload>({\n root: appNode,\n });\n }\n\n const ssrResult = await ssrEntryModule.renderHTML(rootRscStream, {\n appEntryMarker: marker,\n build: true,\n ssr: ssrEnabled,\n deferRegistry,\n });\n\n results.push({\n path: entry.path,\n html: ssrResult.stream,\n appRsc: appRscStream,\n });\n }\n\n return {\n entries: results,\n deferRegistry,\n };\n}\n\nexport { defer } from \"./defer\";\n\nif (import.meta.hot) {\n import.meta.hot.accept();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"entry.mjs","names":["ssrEnabled"],"sources":["../../src/rsc/entry.tsx"],"sourcesContent":["import \"./defer\";\nimport { renderToReadableStream } from \"@vitejs/plugin-rsc/rsc\";\nimport { devMainRscPath } from \"./request\";\nimport { generateAppMarker } from \"./marker\";\nimport { deferRegistry } from \"./defer\";\nimport { extractIDFromModulePath } from \"./rscModule\";\nimport { stripBasePath } from \"../util/basePath\";\nimport { urlPathToFileCandidates } from \"../util/urlPath\";\nimport { resolveRoot, resolveApp } from \"./resolveEntry\";\nimport type { EntryDefinition, GetEntriesResult } from \"../entryDefinition\";\n\nexport type RscPayload = {\n root: React.ReactNode;\n};\n\nexport type EntryBuildResult = {\n path: string;\n html: ReadableStream<Uint8Array>;\n appRsc: ReadableStream<Uint8Array>;\n};\n\nimport { ssr as ssrEnabled } from \"virtual:funstack/config\";\n\nasync function loadEntriesList(): Promise<EntryDefinition[]> {\n const getEntries = (await import(\"virtual:funstack/entries\")).default;\n const result: GetEntriesResult = getEntries();\n const entries: EntryDefinition[] = [];\n for await (const entry of result) {\n entries.push(entry);\n }\n return entries;\n}\n\n/**\n * Find the entry matching a URL path from a list of entries.\n */\nfunction findEntryForUrlPath(\n entries: EntryDefinition[],\n urlPath: string,\n): EntryDefinition | undefined {\n const candidates = urlPathToFileCandidates(urlPath);\n for (const candidate of candidates) {\n const entry = entries.find((e) => e.path === candidate);\n if (entry) {\n return entry;\n }\n }\n return undefined;\n}\n\n/**\n * Renders a single entry to an HTML response.\n */\nasync function renderEntryToResponse(\n entry: EntryDefinition,\n timings: string[],\n): Promise<Response> {\n const marker = generateAppMarker();\n\n const resolveStart = performance.now();\n const Root = await resolveRoot(entry.root);\n const appNode = await resolveApp(entry.app);\n timings.push(`resolve;dur=${performance.now() - resolveStart}`);\n\n const ssrModuleStart = performance.now();\n const ssrEntryModule = await import.meta.viteRsc.loadModule<\n typeof import(\"../ssr/entry\")\n >(\"ssr\");\n timings.push(`ssr-module;dur=${performance.now() - ssrModuleStart}`);\n\n if (ssrEnabled) {\n // SSR on: single RSC stream with full tree\n const rscStart = performance.now();\n const rootRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n timings.push(`rsc;dur=${performance.now() - rscStart}`);\n\n const ssrStart = performance.now();\n const ssrResult = await ssrEntryModule.renderHTML(rootRscStream, {\n appEntryMarker: marker,\n build: false,\n ssr: true,\n deferRegistry,\n });\n timings.push(`ssr;dur=${performance.now() - ssrStart}`);\n\n return new Response(ssrResult.stream, {\n status: ssrResult.status,\n headers: {\n \"Content-type\": \"text/html\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n } else {\n // SSR off: shell RSC for SSR, full RSC for client\n const rscStart = performance.now();\n const shellRscStream = renderToReadableStream<RscPayload>({\n root: (\n <Root>\n <span id={marker} />\n </Root>\n ),\n });\n const clientRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n timings.push(`rsc;dur=${performance.now() - rscStart}`);\n\n const ssrStart = performance.now();\n const ssrResult = await ssrEntryModule.renderHTML(shellRscStream, {\n appEntryMarker: marker,\n build: false,\n ssr: false,\n clientRscStream,\n });\n timings.push(`ssr;dur=${performance.now() - ssrStart}`);\n\n return new Response(ssrResult.stream, {\n status: ssrResult.status,\n headers: {\n \"Content-type\": \"text/html\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n}\n\n/**\n * Entrypoint to serve HTML response in dev environment.\n * Accepts a Request to determine which entry to render based on URL path.\n */\nexport async function serveHTML(request: Request): Promise<Response> {\n const timings: string[] = [];\n\n const entriesStart = performance.now();\n const entries = await loadEntriesList();\n timings.push(`entries;dur=${performance.now() - entriesStart}`);\n\n const url = new URL(request.url);\n const urlPath = stripBasePath(url.pathname);\n let entry = findEntryForUrlPath(entries, urlPath);\n\n // SPA fallback: if no entry matched, fall back to index.html or index.htm entry\n if (!entry) {\n entry = entries.find(\n (e) => e.path === \"index.html\" || e.path === \"index.htm\",\n );\n }\n\n if (!entry) {\n return new Response(\"Not Found\", {\n status: 404,\n headers: { \"Content-type\": \"text/plain\" },\n });\n }\n\n return renderEntryToResponse(entry, timings);\n}\n\nclass ServeRSCError extends Error {\n status: 404 | 500;\n constructor(message: string, status: 404 | 500) {\n super(message);\n this.name = \"ServeRSCError\";\n this.status = status;\n }\n}\n\nexport function isServeRSCError(error: unknown): error is ServeRSCError {\n return error instanceof Error && error.name === \"ServeRSCError\";\n}\n\n/**\n * Serves an RSC stream response\n */\nexport async function serveRSC(request: Request): Promise<Response> {\n const timings: string[] = [];\n const url = new URL(request.url);\n const pathname = stripBasePath(url.pathname);\n if (pathname === devMainRscPath) {\n // root RSC stream is requested (HMR re-fetch always sends full tree)\n // For HMR, re-render the first entry (single-entry mode) or index.html entry\n const entriesStart = performance.now();\n const entries = await loadEntriesList();\n timings.push(`entries;dur=${performance.now() - entriesStart}`);\n\n // Use the first entry for HMR re-fetch\n const entry = entries[0];\n if (!entry) {\n throw new ServeRSCError(\"No entries defined\", 404);\n }\n\n const resolveStart = performance.now();\n const Root = await resolveRoot(entry.root);\n const appNode = await resolveApp(entry.app);\n timings.push(`resolve;dur=${performance.now() - resolveStart}`);\n\n const rscStart = performance.now();\n const rootRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n timings.push(`rsc;dur=${performance.now() - rscStart}`);\n\n return new Response(rootRscStream, {\n status: 200,\n headers: {\n \"content-type\": \"text/x-component;charset=utf-8\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n\n const moduleId = extractIDFromModulePath(pathname);\n if (!moduleId) {\n throw new ServeRSCError(`Invalid RSC module path: ${pathname}`, 404);\n }\n\n const deferLoadStart = performance.now();\n const entry = deferRegistry.load(moduleId);\n if (!entry) {\n throw new ServeRSCError(`RSC component not found: ${moduleId}`, 404);\n }\n timings.push(`defer-load;dur=${performance.now() - deferLoadStart}`);\n\n const { state } = entry;\n switch (state.state) {\n case \"streaming\": {\n return new Response(state.stream, {\n status: 200,\n headers: {\n \"content-type\": \"text/x-component;charset=utf-8\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n case \"ready\": {\n return new Response(await entry.drainPromise, {\n status: 200,\n headers: {\n \"content-type\": \"text/x-component;charset=utf-8\",\n \"Server-Timing\": timings.join(\", \"),\n },\n });\n }\n case \"error\": {\n throw new ServeRSCError(\n `Failed to load RSC component: ${state.error}`,\n 500,\n );\n }\n }\n}\n\n/**\n * Build handler — iterates over all entries and returns per-entry results\n * along with the shared defer registry.\n */\nexport async function build() {\n const getEntries = (await import(\"virtual:funstack/entries\")).default;\n\n const ssrEntryModule = await import.meta.viteRsc.loadModule<\n typeof import(\"../ssr/entry\")\n >(\"ssr\");\n\n const results: EntryBuildResult[] = [];\n for await (const entry of getEntries()) {\n const Root = await resolveRoot(entry.root);\n const appNode = await resolveApp(entry.app);\n\n const marker = generateAppMarker();\n\n let rootRscStream: ReadableStream<Uint8Array>;\n let appRscStream: ReadableStream<Uint8Array>;\n\n if (ssrEnabled) {\n // SSR on: both streams have full tree\n rootRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n appRscStream = renderToReadableStream<RscPayload>({\n root: <Root>{appNode}</Root>,\n });\n } else {\n // SSR off: root stream has shell, app stream has App only\n rootRscStream = renderToReadableStream<RscPayload>({\n root: (\n <Root>\n <span id={marker} />\n </Root>\n ),\n });\n appRscStream = renderToReadableStream<RscPayload>({\n root: appNode,\n });\n }\n\n const ssrResult = await ssrEntryModule.renderHTML(rootRscStream, {\n appEntryMarker: marker,\n build: true,\n ssr: ssrEnabled,\n deferRegistry,\n });\n\n results.push({\n path: entry.path,\n html: ssrResult.stream,\n appRsc: appRscStream,\n });\n }\n\n return {\n entries: results,\n deferRegistry,\n };\n}\n\nexport { defer } from \"./defer\";\n\nif (import.meta.hot) {\n import.meta.hot.accept();\n}\n"],"mappings":"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"}
|
|
@@ -2,7 +2,11 @@ import { DeferRegistry } from "../rsc/defer.mjs";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/rsc-client/clientWrapper.d.ts
|
|
5
|
-
|
|
5
|
+
interface DeferContextValue {
|
|
6
|
+
registry: DeferRegistry;
|
|
7
|
+
createFromReadableStream: <T>(stream: ReadableStream<Uint8Array>) => Promise<T>;
|
|
8
|
+
}
|
|
9
|
+
declare const RegistryContext: React.Context<DeferContextValue | undefined>;
|
|
6
10
|
interface DeferredComponentProps {
|
|
7
11
|
moduleID: string;
|
|
8
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientWrapper.d.mts","names":[],"sources":["../../src/rsc-client/clientWrapper.tsx"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"clientWrapper.d.mts","names":[],"sources":["../../src/rsc-client/clientWrapper.tsx"],"mappings":";;;;UAOU,iBAAA;EACR,QAAA,EAAU,aAAA;EACV,wBAAA,MACE,MAAA,EAAQ,cAAA,CAAe,UAAA,MACpB,OAAA,CAAQ,CAAA;AAAA;AAAA,cAGF,eAAA,EAAe,KAAA,CAAA,OAAA,CAAA,iBAAA;AAAA,UAIlB,sBAAA;EACR,QAAA;AAAA;AAAA,cAGW,iBAAA,EAAmB,KAAA,CAAM,EAAA,CAAG,sBAAA"}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { getModulePathFor } from "../rsc/rscModule.mjs";
|
|
2
2
|
import { withBasePath } from "../util/basePath.mjs";
|
|
3
|
-
import { createFromFetch
|
|
3
|
+
import { createFromFetch } from "@vitejs/plugin-rsc/browser";
|
|
4
4
|
import React, { createContext, use } from "react";
|
|
5
5
|
|
|
6
6
|
//#region src/rsc-client/clientWrapper.tsx
|
|
7
7
|
const RegistryContext = createContext(void 0);
|
|
8
8
|
const DeferredComponent = ({ moduleID }) => {
|
|
9
|
-
const
|
|
9
|
+
const deferContext = use(RegistryContext);
|
|
10
10
|
const modulePath = getModulePathFor(moduleID);
|
|
11
|
-
if (
|
|
12
|
-
const entry = registry.load(moduleID);
|
|
11
|
+
if (deferContext) {
|
|
12
|
+
const entry = deferContext.registry.load(moduleID);
|
|
13
13
|
if (!entry) throw new Error(`Module entry not found for ID '${moduleID}'`);
|
|
14
|
-
return getRSCStreamFromRegistry(entry);
|
|
14
|
+
return getRSCStreamFromRegistry(entry, deferContext.createFromReadableStream);
|
|
15
15
|
}
|
|
16
16
|
return use(getClientRSCStream(withBasePath(modulePath)));
|
|
17
17
|
};
|
|
18
18
|
const moduleToStreamMap = /* @__PURE__ */ new Map();
|
|
19
|
-
async function getRSCStreamFromRegistry(entry) {
|
|
19
|
+
async function getRSCStreamFromRegistry(entry, createFromReadableStream) {
|
|
20
20
|
switch (entry.state.state) {
|
|
21
21
|
case "streaming": return createFromReadableStream(entry.state.stream);
|
|
22
22
|
case "ready": {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const data = await entry.drainPromise;
|
|
24
|
+
return createFromReadableStream(new ReadableStream({ start(controller) {
|
|
25
|
+
const encoder = new TextEncoder();
|
|
26
|
+
controller.enqueue(encoder.encode(data));
|
|
27
|
+
controller.close();
|
|
28
|
+
} }));
|
|
29
29
|
}
|
|
30
30
|
case "error": return Promise.reject(entry.state.error);
|
|
31
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientWrapper.mjs","names":[],"sources":["../../src/rsc-client/clientWrapper.tsx"],"sourcesContent":["import React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"clientWrapper.mjs","names":[],"sources":["../../src/rsc-client/clientWrapper.tsx"],"sourcesContent":["import React from \"react\";\nimport { createFromFetch } from \"@vitejs/plugin-rsc/browser\";\nimport { getModulePathFor } from \"../rsc/rscModule\";\nimport { createContext, use } from \"react\";\nimport type { LoadedDeferEntry, DeferRegistry } from \"../rsc/defer\";\nimport { withBasePath } from \"../util/basePath\";\n\ninterface DeferContextValue {\n registry: DeferRegistry;\n createFromReadableStream: <T>(\n stream: ReadableStream<Uint8Array>,\n ) => Promise<T>;\n}\n\nexport const RegistryContext = createContext<DeferContextValue | undefined>(\n undefined,\n);\n\ninterface DeferredComponentProps {\n moduleID: string;\n}\n\nexport const DeferredComponent: React.FC<DeferredComponentProps> = ({\n moduleID,\n}) => {\n const deferContext = use(RegistryContext);\n const modulePath = getModulePathFor(moduleID);\n if (deferContext) {\n const entry = deferContext.registry.load(moduleID);\n if (!entry) {\n throw new Error(`Module entry not found for ID '${moduleID}'`);\n }\n return getRSCStreamFromRegistry(\n entry,\n deferContext.createFromReadableStream,\n );\n }\n const stream = getClientRSCStream(withBasePath(modulePath));\n return use(stream);\n};\n\nconst moduleToStreamMap = new Map<string, Promise<React.ReactNode>>();\n\nasync function getRSCStreamFromRegistry(\n entry: LoadedDeferEntry,\n createFromReadableStream: <T>(\n stream: ReadableStream<Uint8Array>,\n ) => Promise<T>,\n): Promise<React.ReactNode> {\n switch (entry.state.state) {\n case \"streaming\": {\n return createFromReadableStream<React.ReactNode>(entry.state.stream);\n }\n case \"ready\": {\n const data = await entry.drainPromise;\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(data));\n controller.close();\n },\n });\n return createFromReadableStream<React.ReactNode>(stream);\n }\n case \"error\": {\n return Promise.reject(entry.state.error);\n }\n }\n}\n\nfunction getClientRSCStream(modulePath: string) {\n let stream = moduleToStreamMap.get(modulePath);\n if (!stream) {\n stream = createFromFetch<React.ReactNode>(fetch(modulePath));\n moduleToStreamMap.set(modulePath, stream);\n }\n return stream;\n}\n"],"mappings":";;;;;;AAcA,MAAa,kBAAkB,cAC7B,OACD;AAMD,MAAa,qBAAuD,EAClE,eACI;CACJ,MAAM,eAAe,IAAI,gBAAgB;CACzC,MAAM,aAAa,iBAAiB,SAAS;AAC7C,KAAI,cAAc;EAChB,MAAM,QAAQ,aAAa,SAAS,KAAK,SAAS;AAClD,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,kCAAkC,SAAS,GAAG;AAEhE,SAAO,yBACL,OACA,aAAa,yBACd;;AAGH,QAAO,IADQ,mBAAmB,aAAa,WAAW,CAAC,CACzC;;AAGpB,MAAM,oCAAoB,IAAI,KAAuC;AAErE,eAAe,yBACb,OACA,0BAG0B;AAC1B,SAAQ,MAAM,MAAM,OAApB;EACE,KAAK,YACH,QAAO,yBAA0C,MAAM,MAAM,OAAO;EAEtE,KAAK,SAAS;GACZ,MAAM,OAAO,MAAM,MAAM;AAQzB,UAAO,yBAPQ,IAAI,eAA2B,EAC5C,MAAM,YAAY;IAChB,MAAM,UAAU,IAAI,aAAa;AACjC,eAAW,QAAQ,QAAQ,OAAO,KAAK,CAAC;AACxC,eAAW,OAAO;MAErB,CAAC,CACsD;;EAE1D,KAAK,QACH,QAAO,QAAQ,OAAO,MAAM,MAAM,MAAM;;;AAK9C,SAAS,mBAAmB,YAAoB;CAC9C,IAAI,SAAS,kBAAkB,IAAI,WAAW;AAC9C,KAAI,CAAC,QAAQ;AACX,WAAS,gBAAiC,MAAM,WAAW,CAAC;AAC5D,oBAAkB,IAAI,YAAY,OAAO;;AAE3C,QAAO"}
|
package/dist/ssr/entry.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.d.mts","names":[],"sources":["../../src/ssr/entry.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"entry.d.mts","names":[],"sources":["../../src/ssr/entry.tsx"],"mappings":";;;iBAYsB,UAAA,CACpB,SAAA,EAAW,cAAA,CAAe,UAAA,GAC1B,OAAA;EACE,cAAA;EACA,KAAA;EACA,GAAA;EACA,KAAA;EACA,aAAA,GAAgB,aAAA;EAChB,eAAA,GAAkB,cAAA,CAAe,UAAA;AAAA,IAElC,OAAA;EAAU,MAAA,EAAQ,cAAA,CAAe,UAAA;EAAa,MAAA;AAAA"}
|
package/dist/ssr/entry.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
5
5
|
import { RegistryContext } from "#rsc-client";
|
|
6
6
|
import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
|
|
7
7
|
import { renderToReadableStream } from "react-dom/server.edge";
|
|
8
|
+
import { prerender } from "react-dom/static";
|
|
8
9
|
import { injectRSCPayload } from "rsc-html-stream/server";
|
|
9
10
|
import { preload } from "react-dom";
|
|
10
11
|
|
|
@@ -19,7 +20,10 @@ async function renderHTML(rscStream, options) {
|
|
|
19
20
|
as: "fetch"
|
|
20
21
|
});
|
|
21
22
|
return /* @__PURE__ */ jsx(RegistryContext, {
|
|
22
|
-
value: options.deferRegistry
|
|
23
|
+
value: options.deferRegistry ? {
|
|
24
|
+
registry: options.deferRegistry,
|
|
25
|
+
createFromReadableStream
|
|
26
|
+
} : void 0,
|
|
23
27
|
children: use(payload).root
|
|
24
28
|
});
|
|
25
29
|
}
|
|
@@ -30,11 +34,15 @@ async function renderHTML(rscStream, options) {
|
|
|
30
34
|
let htmlStream;
|
|
31
35
|
let status;
|
|
32
36
|
try {
|
|
33
|
-
|
|
37
|
+
if (options.build) {
|
|
38
|
+
const { prelude, postponed } = await prerender(/* @__PURE__ */ jsx(SsrRoot, {}), { bootstrapScriptContent });
|
|
39
|
+
if (postponed !== null) throw new Error("Unexpected postponed state during prerendering");
|
|
40
|
+
htmlStream = prelude;
|
|
41
|
+
} else htmlStream = await renderToReadableStream(/* @__PURE__ */ jsx(SsrRoot, {}), {
|
|
34
42
|
bootstrapScriptContent,
|
|
35
43
|
nonce: options?.nonce
|
|
36
44
|
});
|
|
37
|
-
} catch {
|
|
45
|
+
} catch (e) {
|
|
38
46
|
status = 500;
|
|
39
47
|
htmlStream = await renderToReadableStream(/* @__PURE__ */ jsx("html", { children: /* @__PURE__ */ jsx("body", { children: /* @__PURE__ */ jsx("noscript", { children: "Internal Server Error: SSR failed" }) }) }), {
|
|
40
48
|
bootstrapScriptContent: `globalThis.__NO_HYDRATE=1;` + bootstrapScriptContent,
|
package/dist/ssr/entry.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.mjs","names":[],"sources":["../../src/ssr/entry.tsx"],"sourcesContent":["import { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { use } from \"react\";\nimport { renderToReadableStream } from \"react-dom/server.edge\";\nimport { injectRSCPayload } from \"rsc-html-stream/server\";\nimport type { RscPayload } from \"../rsc/entry\";\nimport { appClientManifestVar } from \"../client/globals\";\nimport { rscPayloadPlaceholder } from \"../build/rscPath\";\nimport { preload } from \"react-dom\";\nimport type { DeferRegistry } from \"../rsc/defer\";\nimport { RegistryContext } from \"#rsc-client\";\n\nexport async function renderHTML(\n rscStream: ReadableStream<Uint8Array>,\n options: {\n appEntryMarker: string;\n build: boolean;\n ssr?: boolean;\n nonce?: string;\n deferRegistry?: DeferRegistry;\n clientRscStream?: ReadableStream<Uint8Array>;\n },\n): Promise<{ stream: ReadableStream<Uint8Array>; status?: number }> {\n const [rscStream1, rscStream2] = rscStream.tee();\n\n let payload: Promise<RscPayload> | undefined;\n function SsrRoot() {\n // Tip: calling `createFromReadableStream` inside a component\n // makes `preinit`/`preload` work properly.\n payload ??= createFromReadableStream<RscPayload>(rscStream1);\n if (options.build) {\n preload(rscPayloadPlaceholder, {\n crossOrigin: \"anonymous\",\n as: \"fetch\",\n });\n }\n return (\n <RegistryContext
|
|
1
|
+
{"version":3,"file":"entry.mjs","names":[],"sources":["../../src/ssr/entry.tsx"],"sourcesContent":["import { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { use } from \"react\";\nimport { renderToReadableStream } from \"react-dom/server.edge\";\nimport { prerender } from \"react-dom/static\";\nimport { injectRSCPayload } from \"rsc-html-stream/server\";\nimport type { RscPayload } from \"../rsc/entry\";\nimport { appClientManifestVar } from \"../client/globals\";\nimport { rscPayloadPlaceholder } from \"../build/rscPath\";\nimport { preload } from \"react-dom\";\nimport type { DeferRegistry } from \"../rsc/defer\";\nimport { RegistryContext } from \"#rsc-client\";\n\nexport async function renderHTML(\n rscStream: ReadableStream<Uint8Array>,\n options: {\n appEntryMarker: string;\n build: boolean;\n ssr?: boolean;\n nonce?: string;\n deferRegistry?: DeferRegistry;\n clientRscStream?: ReadableStream<Uint8Array>;\n },\n): Promise<{ stream: ReadableStream<Uint8Array>; status?: number }> {\n const [rscStream1, rscStream2] = rscStream.tee();\n\n let payload: Promise<RscPayload> | undefined;\n function SsrRoot() {\n // Tip: calling `createFromReadableStream` inside a component\n // makes `preinit`/`preload` work properly.\n payload ??= createFromReadableStream<RscPayload>(rscStream1);\n if (options.build) {\n preload(rscPayloadPlaceholder, {\n crossOrigin: \"anonymous\",\n as: \"fetch\",\n });\n }\n return (\n <RegistryContext\n value={\n options.deferRegistry\n ? {\n registry: options.deferRegistry,\n createFromReadableStream,\n }\n : undefined\n }\n >\n {use(payload).root}\n </RegistryContext>\n );\n }\n\n let bootstrapScriptContent: string = \"\";\n if (options.build) {\n if (options.ssr) {\n // SSR on: no marker needed, client hydrates full document\n bootstrapScriptContent += `globalThis.${appClientManifestVar}={stream:\"${rscPayloadPlaceholder}\"};\\n`;\n } else {\n // SSR off: marker needed for client to find mount point\n bootstrapScriptContent += `globalThis.${appClientManifestVar}={marker:\"${options.appEntryMarker}\",stream:\"${rscPayloadPlaceholder}\"};\\n`;\n }\n }\n bootstrapScriptContent +=\n await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n\n let htmlStream: ReadableStream<Uint8Array>;\n let status: number | undefined;\n try {\n if (options.build) {\n const { prelude, postponed } = await prerender(<SsrRoot />, {\n bootstrapScriptContent,\n });\n if (postponed !== null) {\n throw new Error(\"Unexpected postponed state during prerendering\");\n }\n\n htmlStream = prelude;\n } else {\n htmlStream = await renderToReadableStream(<SsrRoot />, {\n bootstrapScriptContent,\n nonce: options?.nonce,\n });\n }\n } catch (e) {\n // In this case, RSC payload is still sent to client and we let client render from scratch anyway.\n // This triggers the error boundary on client side.\n status = 500;\n htmlStream = await renderToReadableStream(\n <html>\n <body>\n <noscript>Internal Server Error: SSR failed</noscript>\n </body>\n </html>,\n {\n bootstrapScriptContent:\n `globalThis.__NO_HYDRATE=1;` + bootstrapScriptContent,\n nonce: options?.nonce,\n },\n );\n }\n\n let responseStream = htmlStream;\n\n // Inject RSC payload into HTML for client consumption.\n // In dev: always inject (client reads from inline stream).\n // In build+SSR: skip (HTML already has full content, client hydrates directly).\n // In build+no-SSR: skip (client fetches RSC from separate file).\n if (!options.build) {\n const streamToInject = options.clientRscStream ?? rscStream2;\n responseStream = responseStream.pipeThrough(\n injectRSCPayload(streamToInject, {\n nonce: options?.nonce,\n }),\n );\n }\n\n return { stream: responseStream, status };\n}\n"],"mappings":";;;;;;;;;;;;AAYA,eAAsB,WACpB,WACA,SAQkE;CAClE,MAAM,CAAC,YAAY,cAAc,UAAU,KAAK;CAEhD,IAAI;CACJ,SAAS,UAAU;AAGjB,cAAY,yBAAqC,WAAW;AAC5D,MAAI,QAAQ,MACV,SAAQ,uBAAuB;GAC7B,aAAa;GACb,IAAI;GACL,CAAC;AAEJ,SACE,oBAAC;GACC,OACE,QAAQ,gBACJ;IACE,UAAU,QAAQ;IAClB;IACD,GACD;aAGL,IAAI,QAAQ,CAAC;IACE;;CAItB,IAAI,yBAAiC;AACrC,KAAI,QAAQ,MACV,KAAI,QAAQ,IAEV,2BAA0B,cAAc,qBAAqB,YAAY,sBAAsB;KAG/F,2BAA0B,cAAc,qBAAqB,YAAY,QAAQ,eAAe,YAAY,sBAAsB;AAGtI,2BACE,MAAM,OAAO,KAAK,QAAQ,2BAA2B,QAAQ;CAE/D,IAAI;CACJ,IAAI;AACJ,KAAI;AACF,MAAI,QAAQ,OAAO;GACjB,MAAM,EAAE,SAAS,cAAc,MAAM,UAAU,oBAAC,YAAU,EAAE,EAC1D,wBACD,CAAC;AACF,OAAI,cAAc,KAChB,OAAM,IAAI,MAAM,iDAAiD;AAGnE,gBAAa;QAEb,cAAa,MAAM,uBAAuB,oBAAC,YAAU,EAAE;GACrD;GACA,OAAO,SAAS;GACjB,CAAC;UAEG,GAAG;AAGV,WAAS;AACT,eAAa,MAAM,uBACjB,oBAAC,oBACC,oBAAC,oBACC,oBAAC,wBAAS,sCAA4C,GACjD,GACF,EACP;GACE,wBACE,+BAA+B;GACjC,OAAO,SAAS;GACjB,CACF;;CAGH,IAAI,iBAAiB;AAMrB,KAAI,CAAC,QAAQ,OAAO;EAClB,MAAM,iBAAiB,QAAQ,mBAAmB;AAClD,mBAAiB,eAAe,YAC9B,iBAAiB,gBAAgB,EAC/B,OAAO,SAAS,OACjB,CAAC,CACH;;AAGH,QAAO;EAAE,QAAQ;EAAgB;EAAQ"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import { DeferredComponent, RegistryContext } from "./clientWrapper.mjs";
|