@jasonshimmy/custom-elements-runtime 3.0.0 → 3.1.1
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 +118 -81
- package/dist/custom-elements-runtime.cjs.js +3 -3
- package/dist/custom-elements-runtime.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.es.js +77 -72
- package/dist/custom-elements-runtime.es.js.map +1 -1
- package/dist/custom-elements-runtime.jit-css.cjs.js +1 -1
- package/dist/custom-elements-runtime.jit-css.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.jit-css.es.js +25 -26
- package/dist/custom-elements-runtime.jit-css.es.js.map +1 -1
- package/dist/custom-elements-runtime.router.cjs.js +8 -8
- package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.router.es.js +134 -134
- package/dist/custom-elements-runtime.router.es.js.map +1 -1
- package/dist/custom-elements-runtime.ssr-middleware.cjs.js +2 -0
- package/dist/custom-elements-runtime.ssr-middleware.cjs.js.map +1 -0
- package/dist/custom-elements-runtime.ssr-middleware.es.js +69 -0
- package/dist/custom-elements-runtime.ssr-middleware.es.js.map +1 -0
- package/dist/custom-elements-runtime.ssr.cjs.js +3 -1
- package/dist/custom-elements-runtime.ssr.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.ssr.es.js +158 -39
- package/dist/custom-elements-runtime.ssr.es.js.map +1 -1
- package/dist/custom-elements-runtime.vite-plugin.cjs.js +1 -1
- package/dist/custom-elements-runtime.vite-plugin.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.vite-plugin.es.js +81 -49
- package/dist/custom-elements-runtime.vite-plugin.es.js.map +1 -1
- package/dist/hooks-x8M4knLc.cjs +6 -0
- package/dist/hooks-x8M4knLc.cjs.map +1 -0
- package/dist/hooks-xWZhQHco.js +1465 -0
- package/dist/hooks-xWZhQHco.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/namespace-helpers-D4wC2-qA.js +61 -0
- package/dist/namespace-helpers-D4wC2-qA.js.map +1 -0
- package/dist/namespace-helpers-ckeEOxpR.cjs +2 -0
- package/dist/namespace-helpers-ckeEOxpR.cjs.map +1 -0
- package/dist/router/matcher.d.ts +14 -0
- package/dist/runtime/component/factory.d.ts +16 -2
- package/dist/runtime/hydration.d.ts +33 -0
- package/dist/runtime/render.d.ts +0 -11
- package/dist/runtime/scheduler.d.ts +12 -0
- package/dist/runtime/ssr-context.d.ts +47 -0
- package/dist/runtime/ssr-utils.d.ts +9 -0
- package/dist/runtime/types.d.ts +18 -0
- package/dist/runtime/vdom-ssr-dsd.d.ts +82 -0
- package/dist/runtime/vdom-ssr.d.ts +2 -6
- package/dist/ssr-middleware.d.ts +125 -0
- package/dist/ssr.d.ts +95 -33
- package/dist/template-compiler-CTUhEHr8.cjs +22 -0
- package/dist/template-compiler-CTUhEHr8.cjs.map +1 -0
- package/dist/template-compiler-ZhSg1yPh.js +3724 -0
- package/dist/template-compiler-ZhSg1yPh.js.map +1 -0
- package/dist/vite-plugin.d.ts +94 -4
- package/package.json +6 -1
- package/dist/helpers-CweFZFWU.js +0 -987
- package/dist/helpers-CweFZFWU.js.map +0 -1
- package/dist/helpers-DeWjSmOl.cjs +0 -5
- package/dist/helpers-DeWjSmOl.cjs.map +0 -1
- package/dist/hooks-BrrLKSub.cjs +0 -3
- package/dist/hooks-BrrLKSub.cjs.map +0 -1
- package/dist/hooks-DyShDHKo.js +0 -403
- package/dist/hooks-DyShDHKo.js.map +0 -1
- package/dist/namespace-helpers-CnpZ5__p.js +0 -45
- package/dist/namespace-helpers-CnpZ5__p.js.map +0 -1
- package/dist/namespace-helpers-CyIDtI97.cjs +0 -2
- package/dist/namespace-helpers-CyIDtI97.cjs.map +0 -1
- package/dist/template-compiler-B5uN1EQw.js +0 -3731
- package/dist/template-compiler-B5uN1EQw.js.map +0 -1
- package/dist/template-compiler-Cx623BSB.cjs +0 -23
- package/dist/template-compiler-Cx623BSB.cjs.map +0 -1
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
* (time-sliced, non-blocking rendering for low-priority work).
|
|
8
8
|
*/
|
|
9
9
|
export type UpdatePriority = 'immediate' | 'normal' | 'idle';
|
|
10
|
+
/**
|
|
11
|
+
* Environment detection utilities
|
|
12
|
+
*/
|
|
13
|
+
export interface TestEnvironment {
|
|
14
|
+
isTest: boolean;
|
|
15
|
+
isVitest: boolean;
|
|
16
|
+
isCypress: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Detect test environment with improved reliability
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectTestEnvironment(): TestEnvironment;
|
|
10
22
|
declare class UpdateScheduler {
|
|
11
23
|
private pendingUpdates;
|
|
12
24
|
private isFlushScheduled;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR execution context for running component render functions server-side.
|
|
3
|
+
*
|
|
4
|
+
* When generating Declarative Shadow DOM (DSD) output, the SSR renderer must
|
|
5
|
+
* call each custom element's render function to obtain its shadow DOM VNode
|
|
6
|
+
* tree and capture any useStyle() / useGlobalStyle() output. This module
|
|
7
|
+
* provides the minimal execution environment that makes that safe.
|
|
8
|
+
*
|
|
9
|
+
* Guarantees:
|
|
10
|
+
* - useStyle() callbacks are executed and their output is captured.
|
|
11
|
+
* - useGlobalStyle() callbacks are captured (not injected into document).
|
|
12
|
+
* - Lifecycle hooks (useOnConnected, watch, …) register harmlessly to arrays
|
|
13
|
+
* that are never invoked.
|
|
14
|
+
* - The reactive system is never permanently mutated — component registration
|
|
15
|
+
* is cleaned up by the render wrapper in factory.ts after each call.
|
|
16
|
+
*/
|
|
17
|
+
import type { ComponentConfig, VNode } from './types';
|
|
18
|
+
/** Start collecting useGlobalStyle() output from the current render pass. */
|
|
19
|
+
export declare function beginSSRGlobalStyleCollection(): void;
|
|
20
|
+
/** Stop collecting and return everything gathered so far. */
|
|
21
|
+
export declare function endSSRGlobalStyleCollection(): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Called by useGlobalStyle() when an SSR collection pass is active.
|
|
24
|
+
* Returns true if the CSS was captured (caller should skip DOM injection).
|
|
25
|
+
*/
|
|
26
|
+
export declare function captureGlobalStyleForSSR(css: string): boolean;
|
|
27
|
+
export interface SSRRenderResult {
|
|
28
|
+
/** VNode tree from the component's render function (shadow DOM content). */
|
|
29
|
+
shadowVNode: VNode | VNode[] | null;
|
|
30
|
+
/** CSS string captured from useStyle() calls during this render. */
|
|
31
|
+
useStyleCSS: string;
|
|
32
|
+
/** Present when the component's render function returned a Promise. */
|
|
33
|
+
asyncPromise?: Promise<VNode | VNode[]>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Run a component's render function in a minimal SSR context to capture its
|
|
37
|
+
* shadow DOM VNode tree and any useStyle() output.
|
|
38
|
+
*
|
|
39
|
+
* The component's render wrapper in factory.ts handles:
|
|
40
|
+
* - setCurrentComponentContext / clearCurrentComponentContext
|
|
41
|
+
* - _hookCallbacks reset
|
|
42
|
+
* - _computedStyle reset
|
|
43
|
+
* - reactiveSystem registration / cleanup
|
|
44
|
+
*
|
|
45
|
+
* We only need to build a context object that satisfies the hooks' expectations.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runComponentSSRRender(config: ComponentConfig<object, object, object, object>, attrs: Record<string, string | number | boolean | null | undefined>, tag?: string): SSRRenderResult;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type RenderOptions = {
|
|
2
|
+
/** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */
|
|
3
|
+
injectSvgNamespace?: boolean;
|
|
4
|
+
/** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */
|
|
5
|
+
injectKnownNamespaces?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const VOID_ELEMENTS: Set<string>;
|
|
8
|
+
export declare function buildAttrs(attrs: Record<string, unknown>, tag: string, opts: RenderOptions): string;
|
|
9
|
+
export declare function buildRawAttrs(attrs: Record<string, unknown>): string;
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -86,11 +86,29 @@ export type ComponentContext<S extends object, C extends object, P extends objec
|
|
|
86
86
|
} & {
|
|
87
87
|
[key: string]: unknown;
|
|
88
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* Controls when (and whether) a server-rendered custom element is hydrated
|
|
91
|
+
* on the client after the JavaScript bundle loads.
|
|
92
|
+
*
|
|
93
|
+
* | Value | Behaviour |
|
|
94
|
+
* |-----------|-----------|
|
|
95
|
+
* | `'load'` | Hydrate immediately when the element connects (default). |
|
|
96
|
+
* | `'idle'` | Defer until `requestIdleCallback` fires. |
|
|
97
|
+
* | `'visible'` | Defer until the element enters the viewport (`IntersectionObserver`). |
|
|
98
|
+
* | `'none'` | Never hydrate — element stays as static server-rendered HTML. |
|
|
99
|
+
*/
|
|
100
|
+
export type HydrateStrategy = 'load' | 'idle' | 'visible' | 'none';
|
|
89
101
|
export type ComponentConfig<S extends object, C extends object = object, P extends object = object, T extends object = object> = {
|
|
90
102
|
props?: Record<string, {
|
|
91
103
|
type: StringConstructor | NumberConstructor | BooleanConstructor | FunctionConstructor;
|
|
92
104
|
default?: string | number | boolean;
|
|
93
105
|
}>;
|
|
106
|
+
/**
|
|
107
|
+
* Partial-hydration strategy for this component when SSR DSD output is used.
|
|
108
|
+
* Emitted as `data-cer-hydrate` on the host element in DSD HTML.
|
|
109
|
+
* @default 'load'
|
|
110
|
+
*/
|
|
111
|
+
hydrate?: HydrateStrategy;
|
|
94
112
|
render: (context: ComponentContext<S, C, P, T>) => VNode | VNode[] | Promise<VNode | VNode[]>;
|
|
95
113
|
onConnected?: (context: ComponentContext<S, C, P, T>) => void;
|
|
96
114
|
onDisconnected?: (context: ComponentContext<S, C, P, T>) => void;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative Shadow DOM (DSD) SSR renderer.
|
|
3
|
+
*
|
|
4
|
+
* When `dsd: true` is passed to the render options, registered custom elements
|
|
5
|
+
* are serialised as:
|
|
6
|
+
*
|
|
7
|
+
* ```html
|
|
8
|
+
* <my-element attr="val">
|
|
9
|
+
* <template shadowrootmode="open">
|
|
10
|
+
* <style>
|
|
11
|
+
* /* baseReset + useStyle() output + JIT utility CSS *\/
|
|
12
|
+
* </style>
|
|
13
|
+
* <!-- shadow DOM from component render function -->
|
|
14
|
+
* </template>
|
|
15
|
+
* <!-- light DOM / slotted children from vnode.children -->
|
|
16
|
+
* </my-element>
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* The browser parses the `<template shadowrootmode="open">` block and attaches
|
|
20
|
+
* a real shadow root before any JavaScript executes. All CSS layers are present
|
|
21
|
+
* at first paint — eliminating both FOUC and layout shift.
|
|
22
|
+
*
|
|
23
|
+
* Non-custom-element VNodes are rendered identically to renderToString() but
|
|
24
|
+
* with DSD recursion active for any custom elements nested inside them.
|
|
25
|
+
*/
|
|
26
|
+
import type { VNode } from './types';
|
|
27
|
+
import { type RenderOptions } from './ssr-utils';
|
|
28
|
+
export type DSDRenderOptions = RenderOptions & {
|
|
29
|
+
/**
|
|
30
|
+
* Emit Declarative Shadow DOM output for registered custom elements.
|
|
31
|
+
* Shadow content is serialised inside `<template shadowrootmode="open">`,
|
|
32
|
+
* with a complete CSS layer stack (`baseReset` + `useStyle` + JIT CSS)
|
|
33
|
+
* injected as a `<style>` block so styles are available at first paint.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
dsd?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Append the DSD polyfill `<script>` for browsers without native support
|
|
39
|
+
* (Firefox < 123). Only meaningful when `dsd` is true.
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
dsdPolyfill?: boolean;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* @internal
|
|
46
|
+
* Minified DSD polyfill for browsers without native Declarative Shadow DOM.
|
|
47
|
+
* Processes all `<template shadowrootmode>` elements synchronously.
|
|
48
|
+
*/
|
|
49
|
+
export declare const DSD_POLYFILL_SCRIPT: string;
|
|
50
|
+
/**
|
|
51
|
+
* Build the combined `<style>` block for a shadow root.
|
|
52
|
+
*
|
|
53
|
+
* Layer order (matches the runtime adoptedStyleSheets order):
|
|
54
|
+
* 1. baseReset — global reset + CSS custom properties
|
|
55
|
+
* 2. useStyle() output — component-defined rules (:host, ::slotted, etc.)
|
|
56
|
+
* 3. JIT CSS — utility classes extracted from the shadow HTML
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildShadowStyleBlock(useStyleCSS: string, shadowHTML: string): string;
|
|
59
|
+
export interface AsyncStreamEntry {
|
|
60
|
+
id: string;
|
|
61
|
+
tag: string;
|
|
62
|
+
attrsString: string;
|
|
63
|
+
hydrateAttr: string;
|
|
64
|
+
useStyleCSS: string;
|
|
65
|
+
lightDOM: string;
|
|
66
|
+
opts: DSDRenderOptions;
|
|
67
|
+
promise: Promise<VNode | VNode[]>;
|
|
68
|
+
}
|
|
69
|
+
/** @internal Called by renderToStream() before the sync render pass. */
|
|
70
|
+
export declare function beginStreamingCollection(collector: AsyncStreamEntry[]): void;
|
|
71
|
+
/** @internal Called by renderToStream() after the sync render pass. */
|
|
72
|
+
export declare function endStreamingCollection(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Render a VNode tree to an HTML string with Declarative Shadow DOM output
|
|
75
|
+
* for all registered custom elements encountered in the tree.
|
|
76
|
+
*/
|
|
77
|
+
export declare function renderToDSD(vnode: VNode, opts: DSDRenderOptions): string;
|
|
78
|
+
/**
|
|
79
|
+
* Render a VNode tree to a DSD HTML string and optionally append the
|
|
80
|
+
* DSD polyfill script for older browsers.
|
|
81
|
+
*/
|
|
82
|
+
export declare function renderToStringDSD(vnode: VNode, opts?: DSDRenderOptions): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode } from './types';
|
|
2
|
+
import { type RenderOptions } from './ssr-utils';
|
|
2
3
|
/**
|
|
3
4
|
* Render a VNode to a string (SSR).
|
|
4
5
|
* Kept intentionally minimal: only serializes attributes under `props.attrs`
|
|
@@ -6,10 +7,5 @@ import type { VNode } from './types';
|
|
|
6
7
|
* @param vnode The virtual node to render.
|
|
7
8
|
* @returns The rendered HTML string.
|
|
8
9
|
*/
|
|
9
|
-
export type RenderOptions
|
|
10
|
-
/** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */
|
|
11
|
-
injectSvgNamespace?: boolean;
|
|
12
|
-
/** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */
|
|
13
|
-
injectKnownNamespaces?: boolean;
|
|
14
|
-
};
|
|
10
|
+
export type { RenderOptions } from './ssr-utils';
|
|
15
11
|
export declare function renderToString(vnode: VNode, opts?: RenderOptions): string;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR middleware helpers for Express, Fastify, Hono, and other Node.js HTTP frameworks.
|
|
3
|
+
*
|
|
4
|
+
* Provides two handler factories that wrap the SSR rendering pipeline and
|
|
5
|
+
* emit a complete HTML document response. Both accept a static VNode **or**
|
|
6
|
+
* a per-request factory function so route-specific data can be threaded into
|
|
7
|
+
* the render tree.
|
|
8
|
+
*
|
|
9
|
+
* @example Express — static VNode
|
|
10
|
+
* ```ts
|
|
11
|
+
* import express from 'express';
|
|
12
|
+
* import { createSSRHandler } from '@jasonshimmy/custom-elements-runtime/ssr-middleware';
|
|
13
|
+
* import { html } from '@jasonshimmy/custom-elements-runtime';
|
|
14
|
+
*
|
|
15
|
+
* const app = express();
|
|
16
|
+
* app.get('/', createSSRHandler(html`<my-app />`, {
|
|
17
|
+
* render: { dsd: true, jit: { extendedColors: true } },
|
|
18
|
+
* }));
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @example Express — per-request factory
|
|
22
|
+
* ```ts
|
|
23
|
+
* app.get('*', createSSRHandler(
|
|
24
|
+
* (req) => html`<my-app url="${req.url}" />`,
|
|
25
|
+
* { render: { dsd: true }, head: '<link rel="stylesheet" href="/app.css">' },
|
|
26
|
+
* ));
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example Streaming variant
|
|
30
|
+
* ```ts
|
|
31
|
+
* app.get('*', createStreamingSSRHandler(
|
|
32
|
+
* (req) => html`<my-app url="${req.url}" />`,
|
|
33
|
+
* ));
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import type { VNode } from './runtime/types';
|
|
37
|
+
import type { RenderOptions } from './runtime/vdom-ssr';
|
|
38
|
+
import type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';
|
|
39
|
+
import type { JITCSSOptions } from './runtime/style';
|
|
40
|
+
/**
|
|
41
|
+
* Minimal request interface compatible with Express, Fastify, Hono, and the
|
|
42
|
+
* raw Node.js `IncomingMessage`. Extend or replace with your framework's
|
|
43
|
+
* request type via the generic parameter on `createSSRHandler`.
|
|
44
|
+
*/
|
|
45
|
+
export interface MinimalRequest {
|
|
46
|
+
url?: string;
|
|
47
|
+
method?: string;
|
|
48
|
+
headers?: Record<string, string | string[] | undefined>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Minimal response interface compatible with Express, Fastify, Hono, and the
|
|
52
|
+
* raw Node.js `ServerResponse`. `write` is optional — handlers fall back to
|
|
53
|
+
* buffering when it is absent.
|
|
54
|
+
*/
|
|
55
|
+
export interface MinimalResponse {
|
|
56
|
+
setHeader(name: string, value: string): void;
|
|
57
|
+
write?(chunk: string): boolean | void;
|
|
58
|
+
end(data?: string): void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Options for {@link createSSRHandler} and {@link createStreamingSSRHandler}.
|
|
62
|
+
*/
|
|
63
|
+
export interface SSRMiddlewareOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Render options forwarded to `renderToStringWithJITCSS`.
|
|
66
|
+
* Defaults to `{ dsd: true }` so DSD output is on by default.
|
|
67
|
+
*/
|
|
68
|
+
render?: RenderOptions & DSDRenderOptions & {
|
|
69
|
+
jit?: JITCSSOptions;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Additional HTML inserted at the end of the `<head>` tag.
|
|
73
|
+
* Use this to inject `<link>`, `<script>`, `<meta>`, or `<title>` tags.
|
|
74
|
+
*/
|
|
75
|
+
head?: string;
|
|
76
|
+
/**
|
|
77
|
+
* When `true` (default), the response is wrapped in a complete
|
|
78
|
+
* `<!DOCTYPE html>` document shell. Set to `false` if you want to
|
|
79
|
+
* assemble the document yourself and only need the rendered fragment.
|
|
80
|
+
*/
|
|
81
|
+
document?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a request handler that SSR-renders a VNode tree and sends the full
|
|
85
|
+
* HTML document as the response.
|
|
86
|
+
*
|
|
87
|
+
* Compatible with Express, Fastify, Hono, and any framework that uses an
|
|
88
|
+
* `(req, res)` handler signature. The generic `Req` parameter lets you use
|
|
89
|
+
* your framework's typed request object.
|
|
90
|
+
*
|
|
91
|
+
* @param vnodeOrFactory - A static {@link VNode} **or** a (possibly async)
|
|
92
|
+
* factory function that receives the request and returns the VNode to render.
|
|
93
|
+
* @param options - Render and document-shell options.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* app.get('*', createSSRHandler(
|
|
98
|
+
* (req) => html`<my-app url="${req.url}" />`,
|
|
99
|
+
* { render: { dsd: true, jit: { extendedColors: true } } },
|
|
100
|
+
* ));
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function createSSRHandler<Req extends MinimalRequest = MinimalRequest>(vnodeOrFactory: VNode | ((req: Req) => VNode | Promise<VNode>), options?: SSRMiddlewareOptions): (req: Req, res: MinimalResponse) => Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Create a request handler that SSR-renders a VNode tree and streams the HTML
|
|
106
|
+
* response using chunked transfer encoding.
|
|
107
|
+
*
|
|
108
|
+
* Each chunk produced by the underlying {@link renderToStream} call is written
|
|
109
|
+
* to the response as it becomes available, minimising Time-to-First-Byte.
|
|
110
|
+
* The document shell preamble (`<!DOCTYPE html>…<body>`) is sent in the first
|
|
111
|
+
* write so the browser can begin parsing immediately.
|
|
112
|
+
*
|
|
113
|
+
* @param vnodeOrFactory - A static {@link VNode} **or** a (possibly async)
|
|
114
|
+
* factory function that receives the request and returns the VNode to render.
|
|
115
|
+
* @param options - Render and document-shell options.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* app.get('*', createStreamingSSRHandler(
|
|
120
|
+
* (req) => html`<my-app url="${req.url}" />`,
|
|
121
|
+
* { render: { dsd: true } },
|
|
122
|
+
* ));
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export declare function createStreamingSSRHandler<Req extends MinimalRequest = MinimalRequest>(vnodeOrFactory: VNode | ((req: Req) => VNode | Promise<VNode>), options?: SSRMiddlewareOptions): (req: Req, res: MinimalResponse) => Promise<void>;
|
package/dist/ssr.d.ts
CHANGED
|
@@ -1,70 +1,132 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SSR
|
|
3
|
-
* without pulling them into the main client runtime bundle.
|
|
2
|
+
* SSR entry point — import from `@jasonshimmy/custom-elements-runtime/ssr`.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
4
|
+
* Provides four rendering modes:
|
|
6
5
|
*
|
|
7
|
-
*
|
|
6
|
+
* 1. **renderToString** — baseline HTML serialisation (no shadow DOM content).
|
|
7
|
+
* Backwards-compatible with the original API.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* onto `<svg>` elements that do not already provide an explicit `xmlns`.
|
|
12
|
-
* This matches the client runtime behavior (createElementNS) and avoids
|
|
13
|
-
* hydration/namespace mismatches. Set to `false` to opt out and keep SSR
|
|
14
|
-
* output minimal.
|
|
9
|
+
* 2. **renderToStringWithJITCSS** — HTML + pre-generated JIT CSS injected into
|
|
10
|
+
* `<head>` to prevent FOUC. Supports `dsd: true` for DSD output.
|
|
15
11
|
*
|
|
16
|
-
*
|
|
12
|
+
* 3. **renderToStringWithJITCSSDSD** — convenience alias for DSD mode.
|
|
13
|
+
* Full Declarative Shadow DOM output with per-shadow-root CSS layer stack
|
|
14
|
+
* (baseReset + useStyle() + JIT CSS). Enables true hydration, zero FOUC.
|
|
17
15
|
*
|
|
18
|
-
*
|
|
19
|
-
* import { renderToString } from '@jasonshimmy/custom-elements-runtime/ssr';
|
|
20
|
-
* const html = renderToString(vnodeTree);
|
|
16
|
+
* 4. **renderToStream** — ReadableStream variant for streaming SSR.
|
|
21
17
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Entity map utilities are also exported for full HTML5 named-entity support.
|
|
19
|
+
*
|
|
20
|
+
* @example DSD usage (recommended)
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';
|
|
23
|
+
*
|
|
24
|
+
* const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {
|
|
25
|
+
* jit: { extendedColors: true },
|
|
26
|
+
* });
|
|
27
|
+
* res.send(`<!DOCTYPE html><html><head>${head}</head><body>${htmlWithStyles}</body></html>`);
|
|
28
|
+
* ```
|
|
24
29
|
*/
|
|
25
30
|
export { renderToString } from './runtime/vdom-ssr';
|
|
26
31
|
export type { VNode } from './runtime/types';
|
|
27
32
|
export type { RenderOptions } from './runtime/vdom-ssr';
|
|
28
33
|
export { registerEntityMap, loadEntityMap, clearRegisteredEntityMap, } from './runtime/helpers';
|
|
34
|
+
export { renderToStringDSD, DSD_POLYFILL_SCRIPT, } from './runtime/vdom-ssr-dsd';
|
|
35
|
+
export type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';
|
|
29
36
|
import { type JITCSSOptions } from './runtime/style';
|
|
30
37
|
import type { VNode } from './runtime/types';
|
|
31
38
|
import type { RenderOptions } from './runtime/vdom-ssr';
|
|
39
|
+
import type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';
|
|
32
40
|
/**
|
|
33
|
-
* Result of `renderToStringWithJITCSS()`.
|
|
41
|
+
* Result of `renderToStringWithJITCSS()` and `renderToStringWithJITCSSDSD()`.
|
|
34
42
|
*/
|
|
35
43
|
export interface SSRJITResult {
|
|
36
|
-
/** The rendered HTML string. */
|
|
44
|
+
/** The rendered HTML string (styles not yet injected). */
|
|
37
45
|
html: string;
|
|
38
46
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
47
|
+
* Global JIT CSS extracted from the rendered HTML.
|
|
48
|
+
* For DSD renders, each shadow root embeds its own scoped styles; this field
|
|
49
|
+
* holds any residual light-DOM utility CSS.
|
|
42
50
|
*/
|
|
43
51
|
css: string;
|
|
44
52
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
53
|
+
* CSS captured from `useGlobalStyle()` calls during this render pass
|
|
54
|
+
* (e.g. `@font-face`, `:root` custom properties).
|
|
55
|
+
* Inject in a `<style id="cer-ssr-global">` in `<head>`.
|
|
56
|
+
*/
|
|
57
|
+
globalStyles: string;
|
|
58
|
+
/**
|
|
59
|
+
* Convenience: `html` with both `<style>` tags injected before `</head>`.
|
|
60
|
+
* If no `</head>` is found, the styles are prepended.
|
|
47
61
|
*/
|
|
48
62
|
htmlWithStyles: string;
|
|
49
63
|
}
|
|
50
64
|
/**
|
|
51
|
-
* Server-side render a VNode tree and simultaneously pre-generate JIT CSS
|
|
52
|
-
* all utility classes present in the rendered output.
|
|
65
|
+
* Server-side render a VNode tree and simultaneously pre-generate JIT CSS.
|
|
53
66
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* eliminating Flash of Unstyled Content (FOUC).
|
|
67
|
+
* Pass `dsd: true` to enable Declarative Shadow DOM output with full per-shadow-
|
|
68
|
+
* root CSS layer extraction (recommended for new apps).
|
|
57
69
|
*
|
|
58
|
-
* @example
|
|
70
|
+
* @example Standard (no DSD)
|
|
59
71
|
* ```ts
|
|
60
|
-
*
|
|
72
|
+
* const { htmlWithStyles } = renderToStringWithJITCSS(appVNode);
|
|
73
|
+
* ```
|
|
61
74
|
*
|
|
62
|
-
*
|
|
75
|
+
* @example With DSD
|
|
76
|
+
* ```ts
|
|
77
|
+
* const { htmlWithStyles } = renderToStringWithJITCSS(appVNode, {
|
|
78
|
+
* dsd: true,
|
|
63
79
|
* jit: { extendedColors: true },
|
|
64
80
|
* });
|
|
65
|
-
* res.send(`<!DOCTYPE html><html><head>${headTags}</head><body>${htmlWithStyles}</body></html>`);
|
|
66
81
|
* ```
|
|
67
82
|
*/
|
|
68
|
-
export declare function renderToStringWithJITCSS(vnode: VNode, options?: RenderOptions & {
|
|
83
|
+
export declare function renderToStringWithJITCSS(vnode: VNode, options?: RenderOptions & DSDRenderOptions & {
|
|
69
84
|
jit?: JITCSSOptions;
|
|
70
85
|
}): SSRJITResult;
|
|
86
|
+
/**
|
|
87
|
+
* Convenience alias: `renderToStringWithJITCSS(vnode, { dsd: true, ...options })`.
|
|
88
|
+
*
|
|
89
|
+
* Renders with Declarative Shadow DOM output, full per-shadow-root CSS layer
|
|
90
|
+
* extraction, and the DSD browser polyfill. This is the recommended function
|
|
91
|
+
* for all new server-rendered applications.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';
|
|
96
|
+
*
|
|
97
|
+
* const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {
|
|
98
|
+
* jit: { extendedColors: true },
|
|
99
|
+
* });
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function renderToStringWithJITCSSDSD(vnode: VNode, options?: Omit<RenderOptions & DSDRenderOptions & {
|
|
103
|
+
jit?: JITCSSOptions;
|
|
104
|
+
}, 'dsd'>): SSRJITResult;
|
|
105
|
+
/**
|
|
106
|
+
* Render a VNode tree to a `ReadableStream<string>`.
|
|
107
|
+
*
|
|
108
|
+
* The current implementation flushes the complete rendered output as a single
|
|
109
|
+
* chunk, providing the streaming API surface for framework adapters. True
|
|
110
|
+
* incremental streaming (flush shell immediately, resolve async components
|
|
111
|
+
* progressively) is planned for a future release.
|
|
112
|
+
*
|
|
113
|
+
* @example Node.js
|
|
114
|
+
* ```ts
|
|
115
|
+
* import { renderToStream } from '@jasonshimmy/custom-elements-runtime/ssr';
|
|
116
|
+
*
|
|
117
|
+
* app.get('/', (req, res) => {
|
|
118
|
+
* const stream = renderToStream(appVNode, { dsd: true });
|
|
119
|
+
* const reader = stream.getReader();
|
|
120
|
+
* const pump = () =>
|
|
121
|
+
* reader.read().then(({ value, done }) => {
|
|
122
|
+
* if (done) { res.end(); return; }
|
|
123
|
+
* res.write(value);
|
|
124
|
+
* pump();
|
|
125
|
+
* });
|
|
126
|
+
* pump();
|
|
127
|
+
* });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare function renderToStream(vnode: VNode, options?: RenderOptions & DSDRenderOptions & {
|
|
131
|
+
jit?: JITCSSOptions;
|
|
132
|
+
}): ReadableStream<string>;
|