@llui/vike 0.0.3 → 0.0.4
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 +48 -25
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/on-render-client.d.ts +24 -0
- package/dist/on-render-client.d.ts.map +1 -1
- package/dist/on-render-client.js +41 -3
- package/dist/on-render-client.js.map +1 -1
- package/dist/on-render-html.d.ts +41 -3
- package/dist/on-render-html.d.ts.map +1 -1
- package/dist/on-render-html.js +47 -9
- package/dist/on-render-html.js.map +1 -1
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @llui/vike
|
|
2
2
|
|
|
3
|
-
[Vike](https://vike.dev) SSR adapter for [LLui](https://github.com/fponticelli/llui). Server-side rendering with client hydration.
|
|
3
|
+
[Vike](https://vike.dev) SSR/SSG adapter for [LLui](https://github.com/fponticelli/llui). Server-side rendering with client hydration, or static site generation via prerendering.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
pnpm add @llui/vike
|
|
@@ -8,49 +8,72 @@ pnpm add @llui/vike
|
|
|
8
8
|
|
|
9
9
|
## Setup
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Use sub-path imports to keep jsdom out of the client bundle:
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
14
|
// pages/+onRenderHtml.ts
|
|
15
|
-
export { onRenderHtml } from '@llui/vike'
|
|
15
|
+
export { onRenderHtml } from '@llui/vike/server'
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
19
|
// pages/+onRenderClient.ts
|
|
20
|
-
export { onRenderClient } from '@llui/vike'
|
|
20
|
+
export { onRenderClient } from '@llui/vike/client'
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### Server (`onRenderHtml`)
|
|
23
|
+
### Custom Document Template
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
Use `createOnRenderHtml` to control the full HTML document — add stylesheets, meta tags, favicons:
|
|
28
26
|
|
|
29
27
|
```ts
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
// pages/+onRenderHtml.ts
|
|
29
|
+
import { createOnRenderHtml } from '@llui/vike/server'
|
|
30
|
+
|
|
31
|
+
export const onRenderHtml = createOnRenderHtml({
|
|
32
|
+
document: ({ html, state, pageContext }) => `<!DOCTYPE html>
|
|
33
|
+
<html lang="en">
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="utf-8" />
|
|
36
|
+
<link rel="stylesheet" href="/styles.css" />
|
|
37
|
+
</head>
|
|
38
|
+
<body>
|
|
39
|
+
<div id="app">${html}</div>
|
|
40
|
+
<script>window.__LLUI_STATE__ = ${state}</script>
|
|
41
|
+
</body>
|
|
42
|
+
</html>`,
|
|
43
|
+
})
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
###
|
|
46
|
+
### Custom Container
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
Use `createOnRenderClient` to configure the mount container or add lifecycle hooks:
|
|
39
49
|
|
|
40
50
|
```ts
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
// pages/+onRenderClient.ts
|
|
52
|
+
import { createOnRenderClient } from '@llui/vike/client'
|
|
53
|
+
|
|
54
|
+
export const onRenderClient = createOnRenderClient({
|
|
55
|
+
container: '#root',
|
|
56
|
+
onMount: () => console.log('Page ready'),
|
|
57
|
+
})
|
|
45
58
|
```
|
|
46
59
|
|
|
47
|
-
##
|
|
60
|
+
## How It Works
|
|
61
|
+
|
|
62
|
+
### Server (`onRenderHtml`)
|
|
63
|
+
|
|
64
|
+
Renders the component to HTML via `renderToString()`. Automatically initializes jsdom for server-side DOM (lazy-loaded to avoid client bundle pollution). Serializes state into a `<script>` tag for hydration.
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
66
|
+
### Client (`onRenderClient`)
|
|
67
|
+
|
|
68
|
+
Hydrates the server-rendered HTML on the client. Attaches event listeners and reactive bindings to existing DOM nodes without re-rendering. Falls back to fresh `mountApp()` for client-side navigations.
|
|
69
|
+
|
|
70
|
+
## API
|
|
53
71
|
|
|
54
|
-
|
|
72
|
+
| Export | Sub-path | Description |
|
|
73
|
+
| ---------------------- | ------------------- | ------------------------------------------- |
|
|
74
|
+
| `onRenderHtml` | `@llui/vike/server` | Default server hook — minimal HTML template |
|
|
75
|
+
| `createOnRenderHtml` | `@llui/vike/server` | Factory for custom document templates |
|
|
76
|
+
| `onRenderClient` | `@llui/vike/client` | Default client hook — hydrate or mount |
|
|
77
|
+
| `createOnRenderClient` | `@llui/vike/client` | Factory for custom container/lifecycle |
|
|
55
78
|
|
|
56
|
-
|
|
79
|
+
The barrel export (`@llui/vike`) re-exports everything, but prefer sub-path imports to avoid bundling jsdom into the client.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export { onRenderHtml } from './on-render-html';
|
|
2
|
-
export {
|
|
1
|
+
export { onRenderHtml, createOnRenderHtml } from './on-render-html';
|
|
2
|
+
export type { PageContext, DocumentContext, RenderHtmlResult } from './on-render-html';
|
|
3
|
+
export { onRenderClient, createOnRenderClient } from './on-render-client';
|
|
4
|
+
export type { ClientPageContext, RenderClientOptions } from './on-render-client';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACnE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAEtF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzE,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { onRenderHtml } from './on-render-html';
|
|
2
|
-
export { onRenderClient } from './on-render-client';
|
|
1
|
+
export { onRenderHtml, createOnRenderHtml } from './on-render-html';
|
|
2
|
+
export { onRenderClient, createOnRenderClient } from './on-render-client';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAGnE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -9,5 +9,29 @@ export interface ClientPageContext {
|
|
|
9
9
|
data?: unknown;
|
|
10
10
|
isHydration?: boolean;
|
|
11
11
|
}
|
|
12
|
+
export interface RenderClientOptions {
|
|
13
|
+
/** CSS selector for the mount container. Default: '#app' */
|
|
14
|
+
container?: string;
|
|
15
|
+
/** Called after mount or hydration completes */
|
|
16
|
+
onMount?: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Default onRenderClient hook.
|
|
20
|
+
* Hydrates if isHydration is true, otherwise mounts fresh.
|
|
21
|
+
*/
|
|
12
22
|
export declare function onRenderClient(pageContext: ClientPageContext): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Factory to create a customized onRenderClient hook.
|
|
25
|
+
*
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // pages/+onRenderClient.ts
|
|
28
|
+
* import { createOnRenderClient } from '@llui/vike/client'
|
|
29
|
+
*
|
|
30
|
+
* export const onRenderClient = createOnRenderClient({
|
|
31
|
+
* container: '#root',
|
|
32
|
+
* onMount: () => console.log('Page ready'),
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createOnRenderClient(options: RenderClientOptions): (pageContext: ClientPageContext) => Promise<void>;
|
|
13
37
|
//# sourceMappingURL=on-render-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-render-client.d.ts","sourceRoot":"","sources":["../src/on-render-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"on-render-client.d.ts","sourceRoot":"","sources":["../src/on-render-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,WAAW,CAAA;AAExD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,cAAc,CAAC,EAAE,OAAO,CAAA;KACzB;CACF;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACtD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAKD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,mBAAmB,GAC3B,CAAC,WAAW,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAEnD"}
|
package/dist/on-render-client.js
CHANGED
|
@@ -1,13 +1,51 @@
|
|
|
1
1
|
import { hydrateApp, mountApp } from '@llui/dom';
|
|
2
|
+
// Track the current app handle so we can dispose it on client navigation
|
|
3
|
+
let currentHandle = null;
|
|
4
|
+
/**
|
|
5
|
+
* Default onRenderClient hook.
|
|
6
|
+
* Hydrates if isHydration is true, otherwise mounts fresh.
|
|
7
|
+
*/
|
|
2
8
|
export async function onRenderClient(pageContext) {
|
|
9
|
+
renderClient(pageContext, {});
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Factory to create a customized onRenderClient hook.
|
|
13
|
+
*
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // pages/+onRenderClient.ts
|
|
16
|
+
* import { createOnRenderClient } from '@llui/vike/client'
|
|
17
|
+
*
|
|
18
|
+
* export const onRenderClient = createOnRenderClient({
|
|
19
|
+
* container: '#root',
|
|
20
|
+
* onMount: () => console.log('Page ready'),
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function createOnRenderClient(options) {
|
|
25
|
+
return (pageContext) => renderClient(pageContext, options);
|
|
26
|
+
}
|
|
27
|
+
async function renderClient(pageContext, options) {
|
|
3
28
|
const { Page } = pageContext;
|
|
4
|
-
const
|
|
29
|
+
const selector = options.container ?? '#app';
|
|
30
|
+
const container = document.querySelector(selector);
|
|
31
|
+
if (!container) {
|
|
32
|
+
throw new Error(`@llui/vike: container "${selector}" not found in DOM`);
|
|
33
|
+
}
|
|
34
|
+
// Dispose previous page's component on client navigation
|
|
35
|
+
if (currentHandle) {
|
|
36
|
+
currentHandle.dispose();
|
|
37
|
+
currentHandle = null;
|
|
38
|
+
}
|
|
39
|
+
const el = container;
|
|
5
40
|
if (pageContext.isHydration) {
|
|
6
41
|
const serverState = window.__LLUI_STATE__;
|
|
7
|
-
hydrateApp(
|
|
42
|
+
currentHandle = hydrateApp(el, Page, serverState);
|
|
8
43
|
}
|
|
9
44
|
else {
|
|
10
|
-
|
|
45
|
+
// Clear old DOM before mounting new page
|
|
46
|
+
el.textContent = '';
|
|
47
|
+
currentHandle = mountApp(el, Page, pageContext.data);
|
|
11
48
|
}
|
|
49
|
+
options.onMount?.();
|
|
12
50
|
}
|
|
13
51
|
//# sourceMappingURL=on-render-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-render-client.js","sourceRoot":"","sources":["../src/on-render-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"on-render-client.js","sourceRoot":"","sources":["../src/on-render-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAsBhD,yEAAyE;AACzE,IAAI,aAAa,GAAqB,IAAI,CAAA;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAA8B;IACjE,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;AAC/B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA4B;IAE5B,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;AAC5D,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,WAA8B,EAC9B,OAA4B;IAE5B,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAA;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAA;IAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;IAElD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,oBAAoB,CAAC,CAAA;IACzE,CAAC;IAED,yDAAyD;IACzD,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,CAAC,OAAO,EAAE,CAAA;QACvB,aAAa,GAAG,IAAI,CAAA;IACtB,CAAC;IAED,MAAM,EAAE,GAAG,SAAwB,CAAA;IAEnC,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAA;QACzC,aAAa,GAAG,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;IACnD,CAAC;SAAM,CAAC;QACN,yCAAyC;QACzC,EAAE,CAAC,WAAW,GAAG,EAAE,CAAA;QACnB,aAAa,GAAG,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;IACtD,CAAC;IAED,OAAO,CAAC,OAAO,EAAE,EAAE,CAAA;AACrB,CAAC"}
|
package/dist/on-render-html.d.ts
CHANGED
|
@@ -2,11 +2,49 @@ import type { ComponentDef } from '@llui/dom';
|
|
|
2
2
|
export interface PageContext {
|
|
3
3
|
Page: ComponentDef<unknown, unknown, unknown, unknown>;
|
|
4
4
|
data?: unknown;
|
|
5
|
+
head?: string;
|
|
5
6
|
}
|
|
6
|
-
export
|
|
7
|
-
|
|
7
|
+
export interface DocumentContext {
|
|
8
|
+
/** Rendered component HTML */
|
|
9
|
+
html: string;
|
|
10
|
+
/** JSON-serialized initial state */
|
|
11
|
+
state: string;
|
|
12
|
+
/** Head content from pageContext.head (e.g. from +Head.ts) */
|
|
13
|
+
head: string;
|
|
14
|
+
/** Full page context for custom logic */
|
|
15
|
+
pageContext: PageContext;
|
|
16
|
+
}
|
|
17
|
+
export interface RenderHtmlResult {
|
|
18
|
+
documentHtml: string | {
|
|
19
|
+
_escaped: string;
|
|
20
|
+
};
|
|
8
21
|
pageContext: {
|
|
9
22
|
lluiState: unknown;
|
|
10
23
|
};
|
|
11
|
-
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default onRenderHtml hook for simple cases.
|
|
27
|
+
* Uses a minimal HTML document template.
|
|
28
|
+
*/
|
|
29
|
+
export declare function onRenderHtml(pageContext: PageContext): Promise<RenderHtmlResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Factory to create a customized onRenderHtml hook.
|
|
32
|
+
*
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // pages/+onRenderHtml.ts
|
|
35
|
+
* import { createOnRenderHtml } from '@llui/vike'
|
|
36
|
+
*
|
|
37
|
+
* export const onRenderHtml = createOnRenderHtml({
|
|
38
|
+
* document: ({ html, state, head }) => `<!DOCTYPE html>
|
|
39
|
+
* <html>
|
|
40
|
+
* <head>${head}<link rel="stylesheet" href="/styles.css" /></head>
|
|
41
|
+
* <body><div id="app">${html}</div>
|
|
42
|
+
* <script>window.__LLUI_STATE__ = ${state}</script></body>
|
|
43
|
+
* </html>`,
|
|
44
|
+
* })
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function createOnRenderHtml(options: {
|
|
48
|
+
document: (ctx: DocumentContext) => string;
|
|
49
|
+
}): (pageContext: PageContext) => Promise<RenderHtmlResult>;
|
|
12
50
|
//# sourceMappingURL=on-render-html.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-render-html.d.ts","sourceRoot":"","sources":["../src/on-render-html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACtD,IAAI,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"on-render-html.d.ts","sourceRoot":"","sources":["../src/on-render-html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACtD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,yCAAyC;IACzC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,WAAW,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAA;CACpC;AAcD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEtF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAA;CAC3C,GAAG,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAE1D"}
|
package/dist/on-render-html.js
CHANGED
|
@@ -1,18 +1,56 @@
|
|
|
1
1
|
import { renderToString } from '@llui/dom';
|
|
2
|
+
const DEFAULT_DOCUMENT = ({ html, state, head }) => `<!DOCTYPE html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
${head}
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app">${html}</div>
|
|
10
|
+
<script>window.__LLUI_STATE__ = ${state}</script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>`;
|
|
13
|
+
/**
|
|
14
|
+
* Default onRenderHtml hook for simple cases.
|
|
15
|
+
* Uses a minimal HTML document template.
|
|
16
|
+
*/
|
|
2
17
|
export async function onRenderHtml(pageContext) {
|
|
18
|
+
return renderPage(pageContext, DEFAULT_DOCUMENT);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Factory to create a customized onRenderHtml hook.
|
|
22
|
+
*
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // pages/+onRenderHtml.ts
|
|
25
|
+
* import { createOnRenderHtml } from '@llui/vike'
|
|
26
|
+
*
|
|
27
|
+
* export const onRenderHtml = createOnRenderHtml({
|
|
28
|
+
* document: ({ html, state, head }) => `<!DOCTYPE html>
|
|
29
|
+
* <html>
|
|
30
|
+
* <head>${head}<link rel="stylesheet" href="/styles.css" /></head>
|
|
31
|
+
* <body><div id="app">${html}</div>
|
|
32
|
+
* <script>window.__LLUI_STATE__ = ${state}</script></body>
|
|
33
|
+
* </html>`,
|
|
34
|
+
* })
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function createOnRenderHtml(options) {
|
|
38
|
+
return (pageContext) => renderPage(pageContext, options.document);
|
|
39
|
+
}
|
|
40
|
+
async function renderPage(pageContext, document) {
|
|
41
|
+
// Lazy-import to keep jsdom out of the client bundle's dependency graph
|
|
42
|
+
const { initSsrDom } = await import('@llui/dom/ssr');
|
|
43
|
+
await initSsrDom();
|
|
3
44
|
const { Page, data } = pageContext;
|
|
4
45
|
const [initialState] = Page.init(data);
|
|
5
46
|
const html = renderToString(Page, initialState);
|
|
6
|
-
const
|
|
47
|
+
const state = JSON.stringify(initialState);
|
|
48
|
+
const head = pageContext.head ?? '';
|
|
49
|
+
const documentHtml = document({ html, state, head, pageContext });
|
|
7
50
|
return {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<body>
|
|
12
|
-
<div id="app">${html}</div>
|
|
13
|
-
<script>window.__LLUI_STATE__ = ${serializedState}</script>
|
|
14
|
-
</body>
|
|
15
|
-
</html>`,
|
|
51
|
+
// Use Vike's dangerouslySkipEscape format — the document template
|
|
52
|
+
// is trusted (authored by the developer, not user input)
|
|
53
|
+
documentHtml: { _escaped: documentHtml },
|
|
16
54
|
pageContext: { lluiState: initialState },
|
|
17
55
|
};
|
|
18
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-render-html.js","sourceRoot":"","sources":["../src/on-render-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"on-render-html.js","sourceRoot":"","sources":["../src/on-render-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAyB1C,MAAM,gBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAmB,EAAU,EAAE,CAAC;;;;MAIvE,IAAI;;;oBAGU,IAAI;sCACc,KAAK;;QAEnC,CAAA;AAER;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAwB;IACzD,OAAO,UAAU,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;AAClD,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAElC;IACC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;AACnE,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,WAAwB,EACxB,QAA0C;IAE1C,wEAAwE;IACxE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;IACpD,MAAM,UAAU,EAAE,CAAA;IAElB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,WAAW,CAAA;IAClC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;IAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,IAAI,EAAE,CAAA;IAEnC,MAAM,YAAY,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAEjE,OAAO;QACL,kEAAkE;QAClE,yDAAyD;QACzD,YAAY,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE;QACxC,WAAW,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE;KACzC,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llui/vike",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"import": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./client": {
|
|
12
|
+
"types": "./dist/on-render-client.d.ts",
|
|
13
|
+
"import": "./dist/on-render-client.js"
|
|
14
|
+
},
|
|
15
|
+
"./server": {
|
|
16
|
+
"types": "./dist/on-render-html.d.ts",
|
|
17
|
+
"import": "./dist/on-render-html.js"
|
|
10
18
|
}
|
|
11
19
|
},
|
|
12
20
|
"files": [
|
|
@@ -20,7 +28,8 @@
|
|
|
20
28
|
"test:coverage": "vitest run --coverage"
|
|
21
29
|
},
|
|
22
30
|
"dependencies": {
|
|
23
|
-
"@llui/dom": "workspace:*"
|
|
31
|
+
"@llui/dom": "workspace:*",
|
|
32
|
+
"jsdom": "^26.1.0"
|
|
24
33
|
},
|
|
25
34
|
"description": "LLui Vike SSR adapter — onRenderHtml, onRenderClient hooks",
|
|
26
35
|
"keywords": [
|