lit-ui-router-ssr 0.6.0 → 0.8.0
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 +189 -24
- package/dist/client.d.ts +53 -18
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +30 -7
- package/dist/client.js.map +1 -1
- package/dist/development/client.js +30 -7
- package/dist/development/client.js.map +1 -1
- package/dist/development/index.js +1 -0
- package/dist/development/index.js.map +1 -1
- package/dist/development/light-element-renderer.js +1 -1
- package/dist/development/prerender.js +61 -11
- package/dist/development/prerender.js.map +1 -1
- package/dist/development/respond.js +26 -0
- package/dist/development/respond.js.map +1 -0
- package/dist/development/served-interior.js +9 -0
- package/dist/development/served-interior.js.map +1 -0
- package/dist/development/served-view.js +13 -1
- package/dist/development/served-view.js.map +1 -1
- package/dist/development/signature.js +3 -2
- package/dist/development/signature.js.map +1 -1
- package/dist/development/testing.js +35 -0
- package/dist/development/testing.js.map +1 -0
- package/dist/development/ui-view-renderer.js +45 -40
- package/dist/development/ui-view-renderer.js.map +1 -1
- package/dist/development/vite-preload.js +7 -0
- package/dist/development/vite-preload.js.map +1 -0
- package/dist/development/vite.js +27 -0
- package/dist/development/vite.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/light-element-renderer.js +1 -1
- package/dist/prerender.d.ts +112 -9
- package/dist/prerender.d.ts.map +1 -1
- package/dist/prerender.js +60 -10
- package/dist/prerender.js.map +1 -1
- package/dist/respond.d.ts +43 -0
- package/dist/respond.d.ts.map +1 -0
- package/dist/respond.js +26 -0
- package/dist/respond.js.map +1 -0
- package/dist/served-interior.d.ts +10 -0
- package/dist/served-interior.d.ts.map +1 -0
- package/dist/served-interior.js +9 -0
- package/dist/served-interior.js.map +1 -0
- package/dist/served-view.d.ts +13 -2
- package/dist/served-view.d.ts.map +1 -1
- package/dist/served-view.js +13 -1
- package/dist/served-view.js.map +1 -1
- package/dist/signature.d.ts +17 -5
- package/dist/signature.d.ts.map +1 -1
- package/dist/signature.js +3 -2
- package/dist/signature.js.map +1 -1
- package/dist/testing.d.ts +44 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +35 -0
- package/dist/testing.js.map +1 -0
- package/dist/ui-view-renderer.d.ts +12 -29
- package/dist/ui-view-renderer.d.ts.map +1 -1
- package/dist/ui-view-renderer.js +46 -37
- package/dist/ui-view-renderer.js.map +1 -1
- package/dist/vite-preload.d.ts +11 -0
- package/dist/vite-preload.d.ts.map +1 -0
- package/dist/vite-preload.js +7 -0
- package/dist/vite-preload.js.map +1 -0
- package/dist/vite.d.ts +86 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +27 -0
- package/dist/vite.js.map +1 -0
- package/package.json +46 -3
- package/src/client.ts +131 -28
- package/src/index.ts +15 -1
- package/src/light-element-renderer.ts +1 -1
- package/src/prerender.ts +225 -15
- package/src/respond.ts +105 -0
- package/src/served-interior.ts +26 -0
- package/src/served-view.ts +40 -4
- package/src/signature.ts +31 -14
- package/src/testing.ts +88 -0
- package/src/ui-view-renderer.ts +126 -112
- package/src/vite-preload.ts +18 -0
- package/src/vite.ts +158 -0
package/README.md
CHANGED
|
@@ -24,14 +24,17 @@ imports the pre-1.0 renderer or re-derives the incantation.
|
|
|
24
24
|
on the page carries `defer-hydration` and renders nothing until the client's walk reaches it.
|
|
25
25
|
- **The hydration signature.** A page rendered from a template opens on a JSON data block,
|
|
26
26
|
`<script type="application/json" data-lit-ui-router-ssr>`, naming this package's version, the
|
|
27
|
-
state the router stood on,
|
|
28
|
-
as a string is written as-is, without one.
|
|
27
|
+
state the router stood on, that state's url parameter values, and the resolved values
|
|
28
|
+
`dehydrate` or the `payload` hook draws. A page `renderShell` returns as a string is written as-is, without one.
|
|
29
29
|
- **The lit render inside the emit loop.** The loop itself — verdict to file name, redirect to
|
|
30
30
|
rules line, the `_redirects` file, delegating states skipped, tally, warnings for paths that
|
|
31
31
|
matched nothing — is
|
|
32
32
|
`prerender` from `ui-router-server/prerender`, which takes any render. This package's `prerender`
|
|
33
33
|
supplies the lit one and takes the same options, plus `router`, `renderShell`, `document`,
|
|
34
|
-
`root` and `
|
|
34
|
+
`root`, `elementRenderers`, `dehydrate`, `payload`, `responses` and `origin`. No SPA catch-all is ever written: one
|
|
35
|
+
turns every 404 into a 200.
|
|
36
|
+
- **Response states after settle.** `responder` runs the handler bound to a response state's name
|
|
37
|
+
with the resolves its transition landed with.
|
|
35
38
|
- **`<ui-view>` on both sides.** `UiViewRenderer` fills the element's light DOM on the server;
|
|
36
39
|
`lit-ui-router-ssr/client` adopts what it drew.
|
|
37
40
|
|
|
@@ -48,7 +51,11 @@ npm install lit-ui-router-ssr
|
|
|
48
51
|
`lit-ui-router`, `ui-router-server`, `@lit-labs/ssr`, `@lit-labs/ssr-client`, `lit`, and
|
|
49
52
|
`@uirouter/core` are peer dependencies. `@lit-labs/ssr` is the server half and `@lit-labs/ssr-client`
|
|
50
53
|
the client half, so a bundle takes one or the other, never both. `@lit-labs/ssr-client` is optional:
|
|
51
|
-
install it when you import `lit-ui-router-ssr/client`.
|
|
54
|
+
install it when you import `lit-ui-router-ssr/client`. `lit-ui-router-ssr/vite` wraps
|
|
55
|
+
`ui-router-server/vite`, so it takes `vite` through that package's optional peer.
|
|
56
|
+
|
|
57
|
+
The `lit-ui-router` peer is `^1.19.0`: the server renders a view through the helper `<ui-view>`
|
|
58
|
+
renders through, and the client hands a served class element to the view it wakes.
|
|
52
59
|
|
|
53
60
|
## Quick Start
|
|
54
61
|
|
|
@@ -82,6 +89,14 @@ on. `dryRun: true` plans all of it and writes nothing.
|
|
|
82
89
|
Files land through `node:fs`, imported lazily on first write; pass `write` to emit into memory or a
|
|
83
90
|
virtual fs instead.
|
|
84
91
|
|
|
92
|
+
## After `vite build`
|
|
93
|
+
|
|
94
|
+
`lit-ui-router-ssr/vite` prerenders the built app after `vite build`. Its `serverRouterPlugin` is
|
|
95
|
+
`ui-router-server/vite`'s, with the DOM shim and `lit-ui-router-ssr/register` loaded before the
|
|
96
|
+
prerender script, and its `definePrerender` calls this package's `prerender` with the options the
|
|
97
|
+
script returns; [Prerender with Vite](https://lit-ui-router.dev/guides/prerender-with-vite) shows
|
|
98
|
+
both files in full.
|
|
99
|
+
|
|
85
100
|
## Static hosts add a trailing slash
|
|
86
101
|
|
|
87
102
|
A shell page lands at `<subpath>/index.html`. Cloudflare Pages, Netlify, and S3-style hosts serve
|
|
@@ -125,6 +140,80 @@ A page fails to land in four ways, and each rejects rather than hangs:
|
|
|
125
140
|
`settle()` never calls `router.start()`, which runs once per router: it drives `urlService`
|
|
126
141
|
directly, so a page loop calls it once per path on the same router, started or not.
|
|
127
142
|
|
|
143
|
+
## Response states
|
|
144
|
+
|
|
145
|
+
A [response state](https://lit-ui-router.dev/packages/server#response-states) answers with a
|
|
146
|
+
`Response` built from its resolves instead of a page. `responder(router, responses)` settles
|
|
147
|
+
`router` on the verdict's subpath, query included, runs the handler bound to the landed state's
|
|
148
|
+
name with that transition's resolves (inherited ones included) and the request, and returns the
|
|
149
|
+
`Response` as built; a HEAD gets it without its body. A resolve that throws rejects before any
|
|
150
|
+
handler runs. It fits the fetch adapter's `serveResponse`, and `prerender` takes the same handlers
|
|
151
|
+
as `responses`, writing a 2xx body at the path its url spells or a 3xx as a rules line. See
|
|
152
|
+
[response states](https://lit-ui-router.dev/packages/ssr#response-states).
|
|
153
|
+
|
|
154
|
+
## Adopting the resolves on boot
|
|
155
|
+
|
|
156
|
+
The `dehydrate` option draws each rendered page's resolve payload: `prerender` calls `dehydrate`
|
|
157
|
+
from `ui-router-server/ssr` on the page's landed transition with the options given, so
|
|
158
|
+
`shouldDehydrate` and `transport` act exactly as they do there. Pass `{}` to draw every resolve:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { prerender } from 'lit-ui-router-ssr';
|
|
162
|
+
|
|
163
|
+
await prerender({
|
|
164
|
+
// mounts, router, paths, renderShell, …
|
|
165
|
+
dehydrate: {
|
|
166
|
+
shouldDehydrate: ({ token }) => token !== 'manifest',
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The payload's `resolves` go into the page's hydration signature, beside `version`, `state` and
|
|
172
|
+
`params`, so the one block is the payload. `bootstrap()` seeds the boot transition from it before
|
|
173
|
+
the router starts: each resolve the page was drawn with adopts its value in place of running its
|
|
174
|
+
function. Every other resolve runs as it would without one: a value `dehydrate` left out, a
|
|
175
|
+
`NOWAIT` resolve, every resolve of a boot that lands on another state or other parameters, and
|
|
176
|
+
every resolve of a page whose block carries no `resolves`. Without `dehydrate` or a `payload` hook
|
|
177
|
+
no page carries resolves. What `dehydrate` draws, and which values it leaves out, is in
|
|
178
|
+
[its documentation](https://lit-ui-router.dev/packages/server#handing-resolves-to-the-client).
|
|
179
|
+
|
|
180
|
+
A value plain JSON can't carry, such as a `Date`, travels through a transporter. Pass the same
|
|
181
|
+
`transport` in `dehydrate` and to `bootstrap()`: the signature keeps the payload's `transported`
|
|
182
|
+
marks, and `bootstrap()` hands `transport` to `seed`. See
|
|
183
|
+
[values beyond plain JSON](https://lit-ui-router.dev/packages/server#values-beyond-plain-json).
|
|
184
|
+
|
|
185
|
+
The `payload` option takes the drawing over by hand: a hook handed each page's landed transition
|
|
186
|
+
returns the payload to write, or `undefined` to write none. Pass one or the other; passing both
|
|
187
|
+
throws.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { dehydrate } from 'ui-router-server/ssr';
|
|
191
|
+
|
|
192
|
+
await prerender({
|
|
193
|
+
// mounts, router, paths, renderShell, …
|
|
194
|
+
payload: (transition, { path }) =>
|
|
195
|
+
path.startsWith('/drafts/')
|
|
196
|
+
? undefined
|
|
197
|
+
: dehydrate(transition, { transport }).payload,
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Each rendered page's entry in `result.pages` reports its payload as `payload`: `bytes`, what the
|
|
202
|
+
payload adds to the page's signature as written, and, when `dehydrate` drew it, `unserializable`,
|
|
203
|
+
the resolves left out to re-run on the client. A hook returns the payload alone, so behind one the
|
|
204
|
+
report carries `bytes` only. A page with no payload has no `payload` field.
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
const { pages } = await prerender({ /* … */ dehydrate: {} });
|
|
208
|
+
|
|
209
|
+
for (const { path, payload } of pages) {
|
|
210
|
+
if (!payload) continue;
|
|
211
|
+
console.log(`${path}: ${payload.bytes} bytes of resolves`);
|
|
212
|
+
for (const { state, token } of payload.unserializable ?? [])
|
|
213
|
+
console.warn(`${path}: ${state}.${token} re-runs on the client`);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
128
217
|
## The routed view, drawn on the server
|
|
129
218
|
|
|
130
219
|
`elementRenderers` defaults to `[UiViewRenderer, LightElementRenderer]` — not `@lit-labs/ssr`'s
|
|
@@ -138,6 +227,20 @@ hydrates against. An address no state routes gets empty markers. That pair stays
|
|
|
138
227
|
hydrating the view's surroundings reads it as the `uiViewSlot()` part and stops there; every marker
|
|
139
228
|
between it carries a prefix, so the same walk reads past the view's interior.
|
|
140
229
|
|
|
230
|
+
The template comes from `lit-ui-router`'s own render helper, the one `<ui-view>`'s `render()` calls,
|
|
231
|
+
so the served markup and the client's first render share one source. A routed `LitElement` class,
|
|
232
|
+
plain or `sticky`, prerenders too: `lit-ui-router` builds the element and assigns its props, and
|
|
233
|
+
`LitElementRenderer` writes it, shadow root included, into the slot `<ui-view>` places a class in.
|
|
234
|
+
At the wake the served view hands that element to `lit-ui-router`, which adopts it instead of
|
|
235
|
+
building its own, so the element the server wrote is the element the client keeps. A class that
|
|
236
|
+
renders into its own light DOM prerenders into it when it uses
|
|
237
|
+
[`LightDomHydrating`](#light-dom-elements), and hydrates those nodes in place. Without it, the class
|
|
238
|
+
is written as its bare element, with no shadow root to hide its render, and renders on the client. A
|
|
239
|
+
class must be on the `customElements` registry to prerender.
|
|
240
|
+
|
|
241
|
+
The served `<ui-view>` markup is internal to this package and `lit-ui-router` and changes with them.
|
|
242
|
+
Post-processing of prerendered HTML keys on the [hydration signature](#the-client-half) block.
|
|
243
|
+
|
|
141
244
|
The use site opts in with `uiViewSlot()`, which is what reaches the renderer's light-DOM render and
|
|
142
245
|
commits nothing on the client:
|
|
143
246
|
|
|
@@ -295,23 +398,41 @@ await bootstrap(router, root, page(router));
|
|
|
295
398
|
|
|
296
399
|
A `<ui-view>` another class already defined throws, naming both ways out.
|
|
297
400
|
|
|
298
|
-
The build-time entry that calls `prerender()`
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
401
|
+
The build-time entry that calls `prerender()` needs the DOM shim installed before anything defines
|
|
402
|
+
an element. The shim module awaits at its top level, so a static import beside it evaluates first:
|
|
403
|
+
lit's Node build installs a registry of its own, the elements are defined there, and the shim then
|
|
404
|
+
replaces `globalThis.customElements` with an empty one. Load the shim and `lit-ui-router-ssr/register`
|
|
405
|
+
before the entry starts. `serverRouterPlugin` from `lit-ui-router-ssr/vite` names both as preloads
|
|
406
|
+
of its prerender worker, and its `definePrerender` calls `prerender()` with the options the entry
|
|
407
|
+
returns:
|
|
303
408
|
|
|
304
409
|
```typescript
|
|
305
|
-
|
|
410
|
+
// vite.config.ts
|
|
411
|
+
import { createServerRouter } from 'ui-router-server';
|
|
412
|
+
import { serverRouterPlugin } from 'lit-ui-router-ssr/vite';
|
|
413
|
+
|
|
414
|
+
plugins: [
|
|
415
|
+
serverRouterPlugin(createServerRouter({ mounts }), {
|
|
416
|
+
prerender: './src/prerender.ts',
|
|
417
|
+
}),
|
|
418
|
+
];
|
|
419
|
+
|
|
420
|
+
// src/prerender.ts
|
|
421
|
+
import { definePrerender } from 'lit-ui-router-ssr/vite';
|
|
306
422
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
423
|
+
export default definePrerender((site) => ({
|
|
424
|
+
mounts,
|
|
425
|
+
router,
|
|
426
|
+
paths,
|
|
427
|
+
renderShell,
|
|
428
|
+
document,
|
|
429
|
+
}));
|
|
311
430
|
```
|
|
312
431
|
|
|
313
|
-
|
|
314
|
-
|
|
432
|
+
The entry then uses plain static imports; see
|
|
433
|
+
[Prerender with Vite](https://lit-ui-router.dev/guides/prerender-with-vite). An entry node runs
|
|
434
|
+
directly gets the same order from `node --import @lit-labs/ssr/lib/install-global-dom-shim.js`.
|
|
435
|
+
`UiViewRenderer` draws the served
|
|
315
436
|
class, and a `<ui-view>` nothing defined on the server renders as an inert element with an empty
|
|
316
437
|
part pair — no error, and every page's body missing. In development `prerender()` warns when the
|
|
317
438
|
registry holds no `<ui-view>`.
|
|
@@ -362,15 +483,19 @@ const { outcome } = await bootstrap(router, root, page(router));
|
|
|
362
483
|
- **The boot decides mismatches once.** A boot that lands where the document was drawn adopts every
|
|
363
484
|
view, and a view that still mismatches warns in development: the two halves render that template
|
|
364
485
|
differently. A boot that lands elsewhere — one static document served for a family of urls, or a
|
|
365
|
-
redirect — adopts the views that match and renders the rest cold without a warning each
|
|
366
|
-
|
|
367
|
-
cold.
|
|
368
|
-
|
|
486
|
+
redirect — adopts the views that match and renders the rest cold without a warning each. A view
|
|
487
|
+
whose state, or whose url parameters (its own and inherited), differ from the drawn ones renders
|
|
488
|
+
cold. Once the page is live, a boot into another state warns once in development, naming both
|
|
489
|
+
states and how many views rendered cold; a boot into other url parameters of the drawn state is
|
|
490
|
+
silent.
|
|
491
|
+
- **The boot transition is seeded.** The payload the signature carries is handed to `seed()` from
|
|
369
492
|
`ui-router-server/ssr/client` before the router starts, so the boot transition adopts the
|
|
370
|
-
resolved values
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
`
|
|
493
|
+
resolved values the prerender drew in place of running their resolve functions.
|
|
494
|
+
`options.payload` takes its place when given.
|
|
495
|
+
- **`hydrateRoot()` is the step underneath.** An app that owns its own boot calls
|
|
496
|
+
`seed(router, readResolvePayload(root))` and `router.start()`, awaits the first successful
|
|
497
|
+
transition, then `hydrateRoot(root, page(router))`, and renders `page(router)` itself when that
|
|
498
|
+
returns `false`.
|
|
374
499
|
- **The signature decides first.** `hydrateRoot()` reads the container's hydration signature before
|
|
375
500
|
it touches the document, and returns `false` over an emptied container when there is none — a
|
|
376
501
|
cold client render, a dev server, a page from an earlier `prerender()`, a string `renderShell` —
|
|
@@ -500,6 +625,46 @@ the grid entirely.
|
|
|
500
625
|
|
|
501
626
|
The [guide](https://lit-ui-router.dev/packages/ssr#how-this-compares) carries the longer discussion.
|
|
502
627
|
|
|
628
|
+
## Measuring the round trip
|
|
629
|
+
|
|
630
|
+
`lit-ui-router-ssr/testing` counts how many of the server's elements survive the boot. It imports
|
|
631
|
+
nothing — no lit, no router — and runs anywhere there is a DOM. `stampServed(root)` takes every
|
|
632
|
+
element under `root`, open shadow roots included, before the client boots; `countRetained(stamp)`
|
|
633
|
+
returns `{ served, retained, removed, added }` after it. A hydrated page keeps `removed` at 0. A view
|
|
634
|
+
the client rendered over counts its served elements as removed and its new ones as added; an element
|
|
635
|
+
a component draws in `firstUpdated`, or the shadow `<slot>` each `<ui-router>` renders, counts only
|
|
636
|
+
as added.
|
|
637
|
+
|
|
638
|
+
```ts
|
|
639
|
+
import { countRetained, stampServed } from 'lit-ui-router-ssr/testing';
|
|
640
|
+
|
|
641
|
+
const stamp = stampServed(container); // after the prerender is parsed in, before bootstrap()
|
|
642
|
+
await bootstrap(router, container, page(router));
|
|
643
|
+
expect(countRetained(stamp)).toMatchObject({ removed: 0 });
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
In a browser the stamp and the count must run in the page. Each helper is self-contained, so its
|
|
647
|
+
source text is valid page script. In Playwright, an init script stamps the body when parsing ends,
|
|
648
|
+
before module scripts run:
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
import { countRetained, stampServed } from 'lit-ui-router-ssr/testing';
|
|
652
|
+
|
|
653
|
+
await page.addInitScript(`
|
|
654
|
+
const stampServed = ${stampServed};
|
|
655
|
+
window.countRetained = ${countRetained};
|
|
656
|
+
document.addEventListener('readystatechange', () => {
|
|
657
|
+
if (document.readyState === 'interactive') window.servedStamp = stampServed(document.body);
|
|
658
|
+
});
|
|
659
|
+
`);
|
|
660
|
+
await page.goto('/sheet/7B/');
|
|
661
|
+
await page.waitForFunction(() => !document.querySelector('[defer-hydration]'));
|
|
662
|
+
|
|
663
|
+
expect(await page.evaluate('countRetained(servedStamp)')).toMatchObject({
|
|
664
|
+
removed: 0,
|
|
665
|
+
});
|
|
666
|
+
```
|
|
667
|
+
|
|
503
668
|
## Documentation
|
|
504
669
|
|
|
505
670
|
- [Guide](https://lit-ui-router.dev/packages/ssr)
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { renderLight } from "@lit-labs/ssr-client/directives/render-light.js";
|
|
2
2
|
import type { RenderOptions } from "lit";
|
|
3
3
|
import type { UIRouterLit } from "lit-ui-router/pure";
|
|
4
|
-
import type { ResolvePayload } from "ui-router-server/ssr/client";
|
|
4
|
+
import type { ResolvePayload, SeedOptions } from "ui-router-server/ssr/client";
|
|
5
5
|
import type { HydrationSignature } from "./signature.js";
|
|
6
6
|
export { adoptUiViewContext, type AdoptableView, type AdoptUiViewContext, type AdoptUiViewContextKey } from "./adopt-context.js";
|
|
7
7
|
export { isServedViewClass, type ServedUiView, type ServedUiViewConstructor, servedViewBrand, withServedRender } from "./served-view.js";
|
|
@@ -12,7 +12,8 @@ export type { HydrationSignature } from "./signature.js";
|
|
|
12
12
|
*
|
|
13
13
|
* - `adopted`: the element hydrated its served nodes, and they are the live ones.
|
|
14
14
|
* - `fell-back`: the served pair did not match the render the client booted
|
|
15
|
-
* into,
|
|
15
|
+
* into, was drawn for another state or other url parameters, or was lost;
|
|
16
|
+
* the view dropped the served interior and rendered cold.
|
|
16
17
|
* - `none`: nothing to adopt — an empty served pair, the address no state
|
|
17
18
|
* routed, or a view the document served no markers for.
|
|
18
19
|
*/
|
|
@@ -28,7 +29,7 @@ export declare const uiViewAdoptEventName: "ui-view:adopt";
|
|
|
28
29
|
export interface UiViewAdoptDetail {
|
|
29
30
|
/** What the wake came to. */
|
|
30
31
|
readonly outcome: AdoptOutcome;
|
|
31
|
-
/** What `hydrate()` threw, or why the
|
|
32
|
+
/** What `hydrate()` threw, or why the view did not adopt; present only on `fell-back`. */
|
|
32
33
|
readonly error?: unknown;
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
@@ -135,6 +136,30 @@ export declare const lightSlot: typeof renderLight;
|
|
|
135
136
|
*/
|
|
136
137
|
export declare function readHydrationSignature(container: ParentNode): HydrationSignature | null;
|
|
137
138
|
/**
|
|
139
|
+
* Reads the resolve payload `prerender()` wrote into the container's
|
|
140
|
+
* {@link readHydrationSignature | hydration signature}: the state and url
|
|
141
|
+
* parameters the document was drawn for, and the values its resolves settled
|
|
142
|
+
* on, keyed by state name, then by resolve token.
|
|
143
|
+
*
|
|
144
|
+
* {@link bootstrap} reads it on its own. A boot that calls {@link hydrateRoot}
|
|
145
|
+
* directly hands it to `seed` from `ui-router-server/ssr/client` before the
|
|
146
|
+
* router starts.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* import { readResolvePayload } from 'lit-ui-router-ssr/client';
|
|
151
|
+
* import { seed } from 'ui-router-server/ssr/client';
|
|
152
|
+
*
|
|
153
|
+
* seed(router, readResolvePayload(root));
|
|
154
|
+
* router.start();
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @param container - the element the server's markup was written into
|
|
158
|
+
* @returns the payload, or `undefined` when the container holds no signature,
|
|
159
|
+
* one from another release line of this package, or one without `resolves`
|
|
160
|
+
*/
|
|
161
|
+
export declare function readResolvePayload(container: ParentNode): ResolvePayload | undefined;
|
|
162
|
+
/**
|
|
138
163
|
* Adopts a server-rendered container, and the `<ui-view>`s that wake under it.
|
|
139
164
|
*
|
|
140
165
|
* The container's {@link readHydrationSignature | hydration signature} is read
|
|
@@ -181,11 +206,11 @@ export declare function readHydrationSignature(container: ParentNode): Hydration
|
|
|
181
206
|
* way. The caller renders into it.
|
|
182
207
|
*
|
|
183
208
|
* {@link bootstrap} runs the whole boot around this call. Called directly, the
|
|
184
|
-
* boot is the router first: `router
|
|
185
|
-
* transition, then this call.
|
|
186
|
-
* and each woken `<ui-view>`
|
|
187
|
-
*
|
|
188
|
-
* registered against. Nothing constrains when `lit-ui-router-ssr/register` is
|
|
209
|
+
* boot is the router first: `seed` the router with {@link readResolvePayload},
|
|
210
|
+
* `router.start()`, await its first successful transition, then this call.
|
|
211
|
+
* The walk commits `.uiRouter` onto `<ui-router>` and each woken `<ui-view>`
|
|
212
|
+
* re-seeks the router before its own first render, so the views find the
|
|
213
|
+
* settled router rather than the placeholder they registered against. Nothing constrains when `lit-ui-router-ssr/register` is
|
|
189
214
|
* imported.
|
|
190
215
|
*
|
|
191
216
|
* @example
|
|
@@ -237,12 +262,16 @@ export interface BootstrapResult {
|
|
|
237
262
|
*/
|
|
238
263
|
readonly error?: unknown;
|
|
239
264
|
}
|
|
240
|
-
/**
|
|
241
|
-
|
|
265
|
+
/**
|
|
266
|
+
* {@link bootstrap}'s options: {@link HydrateRootOptions}, plus the boot
|
|
267
|
+
* transition's seed and the `transport` handed to `seed` with it.
|
|
268
|
+
*/
|
|
269
|
+
export interface BootstrapOptions extends HydrateRootOptions, SeedOptions {
|
|
242
270
|
/**
|
|
243
271
|
* Resolved values the document was drawn with, handed to `seed` from
|
|
244
272
|
* `ui-router-server/ssr/client` before the router starts, so the boot
|
|
245
|
-
* transition adopts them in place of running their resolve functions.
|
|
273
|
+
* transition adopts them in place of running their resolve functions. It
|
|
274
|
+
* takes the place of the payload the container's signature carries.
|
|
246
275
|
*/
|
|
247
276
|
readonly payload?: ResolvePayload;
|
|
248
277
|
}
|
|
@@ -250,9 +279,13 @@ export interface BootstrapOptions extends HydrateRootOptions {
|
|
|
250
279
|
* Boots `router` into the page `container` holds, and resolves once that page
|
|
251
280
|
* is live.
|
|
252
281
|
*
|
|
253
|
-
* It owns the whole client boot.
|
|
254
|
-
*
|
|
255
|
-
*
|
|
282
|
+
* It owns the whole client boot. The boot transition is seeded first, with
|
|
283
|
+
* `options.payload` when given, and otherwise with the resolves the
|
|
284
|
+
* container's signature carries ({@link readResolvePayload}): each resolve the
|
|
285
|
+
* document was drawn with adopts its value in place of running its function,
|
|
286
|
+
* and every other resolve runs as it would without a payload. The
|
|
287
|
+
* container's {@link readHydrationSignature | signature} is read before
|
|
288
|
+
* anything else touches the document; a container {@link
|
|
256
289
|
* hydrateRoot} would not adopt — no signature, another release line, stripped
|
|
257
290
|
* markers — is emptied and `value` rendered into it at once, and the router
|
|
258
291
|
* then starts. Otherwise the router starts, the call waits for the boot
|
|
@@ -266,9 +299,11 @@ export interface BootstrapOptions extends HydrateRootOptions {
|
|
|
266
299
|
* since that is a template the two halves render differently.
|
|
267
300
|
* - The boot lands elsewhere — a static host serving one document for a
|
|
268
301
|
* family of urls, or a redirect: the views that match adopt, and the views
|
|
269
|
-
* that differ render cold without a warning of their own.
|
|
270
|
-
*
|
|
271
|
-
*
|
|
302
|
+
* that differ render cold without a warning of their own. A view whose
|
|
303
|
+
* state, or whose url parameters, its own and inherited, differ from the
|
|
304
|
+
* drawn ones renders cold. Once the page is live, a boot into another state
|
|
305
|
+
* warns once in development, naming both states and how many views rendered
|
|
306
|
+
* cold; a boot into other url parameters of the drawn state is silent.
|
|
272
307
|
* - The boot fails, or the url starts no transition: the container is emptied
|
|
273
308
|
* and `value` rendered cold. The root `hydrate()` throwing, as over a
|
|
274
309
|
* mutated document, does the same. The call resolves rather than rejects.
|
|
@@ -288,7 +323,7 @@ export interface BootstrapOptions extends HydrateRootOptions {
|
|
|
288
323
|
* @param router - the client router, its states registered and not yet started
|
|
289
324
|
* @param container - the element the server's markup was written into, or an empty one
|
|
290
325
|
* @param value - the same template the server rendered, with every `<ui-view>` hole empty
|
|
291
|
-
* @param options - lit render options, `onAdopt`, and the boot transition's `payload`
|
|
326
|
+
* @param options - lit render options, `onAdopt`, and the boot transition's `payload` and `transport`
|
|
292
327
|
* @returns what the boot came to, once every awake view has updated
|
|
293
328
|
* @throws what `router.start()` throws, as on a router already started
|
|
294
329
|
* @throws the `TypeError` `seed` throws on a payload with no `resolves`, before the router starts
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","mappings":"AAQA,SAAS,mBAAmB;AAK5B,cAAyB,qBAAqB;AAM9C,cAAc,mBAAmB;AAEjC,cAAc,
|
|
1
|
+
{"version":3,"file":"client.d.ts","mappings":"AAQA,SAAS,mBAAmB;AAK5B,cAAyB,qBAAqB;AAM9C,cAAc,mBAAmB;AAEjC,cAAc,gBAAgB,mBAAmB;AAYjD,cAAc,0BAA0B;AAExC,SACE,yBACK,oBACA,yBACA,6BACA;AAEP,SACE,wBACK,mBACA,yBACL,iBACA,wBACK;AAEP,SACE,wBACK,mCACA,+BACA,6BACA;AAEP,cAAc,0BAA0B;;;;;;;;;;;AAexC,YAAY,eAAe,YAAY,cAAc;;;;;AAMrD,OAAO,cAAM,sBAAuB;;;;AAKpC,iBAAiB,kBAAkB;;UAExB,SAAS;;UAET;AACX;;;;;AAMA,YAAY,mBAAmB,YAAY;;;;;;AAO3C,OAAO,cAAM,wBAAyB;;AAGtC,YAAY,qBAAqB,YAAY;;;;AAK7C,YAAY,iBACV,MAAM,SACN,SAAS,cAET;;;;;AAOF,iBAAiB,2BAA2B,cAAc;;;;;;CAMxD,UAAU;AACZ;eAEe;WACH,oBAAoB;;EAE5B,iBAAiB;;EAEjB,mBAAmB;CACrB;AACF;;;;;;;;;;;;;;;;;;;;;AAgEA,OAAO,cAAM,mBAAmB;;;;;;;;;;;;;;;AAgBhC,OAAO,cAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgZ/B,OAAO,iBAAS,uBACd,WAAW,aACV;;;;;;;;;;;;;;;;;;;;;;;;AA6BH,OAAO,iBAAS,mBACd,WAAW,aACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2JH,OAAO,iBAAS,YACd,WAAW,aAEX,gBACA,UAAS,qBACR;;AAsCH,YAAY,mBAAmB,YAAY;;;;;;;;;;;;;;;;AAiB3C,YAAY,qBAAqB,YAAY,cAAc;;AAG3D,iBAAiB,gBAAgB;;;;;;UAMtB,SAAS;;UAET,WAAW;;;;;UAKX;AACX;;;;;AAMA,iBAAiB,yBAAyB,oBAAoB,YAAY;;;;;;;UAO/D,UAAU;AACrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6LA,OAAO,iBAAe,UACpB,QAAQ,aACR,WAAW,aAEX,gBACA,UAAS,mBACR,QAAQ","names":[],"ignoreList":[],"sources":["../src/client.ts"]}
|
package/dist/client.js
CHANGED
|
@@ -11,7 +11,7 @@ import "#dev-gate";
|
|
|
11
11
|
import { adoptUiViewContext } from "./adopt-context.js";
|
|
12
12
|
import { isLightDomElement } from "./light-dom-brand.js";
|
|
13
13
|
import { servedMarkerPrefix } from "./served-markers.js";
|
|
14
|
-
import { packageVersion, routeOf, signatureSelector } from "./signature.js";
|
|
14
|
+
import { packageVersion, routeOf, signatureSelector, urlParamsOf } from "./signature.js";
|
|
15
15
|
export { adoptUiViewContext } from "./adopt-context.js";
|
|
16
16
|
export { isServedViewClass, servedViewBrand, withServedRender } from "./served-view.js";
|
|
17
17
|
export { LightDomHydrating } from "./light-dom.js";
|
|
@@ -125,6 +125,10 @@ const adopt = (view, policy) => {
|
|
|
125
125
|
return report(view, reporter, "fell-back", error);
|
|
126
126
|
}
|
|
127
127
|
if (isPart(open.nextSibling, "/lit-part")) return report(view, reporter, "none");
|
|
128
|
+
if (policy.drawn && !policy.drawn(view)) {
|
|
129
|
+
clearInterior(open);
|
|
130
|
+
return report(view, reporter, "fell-back", notDrawn);
|
|
131
|
+
}
|
|
128
132
|
try {
|
|
129
133
|
revealServedMarkers(view);
|
|
130
134
|
walkWith(policy, () => hydrate(view.render(), view, view.renderOptions));
|
|
@@ -165,6 +169,13 @@ export function readHydrationSignature(container) {
|
|
|
165
169
|
const block = signatureBlockIn(container);
|
|
166
170
|
return block ? parseSignature(block.text) : null;
|
|
167
171
|
}
|
|
172
|
+
export function readResolvePayload(container) {
|
|
173
|
+
return payloadIn(readHydrationSignature(container));
|
|
174
|
+
}
|
|
175
|
+
const payloadIn = (signature) => {
|
|
176
|
+
if (signature?.resolves === void 0 || releaseLine(signature.version) !== releaseLine(packageVersion)) return void 0;
|
|
177
|
+
return signature;
|
|
178
|
+
};
|
|
168
179
|
const signatureBlockIn = (container) => [...container.children].find((child) => child.matches(signatureSelector));
|
|
169
180
|
const precedesRender = (block) => {
|
|
170
181
|
let node = block.nextSibling;
|
|
@@ -237,6 +248,14 @@ const startBoot = (router) => new Promise((resolve) => {
|
|
|
237
248
|
}
|
|
238
249
|
if (!created) land({});
|
|
239
250
|
});
|
|
251
|
+
const notDrawn = "the view was drawn for another state or other url parameters";
|
|
252
|
+
const drawnView = (signature, router) => (view) => {
|
|
253
|
+
if (!(view instanceof UiView) || !view.viewContext) return true;
|
|
254
|
+
const state = view.viewContext;
|
|
255
|
+
if (!router.stateRegistry.get(String(signature.state))?.$$state?.().path.includes(state)) return false;
|
|
256
|
+
const drawnParams = signature.params ?? {};
|
|
257
|
+
return Object.entries(urlParamsOf(state, router.globals.params)).every(([id, value]) => JSON.stringify(value) === JSON.stringify(drawnParams[id]));
|
|
258
|
+
};
|
|
240
259
|
const signatureMatches = (signature, router) => JSON.stringify([signature.state, signature.params]) === JSON.stringify(routeOf(router.globals));
|
|
241
260
|
const settleViews = async (container) => {
|
|
242
261
|
const settled = new Set();
|
|
@@ -252,11 +271,11 @@ const renderCold = (container, value, renderOptions) => {
|
|
|
252
271
|
render(value, container, renderOptions);
|
|
253
272
|
};
|
|
254
273
|
export async function bootstrap(router, container, value, options = {}) {
|
|
255
|
-
const { onAdopt, payload, ...renderOptions } = options;
|
|
256
|
-
const
|
|
274
|
+
const { onAdopt, payload, transport, ...renderOptions } = options;
|
|
275
|
+
const served = readHydrationSignature(container);
|
|
276
|
+
const disarm = seed(router, payload ?? payloadIn(served), { transport });
|
|
257
277
|
const signature = readAdoptable(container);
|
|
258
278
|
if (!signature) {
|
|
259
|
-
const served = readHydrationSignature(container);
|
|
260
279
|
renderCold(container, value, renderOptions);
|
|
261
280
|
const landing = await startBoot(router);
|
|
262
281
|
disarm();
|
|
@@ -287,9 +306,13 @@ export async function bootstrap(router, container, value, options = {}) {
|
|
|
287
306
|
};
|
|
288
307
|
let release;
|
|
289
308
|
try {
|
|
290
|
-
release = adoptRoot(container, value, renderOptions, {
|
|
309
|
+
release = adoptRoot(container, value, renderOptions, drawn ? {
|
|
310
|
+
reporter,
|
|
311
|
+
quiet: false
|
|
312
|
+
} : {
|
|
291
313
|
reporter,
|
|
292
|
-
quiet:
|
|
314
|
+
quiet: true,
|
|
315
|
+
drawn: drawnView(signature, router)
|
|
293
316
|
});
|
|
294
317
|
} catch (error) {
|
|
295
318
|
render(value, container, renderOptions);
|
|
@@ -302,7 +325,7 @@ export async function bootstrap(router, container, value, options = {}) {
|
|
|
302
325
|
}
|
|
303
326
|
await settleViews(container);
|
|
304
327
|
release();
|
|
305
|
-
if (
|
|
328
|
+
if (fellBack > 0 && signature.state !== router.globals.current.name);
|
|
306
329
|
return {
|
|
307
330
|
outcome: "adopted",
|
|
308
331
|
signature: compared
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","mappings":"AAOA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAE5B,SAAS,YAAY,kBAAkB;AAEvC,SAAS,UAAU,cAAc;AAEjC,SAAS,iBAAiB;AAE1B,SAAS,yBAAyB;AAClC,SAAS,sBAAsB;AAC/B,SAAS,cAAc;AAEvB,SAAS,YAAY;AAErB,OAAwB;AACxB,SAAS,0BAA0B;AAEnC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,
|
|
1
|
+
{"version":3,"file":"client.js","mappings":"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","names":[],"ignoreList":[],"sources":["../src/client.ts"]}
|
|
@@ -11,7 +11,7 @@ import { devGate } from "#dev-gate";
|
|
|
11
11
|
import { adoptUiViewContext } from "./adopt-context.js";
|
|
12
12
|
import { isLightDomElement } from "./light-dom-brand.js";
|
|
13
13
|
import { servedMarkerPrefix } from "./served-markers.js";
|
|
14
|
-
import { packageVersion, routeOf, signatureSelector } from "./signature.js";
|
|
14
|
+
import { packageVersion, routeOf, signatureSelector, urlParamsOf } from "./signature.js";
|
|
15
15
|
export { adoptUiViewContext } from "./adopt-context.js";
|
|
16
16
|
export { isServedViewClass, servedViewBrand, withServedRender } from "./served-view.js";
|
|
17
17
|
export { LightDomHydrating } from "./light-dom.js";
|
|
@@ -134,6 +134,10 @@ const adopt = (view, policy) => {
|
|
|
134
134
|
return report(view, reporter, "fell-back", error);
|
|
135
135
|
}
|
|
136
136
|
if (isPart(open.nextSibling, "/lit-part")) return report(view, reporter, "none");
|
|
137
|
+
if (policy.drawn && !policy.drawn(view)) {
|
|
138
|
+
clearInterior(open);
|
|
139
|
+
return report(view, reporter, "fell-back", notDrawn);
|
|
140
|
+
}
|
|
137
141
|
try {
|
|
138
142
|
revealServedMarkers(view);
|
|
139
143
|
walkWith(policy, () => hydrate(view.render(), view, view.renderOptions));
|
|
@@ -175,6 +179,13 @@ export function readHydrationSignature(container) {
|
|
|
175
179
|
const block = signatureBlockIn(container);
|
|
176
180
|
return block ? parseSignature(block.text) : null;
|
|
177
181
|
}
|
|
182
|
+
export function readResolvePayload(container) {
|
|
183
|
+
return payloadIn(readHydrationSignature(container));
|
|
184
|
+
}
|
|
185
|
+
const payloadIn = (signature) => {
|
|
186
|
+
if (signature?.resolves === void 0 || releaseLine(signature.version) !== releaseLine(packageVersion)) return void 0;
|
|
187
|
+
return signature;
|
|
188
|
+
};
|
|
178
189
|
const signatureBlockIn = (container) => [...container.children].find((child) => child.matches(signatureSelector));
|
|
179
190
|
const precedesRender = (block) => {
|
|
180
191
|
let node = block.nextSibling;
|
|
@@ -256,6 +267,14 @@ const startBoot = (router) => new Promise((resolve) => {
|
|
|
256
267
|
}
|
|
257
268
|
if (!created) land({});
|
|
258
269
|
});
|
|
270
|
+
const notDrawn = "the view was drawn for another state or other url parameters";
|
|
271
|
+
const drawnView = (signature, router) => (view) => {
|
|
272
|
+
if (!(view instanceof UiView) || !view.viewContext) return true;
|
|
273
|
+
const state = view.viewContext;
|
|
274
|
+
if (!router.stateRegistry.get(String(signature.state))?.$$state?.().path.includes(state)) return false;
|
|
275
|
+
const drawnParams = signature.params ?? {};
|
|
276
|
+
return Object.entries(urlParamsOf(state, router.globals.params)).every(([id, value]) => JSON.stringify(value) === JSON.stringify(drawnParams[id]));
|
|
277
|
+
};
|
|
259
278
|
const signatureMatches = (signature, router) => JSON.stringify([signature.state, signature.params]) === JSON.stringify(routeOf(router.globals));
|
|
260
279
|
const warnBootElsewhere = (signature, router, fellBack) => {
|
|
261
280
|
if (!devGate()) return;
|
|
@@ -275,11 +294,11 @@ const renderCold = (container, value, renderOptions) => {
|
|
|
275
294
|
render(value, container, renderOptions);
|
|
276
295
|
};
|
|
277
296
|
export async function bootstrap(router, container, value, options = {}) {
|
|
278
|
-
const { onAdopt, payload, ...renderOptions } = options;
|
|
279
|
-
const
|
|
297
|
+
const { onAdopt, payload, transport, ...renderOptions } = options;
|
|
298
|
+
const served = readHydrationSignature(container);
|
|
299
|
+
const disarm = seed(router, payload ?? payloadIn(served), { transport });
|
|
280
300
|
const signature = readAdoptable(container);
|
|
281
301
|
if (!signature) {
|
|
282
|
-
const served = readHydrationSignature(container);
|
|
283
302
|
renderCold(container, value, renderOptions);
|
|
284
303
|
const landing = await startBoot(router);
|
|
285
304
|
disarm();
|
|
@@ -310,9 +329,13 @@ export async function bootstrap(router, container, value, options = {}) {
|
|
|
310
329
|
};
|
|
311
330
|
let release;
|
|
312
331
|
try {
|
|
313
|
-
release = adoptRoot(container, value, renderOptions, {
|
|
332
|
+
release = adoptRoot(container, value, renderOptions, drawn ? {
|
|
333
|
+
reporter,
|
|
334
|
+
quiet: false
|
|
335
|
+
} : {
|
|
314
336
|
reporter,
|
|
315
|
-
quiet:
|
|
337
|
+
quiet: true,
|
|
338
|
+
drawn: drawnView(signature, router)
|
|
316
339
|
});
|
|
317
340
|
} catch (error) {
|
|
318
341
|
render(value, container, renderOptions);
|
|
@@ -325,7 +348,7 @@ export async function bootstrap(router, container, value, options = {}) {
|
|
|
325
348
|
}
|
|
326
349
|
await settleViews(container);
|
|
327
350
|
release();
|
|
328
|
-
if (
|
|
351
|
+
if (fellBack > 0 && signature.state !== router.globals.current.name) warnBootElsewhere(signature, router, fellBack);
|
|
329
352
|
return {
|
|
330
353
|
outcome: "adopted",
|
|
331
354
|
signature: compared
|