@vertz/ui-server 0.2.32 → 0.2.33
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 +54 -50
- package/dist/bun-dev-server.d.ts +14 -1
- package/dist/bun-dev-server.js +11 -4
- package/dist/index.js +7 -7
- package/dist/node-handler.js +2 -2
- package/dist/shared/{chunk-gbcsa7h1.js → chunk-2kx402c1.js} +3 -204
- package/dist/shared/{chunk-34fexgex.js → chunk-hx7drzm3.js} +599 -409
- package/dist/shared/{chunk-es0406qq.js → chunk-xdb8qn68.js} +17 -5
- package/dist/ssr/index.d.ts +1 -1
- package/dist/ssr/index.js +2 -2
- package/package.json +18 -16
package/README.md
CHANGED
|
@@ -85,14 +85,14 @@ const html = await renderToHTML(App, {
|
|
|
85
85
|
|
|
86
86
|
**Options:**
|
|
87
87
|
|
|
88
|
-
| Option
|
|
89
|
-
|
|
90
|
-
| `app`
|
|
91
|
-
| `url`
|
|
92
|
-
| `theme`
|
|
93
|
-
| `styles`
|
|
94
|
-
| `head`
|
|
95
|
-
| `container` | `string`
|
|
88
|
+
| Option | Type | Description |
|
|
89
|
+
| ----------- | ------------- | ----------------------------------------- |
|
|
90
|
+
| `app` | `() => VNode` | App component function |
|
|
91
|
+
| `url` | `string` | Request URL for SSR routing |
|
|
92
|
+
| `theme` | `Theme` | Theme definition for CSS vars |
|
|
93
|
+
| `styles` | `string[]` | Global CSS strings to inject |
|
|
94
|
+
| `head` | `object` | Head config: `title`, `meta[]`, `links[]` |
|
|
95
|
+
| `container` | `string` | Container selector (default `'#app'`) |
|
|
96
96
|
|
|
97
97
|
### `renderPage(vnode, options?)`
|
|
98
98
|
|
|
@@ -113,18 +113,18 @@ return renderPage(<App />, {
|
|
|
113
113
|
|
|
114
114
|
**Options:**
|
|
115
115
|
|
|
116
|
-
| Option
|
|
117
|
-
|
|
118
|
-
| `status`
|
|
119
|
-
| `title`
|
|
120
|
-
| `description` | `string`
|
|
121
|
-
| `lang`
|
|
122
|
-
| `favicon`
|
|
123
|
-
| `og`
|
|
124
|
-
| `twitter`
|
|
125
|
-
| `scripts`
|
|
126
|
-
| `styles`
|
|
127
|
-
| `head`
|
|
116
|
+
| Option | Type | Description |
|
|
117
|
+
| ------------- | ---------- | ---------------------------------------------------------- |
|
|
118
|
+
| `status` | `number` | HTTP status code (default `200`) |
|
|
119
|
+
| `title` | `string` | Page title |
|
|
120
|
+
| `description` | `string` | Meta description |
|
|
121
|
+
| `lang` | `string` | HTML lang attribute (default `'en'`) |
|
|
122
|
+
| `favicon` | `string` | Favicon URL |
|
|
123
|
+
| `og` | `object` | Open Graph: `title`, `description`, `image`, `url`, `type` |
|
|
124
|
+
| `twitter` | `object` | Twitter card: `card`, `site` |
|
|
125
|
+
| `scripts` | `string[]` | Script URLs for end of body |
|
|
126
|
+
| `styles` | `string[]` | Stylesheet URLs for head |
|
|
127
|
+
| `head` | `string` | Raw HTML escape hatch for head |
|
|
128
128
|
|
|
129
129
|
### `renderToStream(tree, options?)`
|
|
130
130
|
|
|
@@ -148,6 +148,7 @@ return new Response(stream, {
|
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
**Options:**
|
|
151
|
+
|
|
151
152
|
- `nonce?: string` — CSP nonce for inline scripts
|
|
152
153
|
|
|
153
154
|
### `serializeToHtml(node)`
|
|
@@ -203,11 +204,11 @@ removeDomShim();
|
|
|
203
204
|
|
|
204
205
|
**Note:** `renderToHTML` handles DOM shim setup and teardown automatically. You only need these when using lower-level rendering APIs.
|
|
205
206
|
|
|
206
|
-
| Export
|
|
207
|
-
|
|
207
|
+
| Export | Description |
|
|
208
|
+
| ------------------ | -------------------------------------------- |
|
|
208
209
|
| `installDomShim()` | Install the minimal DOM shim on `globalThis` |
|
|
209
|
-
| `removeDomShim()`
|
|
210
|
-
| `toVNode(element)` | Convert an SSR element to a VNode
|
|
210
|
+
| `removeDomShim()` | Remove the DOM shim from `globalThis` |
|
|
211
|
+
| `toVNode(element)` | Convert an SSR element to a VNode |
|
|
211
212
|
|
|
212
213
|
---
|
|
213
214
|
|
|
@@ -228,6 +229,7 @@ const headHtml = renderHeadToHtml(headCollector.getEntries());
|
|
|
228
229
|
```
|
|
229
230
|
|
|
230
231
|
**`HeadCollector` methods:**
|
|
232
|
+
|
|
231
233
|
- `addTitle(text)` — Add a `<title>` tag
|
|
232
234
|
- `addMeta(attrs)` — Add a `<meta>` tag
|
|
233
235
|
- `addLink(attrs)` — Add a `<link>` tag
|
|
@@ -266,7 +268,9 @@ const hydratedNode = wrapWithHydrationMarkers(counterNode, {
|
|
|
266
268
|
<div data-v-id="Counter" data-v-key="counter-0">
|
|
267
269
|
<span>Count: 0</span>
|
|
268
270
|
<button>+</button>
|
|
269
|
-
<script type="application/json">
|
|
271
|
+
<script type="application/json">
|
|
272
|
+
{ "initial": 0 }
|
|
273
|
+
</script>
|
|
270
274
|
</div>
|
|
271
275
|
```
|
|
272
276
|
|
|
@@ -363,24 +367,24 @@ await server.listen();
|
|
|
363
367
|
|
|
364
368
|
**Options:**
|
|
365
369
|
|
|
366
|
-
| Option
|
|
367
|
-
|
|
368
|
-
| `entry`
|
|
369
|
-
| `port`
|
|
370
|
-
| `host`
|
|
371
|
-
| `viteConfig`
|
|
372
|
-
| `middleware`
|
|
373
|
-
| `skipModuleInvalidation` | `boolean`
|
|
374
|
-
| `logRequests`
|
|
370
|
+
| Option | Type | Default | Description |
|
|
371
|
+
| ------------------------ | -------------- | ----------- | ----------------------------------------- |
|
|
372
|
+
| `entry` | `string` | (required) | Path to the SSR entry module |
|
|
373
|
+
| `port` | `number` | `5173` | Port to listen on |
|
|
374
|
+
| `host` | `string` | `'0.0.0.0'` | Host to bind to |
|
|
375
|
+
| `viteConfig` | `InlineConfig` | `{}` | Custom Vite configuration |
|
|
376
|
+
| `middleware` | `function` | — | Custom middleware before SSR handler |
|
|
377
|
+
| `skipModuleInvalidation` | `boolean` | `false` | Skip invalidating modules on each request |
|
|
378
|
+
| `logRequests` | `boolean` | `true` | Log requests to console |
|
|
375
379
|
|
|
376
380
|
**`DevServer` interface:**
|
|
377
381
|
|
|
378
|
-
| Property/Method | Description
|
|
379
|
-
|
|
380
|
-
| `listen()`
|
|
381
|
-
| `close()`
|
|
382
|
-
| `vite`
|
|
383
|
-
| `httpServer`
|
|
382
|
+
| Property/Method | Description |
|
|
383
|
+
| --------------- | ------------------------------ |
|
|
384
|
+
| `listen()` | Start the server |
|
|
385
|
+
| `close()` | Stop the server |
|
|
386
|
+
| `vite` | The underlying `ViteDevServer` |
|
|
387
|
+
| `httpServer` | The underlying `http.Server` |
|
|
384
388
|
|
|
385
389
|
The entry module should export a `renderToString(url: string)` function that returns HTML.
|
|
386
390
|
|
|
@@ -390,11 +394,11 @@ The entry module should export a `renderToString(url: string)` function that ret
|
|
|
390
394
|
|
|
391
395
|
The `@vertz/ui-server/jsx-runtime` subpath provides a server-side JSX factory that produces VNode trees compatible with `renderToStream`. During SSR, Vite's `ssrLoadModule` swaps this in automatically.
|
|
392
396
|
|
|
393
|
-
| Export
|
|
394
|
-
|
|
395
|
-
| `jsx`
|
|
396
|
-
| `jsxs`
|
|
397
|
-
| `Fragment` | Fragment component
|
|
397
|
+
| Export | Description |
|
|
398
|
+
| ---------- | ------------------------------------- |
|
|
399
|
+
| `jsx` | JSX factory for single-child elements |
|
|
400
|
+
| `jsxs` | JSX factory for multi-child elements |
|
|
401
|
+
| `Fragment` | Fragment component |
|
|
398
402
|
|
|
399
403
|
---
|
|
400
404
|
|
|
@@ -430,11 +434,11 @@ import type {
|
|
|
430
434
|
|
|
431
435
|
## Utilities
|
|
432
436
|
|
|
433
|
-
| Export
|
|
434
|
-
|
|
435
|
-
| `streamToString(stream)`
|
|
436
|
-
| `collectStreamChunks(stream)` | Collect stream chunks as a `string[]`
|
|
437
|
-
| `encodeChunk(html)`
|
|
437
|
+
| Export | Description |
|
|
438
|
+
| ----------------------------- | -------------------------------------------------- |
|
|
439
|
+
| `streamToString(stream)` | Convert a `ReadableStream<Uint8Array>` to a string |
|
|
440
|
+
| `collectStreamChunks(stream)` | Collect stream chunks as a `string[]` |
|
|
441
|
+
| `encodeChunk(html)` | Encode a string to a `Uint8Array` chunk |
|
|
438
442
|
|
|
439
443
|
---
|
|
440
444
|
|
package/dist/bun-dev-server.d.ts
CHANGED
|
@@ -133,6 +133,19 @@ declare function isStaleGraphError(message: string): boolean;
|
|
|
133
133
|
* addEventListener("DOMContentLoaded",function(event){location.reload()})
|
|
134
134
|
*/
|
|
135
135
|
declare function isReloadStub(text: string): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Determine whether the dev server should check for a stale dev bundler
|
|
138
|
+
* (and potentially restart) after a file change.
|
|
139
|
+
*
|
|
140
|
+
* When the bundle hash changed, the dev bundler processed the update
|
|
141
|
+
* successfully — HMR will deliver it. Checking for a reload stub would
|
|
142
|
+
* race with Bun's internal update and produce false positives.
|
|
143
|
+
*
|
|
144
|
+
* When the hash did NOT change, the dev bundler may be stuck (e.g. new
|
|
145
|
+
* file imported for the first time). The stale check is needed to detect
|
|
146
|
+
* this and auto-restart.
|
|
147
|
+
*/
|
|
148
|
+
declare function shouldCheckStaleBundler(hashChanged: boolean): boolean;
|
|
136
149
|
/** A resolved stack frame for terminal logging. */
|
|
137
150
|
interface TerminalStackFrame {
|
|
138
151
|
functionName: string | null;
|
|
@@ -244,4 +257,4 @@ declare function clearSSRRequireCache(): number;
|
|
|
244
257
|
* SSR is always on. HMR always works. No mode toggle needed.
|
|
245
258
|
*/
|
|
246
259
|
declare function createBunDevServer(options: BunDevServerOptions): BunDevServer;
|
|
247
|
-
export { parseHMRAssets, isStaleGraphError, isReloadStub, generateSSRPageHtml, formatTerminalRuntimeError, detectFaviconTag, createRuntimeErrorDeduplicator, createFetchInterceptor, createBunDevServer, clearSSRRequireCache, buildScriptTag, SSRPageHtmlOptions, HMRAssets, FetchInterceptorOptions, ErrorDetail, ErrorCategory, BunDevServerOptions, BunDevServer };
|
|
260
|
+
export { shouldCheckStaleBundler, parseHMRAssets, isStaleGraphError, isReloadStub, generateSSRPageHtml, formatTerminalRuntimeError, detectFaviconTag, createRuntimeErrorDeduplicator, createFetchInterceptor, createBunDevServer, clearSSRRequireCache, buildScriptTag, SSRPageHtmlOptions, HMRAssets, FetchInterceptorOptions, ErrorDetail, ErrorCategory, BunDevServerOptions, BunDevServer };
|
package/dist/bun-dev-server.js
CHANGED
|
@@ -2556,6 +2556,9 @@ function isStaleGraphError(message) {
|
|
|
2556
2556
|
function isReloadStub(text) {
|
|
2557
2557
|
return text.trimStart().startsWith("try{location.reload()}");
|
|
2558
2558
|
}
|
|
2559
|
+
function shouldCheckStaleBundler(hashChanged) {
|
|
2560
|
+
return !hashChanged;
|
|
2561
|
+
}
|
|
2559
2562
|
var MAX_TERMINAL_STACK_FRAMES = 5;
|
|
2560
2563
|
function formatTerminalRuntimeError(errors, parsedStack) {
|
|
2561
2564
|
const primary = errors[0];
|
|
@@ -3913,6 +3916,7 @@ data: {}
|
|
|
3913
3916
|
await discoverHMRAssets();
|
|
3914
3917
|
if (stopped)
|
|
3915
3918
|
return;
|
|
3919
|
+
let hashChanged = false;
|
|
3916
3920
|
try {
|
|
3917
3921
|
const clientRelative = rawClientSrc.replace(/^\//, "");
|
|
3918
3922
|
const result = await Bun.build({
|
|
@@ -3944,10 +3948,12 @@ data: {}
|
|
|
3944
3948
|
if (stopped)
|
|
3945
3949
|
return;
|
|
3946
3950
|
await discoverHMRAssets();
|
|
3947
|
-
if (bundledScriptUrl !== prevUrl)
|
|
3951
|
+
if (bundledScriptUrl !== prevUrl) {
|
|
3952
|
+
hashChanged = true;
|
|
3948
3953
|
break;
|
|
3954
|
+
}
|
|
3949
3955
|
}
|
|
3950
|
-
if (bundledScriptUrl && server && !isRestarting) {
|
|
3956
|
+
if (!hashChanged && bundledScriptUrl && server && !isRestarting) {
|
|
3951
3957
|
try {
|
|
3952
3958
|
const bundleRes = await fetch(`http://${host}:${server.port}${bundledScriptUrl}`);
|
|
3953
3959
|
const bundleText = await bundleRes.text();
|
|
@@ -4041,7 +4047,7 @@ data: {}
|
|
|
4041
4047
|
if (logRequests) {
|
|
4042
4048
|
console.log("[Server] SSR module refreshed");
|
|
4043
4049
|
}
|
|
4044
|
-
if (await checkAndRestartIfBundlerStale())
|
|
4050
|
+
if (!hashChanged && await checkAndRestartIfBundlerStale())
|
|
4045
4051
|
return;
|
|
4046
4052
|
clearErrorForFileChange();
|
|
4047
4053
|
} catch {
|
|
@@ -4070,7 +4076,7 @@ data: {}
|
|
|
4070
4076
|
if (logRequests) {
|
|
4071
4077
|
console.log("[Server] SSR module refreshed (retry)");
|
|
4072
4078
|
}
|
|
4073
|
-
if (await checkAndRestartIfBundlerStale())
|
|
4079
|
+
if (!hashChanged && await checkAndRestartIfBundlerStale())
|
|
4074
4080
|
return;
|
|
4075
4081
|
clearErrorForFileChange();
|
|
4076
4082
|
} catch (e2) {
|
|
@@ -4183,6 +4189,7 @@ data: {}
|
|
|
4183
4189
|
return devServer;
|
|
4184
4190
|
}
|
|
4185
4191
|
export {
|
|
4192
|
+
shouldCheckStaleBundler,
|
|
4186
4193
|
parseHMRAssets,
|
|
4187
4194
|
isStaleGraphError,
|
|
4188
4195
|
isReloadStub,
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createHoles,
|
|
3
2
|
createSSRHandler,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
ssrRenderAot
|
|
7
|
-
} from "./shared/chunk-gbcsa7h1.js";
|
|
3
|
+
loadAotManifest
|
|
4
|
+
} from "./shared/chunk-2kx402c1.js";
|
|
8
5
|
import {
|
|
9
6
|
createNodeHandler
|
|
10
|
-
} from "./shared/chunk-
|
|
7
|
+
} from "./shared/chunk-xdb8qn68.js";
|
|
11
8
|
import {
|
|
12
9
|
collectStreamChunks,
|
|
13
10
|
compileThemeCached,
|
|
14
11
|
createAccessSetScript,
|
|
12
|
+
createHoles,
|
|
15
13
|
createRequestContext,
|
|
16
14
|
createSSRDataChunk,
|
|
17
15
|
createSessionScript,
|
|
@@ -23,6 +21,7 @@ import {
|
|
|
23
21
|
evaluateAccessRule,
|
|
24
22
|
getAccessSetForSSR,
|
|
25
23
|
getStreamingRuntimeScript,
|
|
24
|
+
isAotDebugEnabled,
|
|
26
25
|
matchUrlToPatterns,
|
|
27
26
|
reconstructDescriptors,
|
|
28
27
|
renderToStream,
|
|
@@ -30,11 +29,12 @@ import {
|
|
|
30
29
|
safeSerialize,
|
|
31
30
|
serializeToHtml,
|
|
32
31
|
ssrDiscoverQueries,
|
|
32
|
+
ssrRenderAot,
|
|
33
33
|
ssrRenderSinglePass,
|
|
34
34
|
ssrRenderToString,
|
|
35
35
|
streamToString,
|
|
36
36
|
toPrefetchSession
|
|
37
|
-
} from "./shared/chunk-
|
|
37
|
+
} from "./shared/chunk-hx7drzm3.js";
|
|
38
38
|
import {
|
|
39
39
|
clearGlobalSSRTimeout,
|
|
40
40
|
createSSRAdapter,
|
package/dist/node-handler.js
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
compileThemeCached,
|
|
3
|
-
createRequestContext,
|
|
4
2
|
encodeChunk,
|
|
5
3
|
escapeAttr,
|
|
6
4
|
injectIntoTemplate,
|
|
7
|
-
matchUrlToPatterns,
|
|
8
5
|
precomputeHandlerState,
|
|
9
|
-
reconstructDescriptors,
|
|
10
6
|
resolveRouteModulepreload,
|
|
11
7
|
resolveSession,
|
|
12
8
|
safeSerialize,
|
|
13
|
-
|
|
9
|
+
ssrRenderAot,
|
|
14
10
|
ssrRenderProgressive,
|
|
15
11
|
ssrRenderSinglePass,
|
|
16
12
|
ssrStreamNavQueries,
|
|
17
13
|
toPrefetchSession
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import {
|
|
20
|
-
clearGlobalSSRTimeout,
|
|
21
|
-
installDomShim,
|
|
22
|
-
setGlobalSSRTimeout,
|
|
23
|
-
ssrStorage,
|
|
24
|
-
toVNode
|
|
25
|
-
} from "./chunk-ybftdw1r.js";
|
|
14
|
+
} from "./chunk-hx7drzm3.js";
|
|
26
15
|
|
|
27
16
|
// src/aot-manifest-loader.ts
|
|
28
17
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -66,196 +55,6 @@ async function loadAotManifest(serverDir) {
|
|
|
66
55
|
return { routes };
|
|
67
56
|
}
|
|
68
57
|
|
|
69
|
-
// src/ssr-aot-pipeline.ts
|
|
70
|
-
function createHoles(holeNames, module, url, queryCache, ssrAuth) {
|
|
71
|
-
if (holeNames.length === 0)
|
|
72
|
-
return {};
|
|
73
|
-
const holes = {};
|
|
74
|
-
for (const name of holeNames) {
|
|
75
|
-
holes[name] = () => {
|
|
76
|
-
const holeCtx = createRequestContext(url);
|
|
77
|
-
for (const [key, data] of queryCache) {
|
|
78
|
-
holeCtx.queryCache.set(key, data);
|
|
79
|
-
}
|
|
80
|
-
if (ssrAuth) {
|
|
81
|
-
holeCtx.ssrAuth = ssrAuth;
|
|
82
|
-
}
|
|
83
|
-
holeCtx.resolvedComponents = new Map;
|
|
84
|
-
return ssrStorage.run(holeCtx, () => {
|
|
85
|
-
ensureDomShim();
|
|
86
|
-
const factory = resolveHoleComponent(module, name);
|
|
87
|
-
if (!factory) {
|
|
88
|
-
return `<!-- AOT hole: ${name} not found -->`;
|
|
89
|
-
}
|
|
90
|
-
const node = factory();
|
|
91
|
-
const vnode = toVNode(node);
|
|
92
|
-
return serializeToHtml(vnode);
|
|
93
|
-
});
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
return holes;
|
|
97
|
-
}
|
|
98
|
-
function resolveHoleComponent(module, name) {
|
|
99
|
-
const moduleRecord = module;
|
|
100
|
-
const exported = moduleRecord[name];
|
|
101
|
-
if (typeof exported === "function") {
|
|
102
|
-
return exported;
|
|
103
|
-
}
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
async function ssrRenderAot(module, url, options) {
|
|
107
|
-
const { aotManifest, manifest } = options;
|
|
108
|
-
const ssrTimeout = options.ssrTimeout ?? 300;
|
|
109
|
-
const normalizedUrl = url.endsWith("/index.html") ? url.slice(0, -"/index.html".length) || "/" : url;
|
|
110
|
-
const fallbackOptions = {
|
|
111
|
-
ssrTimeout,
|
|
112
|
-
fallbackMetrics: options.fallbackMetrics,
|
|
113
|
-
ssrAuth: options.ssrAuth,
|
|
114
|
-
manifest,
|
|
115
|
-
prefetchSession: options.prefetchSession
|
|
116
|
-
};
|
|
117
|
-
const aotPatterns = Object.keys(aotManifest.routes);
|
|
118
|
-
const matches = matchUrlToPatterns(normalizedUrl, aotPatterns);
|
|
119
|
-
if (matches.length === 0) {
|
|
120
|
-
return ssrRenderSinglePass(module, normalizedUrl, fallbackOptions);
|
|
121
|
-
}
|
|
122
|
-
const match = matches[matches.length - 1];
|
|
123
|
-
if (!match) {
|
|
124
|
-
return ssrRenderSinglePass(module, normalizedUrl, fallbackOptions);
|
|
125
|
-
}
|
|
126
|
-
const aotEntry = aotManifest.routes[match.pattern];
|
|
127
|
-
if (!aotEntry) {
|
|
128
|
-
return ssrRenderSinglePass(module, normalizedUrl, fallbackOptions);
|
|
129
|
-
}
|
|
130
|
-
const queryCache = new Map;
|
|
131
|
-
if (aotEntry.queryKeys && aotEntry.queryKeys.length > 0 && manifest?.routeEntries) {
|
|
132
|
-
const apiClient = module.api;
|
|
133
|
-
if (apiClient) {
|
|
134
|
-
await prefetchForAot(aotEntry.queryKeys, manifest.routeEntries, match, apiClient, ssrTimeout, queryCache);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
try {
|
|
138
|
-
setGlobalSSRTimeout(ssrTimeout);
|
|
139
|
-
const holes = createHoles(aotEntry.holes, module, normalizedUrl, queryCache, options.ssrAuth);
|
|
140
|
-
const ctx = {
|
|
141
|
-
holes,
|
|
142
|
-
getData: (key) => queryCache.get(key),
|
|
143
|
-
session: options.prefetchSession,
|
|
144
|
-
params: match.params
|
|
145
|
-
};
|
|
146
|
-
const data = {};
|
|
147
|
-
for (const [key, value] of queryCache) {
|
|
148
|
-
data[key] = value;
|
|
149
|
-
}
|
|
150
|
-
const html = aotEntry.render(data, ctx);
|
|
151
|
-
if (options.diagnostics && isAotDebugEnabled()) {
|
|
152
|
-
try {
|
|
153
|
-
const domResult = await ssrRenderSinglePass(module, normalizedUrl, fallbackOptions);
|
|
154
|
-
if (domResult.html !== html) {
|
|
155
|
-
options.diagnostics.recordDivergence(match.pattern, html, domResult.html);
|
|
156
|
-
}
|
|
157
|
-
} catch {}
|
|
158
|
-
}
|
|
159
|
-
const css = collectCSSFromModule(module, options.fallbackMetrics);
|
|
160
|
-
const ssrData = [];
|
|
161
|
-
for (const [key, data2] of queryCache) {
|
|
162
|
-
ssrData.push({ key, data: data2 });
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
html,
|
|
166
|
-
css: css.cssString,
|
|
167
|
-
ssrData,
|
|
168
|
-
headTags: css.preloadTags,
|
|
169
|
-
matchedRoutePatterns: [match.pattern]
|
|
170
|
-
};
|
|
171
|
-
} finally {
|
|
172
|
-
clearGlobalSSRTimeout();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
async function prefetchForAot(queryKeys, routeEntries, match, apiClient, ssrTimeout, queryCache) {
|
|
176
|
-
const entry = routeEntries[match.pattern];
|
|
177
|
-
if (!entry)
|
|
178
|
-
return;
|
|
179
|
-
const queryKeySet = new Set(queryKeys);
|
|
180
|
-
const fetchJobs = [];
|
|
181
|
-
for (const query of entry.queries) {
|
|
182
|
-
if (!query.entity || !query.operation)
|
|
183
|
-
continue;
|
|
184
|
-
const aotKey = `${query.entity}-${query.operation}`;
|
|
185
|
-
if (!queryKeySet.has(aotKey))
|
|
186
|
-
continue;
|
|
187
|
-
const descriptors = reconstructDescriptors([query], match.params, apiClient);
|
|
188
|
-
if (descriptors.length > 0 && descriptors[0]) {
|
|
189
|
-
fetchJobs.push({ aotKey, fetchFn: descriptors[0].fetch });
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (fetchJobs.length === 0)
|
|
193
|
-
return;
|
|
194
|
-
await Promise.allSettled(fetchJobs.map(({ aotKey, fetchFn }) => {
|
|
195
|
-
let timer;
|
|
196
|
-
return Promise.race([
|
|
197
|
-
fetchFn().then((result) => {
|
|
198
|
-
clearTimeout(timer);
|
|
199
|
-
const data = unwrapResult(result);
|
|
200
|
-
queryCache.set(aotKey, data);
|
|
201
|
-
}),
|
|
202
|
-
new Promise((r) => {
|
|
203
|
-
timer = setTimeout(r, ssrTimeout);
|
|
204
|
-
})
|
|
205
|
-
]);
|
|
206
|
-
}));
|
|
207
|
-
}
|
|
208
|
-
function unwrapResult(result) {
|
|
209
|
-
if (result && typeof result === "object" && "ok" in result && "data" in result) {
|
|
210
|
-
const r = result;
|
|
211
|
-
if (r.ok)
|
|
212
|
-
return r.data;
|
|
213
|
-
}
|
|
214
|
-
return result;
|
|
215
|
-
}
|
|
216
|
-
function isAotDebugEnabled() {
|
|
217
|
-
const env = process.env.VERTZ_DEBUG;
|
|
218
|
-
if (!env)
|
|
219
|
-
return false;
|
|
220
|
-
return env === "1" || env.split(",").includes("aot");
|
|
221
|
-
}
|
|
222
|
-
var domShimInstalled = false;
|
|
223
|
-
function ensureDomShim() {
|
|
224
|
-
if (domShimInstalled && typeof document !== "undefined")
|
|
225
|
-
return;
|
|
226
|
-
domShimInstalled = true;
|
|
227
|
-
installDomShim();
|
|
228
|
-
}
|
|
229
|
-
function collectCSSFromModule(module, fallbackMetrics) {
|
|
230
|
-
let themeCss = "";
|
|
231
|
-
let preloadTags = "";
|
|
232
|
-
if (module.theme) {
|
|
233
|
-
try {
|
|
234
|
-
const compiled = compileThemeCached(module.theme, fallbackMetrics);
|
|
235
|
-
themeCss = compiled.css;
|
|
236
|
-
preloadTags = compiled.preloadTags;
|
|
237
|
-
} catch (e) {
|
|
238
|
-
console.error("[vertz] Failed to compile theme export. Ensure your theme is created with defineTheme().", e);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
const alreadyIncluded = new Set;
|
|
242
|
-
if (themeCss)
|
|
243
|
-
alreadyIncluded.add(themeCss);
|
|
244
|
-
if (module.styles) {
|
|
245
|
-
for (const s of module.styles)
|
|
246
|
-
alreadyIncluded.add(s);
|
|
247
|
-
}
|
|
248
|
-
const componentCss = module.getInjectedCSS ? module.getInjectedCSS().filter((s) => !alreadyIncluded.has(s)) : [];
|
|
249
|
-
const themeTag = themeCss ? `<style data-vertz-css>${themeCss}</style>` : "";
|
|
250
|
-
const globalTag = module.styles && module.styles.length > 0 ? `<style data-vertz-css>${module.styles.join(`
|
|
251
|
-
`)}</style>` : "";
|
|
252
|
-
const componentTag = componentCss.length > 0 ? `<style data-vertz-css>${componentCss.join(`
|
|
253
|
-
`)}</style>` : "";
|
|
254
|
-
const cssString = [themeTag, globalTag, componentTag].filter(Boolean).join(`
|
|
255
|
-
`);
|
|
256
|
-
return { cssString, preloadTags };
|
|
257
|
-
}
|
|
258
|
-
|
|
259
58
|
// src/ssr-progressive-response.ts
|
|
260
59
|
function buildProgressiveResponse(options) {
|
|
261
60
|
const { headChunk, renderStream, tailChunk, ssrData, nonce, headers } = options;
|
|
@@ -468,4 +267,4 @@ async function handleHTMLRequest(module, template, url, ssrTimeout, nonce, fallb
|
|
|
468
267
|
}
|
|
469
268
|
}
|
|
470
269
|
|
|
471
|
-
export { loadAotManifest,
|
|
270
|
+
export { loadAotManifest, createSSRHandler };
|