@takazudo/zfb-runtime 0.1.0-next.55 → 0.1.0-next.57
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 +103 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -95,6 +95,109 @@ import type { ContentSnapshot } from "@takazudo/zfb-runtime/snapshot";
|
|
|
95
95
|
import { ClientRouter } from "@takazudo/zfb-runtime/client-router";
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
#### Enabling SPA soft-navigation (the runtime ships automatically)
|
|
99
|
+
|
|
100
|
+
Mounting `<ClientRouter />` in your layout `<head>` is normally **all you need**.
|
|
101
|
+
The build detects the usage and automatically ships the client-router runtime to
|
|
102
|
+
the browser — you do **not** have to add a manual `"use client"` bootstrap
|
|
103
|
+
island.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { ClientRouter } from "@takazudo/zfb-runtime";
|
|
107
|
+
|
|
108
|
+
export default function Layout({ children }) {
|
|
109
|
+
return (
|
|
110
|
+
<html>
|
|
111
|
+
<head>
|
|
112
|
+
<ClientRouter fallback="animate" />
|
|
113
|
+
</head>
|
|
114
|
+
<body>{children}</body>
|
|
115
|
+
</html>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**How the runtime reaches the browser.** `<ClientRouter />` itself only renders
|
|
121
|
+
SSR `<head>` tags. The click/form interception is registered by an `init()` call
|
|
122
|
+
that runs as a side effect when `@takazudo/zfb-runtime/client-router` is imported
|
|
123
|
+
in the browser, guarded so it never runs during SSR:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
// inside @takazudo/zfb-runtime — client-router.ts
|
|
127
|
+
if (typeof document !== "undefined") {
|
|
128
|
+
init();
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
To get that side-effect import into the client bundle, zfb's island scanner
|
|
133
|
+
detects when a page transitively reaches `<ClientRouter />` and injects
|
|
134
|
+
`import "@takazudo/zfb-runtime/client-router"` into the islands asset
|
|
135
|
+
(`assets/islands.js`) — **even when the project has no `"use client"` islands of
|
|
136
|
+
its own**. The asset is then loaded on the page, the import runs, and `init()`
|
|
137
|
+
fires on the client with zero boilerplate. (Auto-include added in zfb #289 /
|
|
138
|
+
#307; the runtime is byte-for-byte absent from projects that never reach
|
|
139
|
+
`<ClientRouter />`.)
|
|
140
|
+
|
|
141
|
+
**What counts as a `ClientRouter` usage the scanner detects:**
|
|
142
|
+
|
|
143
|
+
- a named `ClientRouter` import from the `@takazudo/zfb-runtime` barrel —
|
|
144
|
+
`import { ClientRouter } from "@takazudo/zfb-runtime"` (renamed forms like
|
|
145
|
+
`{ ClientRouter as CR }` match on the imported name), or
|
|
146
|
+
- any import or re-export of the `@takazudo/zfb-runtime/client-router` subpath
|
|
147
|
+
(e.g. when you only need `navigate` / `prefetch`), or
|
|
148
|
+
- a named `ClientRouter` imported from a *local* barrel that re-exports the
|
|
149
|
+
runtime via `export * from "@takazudo/zfb-runtime"`.
|
|
150
|
+
|
|
151
|
+
The importing module has to be reachable from a page in `pages/` — that is the
|
|
152
|
+
import graph the scanner walks.
|
|
153
|
+
|
|
154
|
+
**When you need a manual side-effect import.** Detection keys off the *import* of
|
|
155
|
+
`ClientRouter`, and a couple of shapes are deliberately **not** treated as a
|
|
156
|
+
trigger — firing on them would ship the runtime to projects that only reference
|
|
157
|
+
`ClientRouter` as a type or never call it:
|
|
158
|
+
|
|
159
|
+
- a namespace import — `import * as rt from "@takazudo/zfb-runtime"` used as
|
|
160
|
+
`rt.ClientRouter`, and
|
|
161
|
+
- a type-only import — `import type { ClientRouter }` (or `{ type ClientRouter }`).
|
|
162
|
+
|
|
163
|
+
If soft-navigation is not working because your reference takes one of these forms
|
|
164
|
+
(or the mounting module is otherwise not reachable from a page), force the
|
|
165
|
+
runtime in with an explicit side-effect import from a page-reachable
|
|
166
|
+
`"use client"` island. The island renders nothing; running its bundle in the
|
|
167
|
+
browser fires the same `typeof document !== "undefined"` guard (`init()` is
|
|
168
|
+
idempotent, so reaching it again is a no-op):
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
// src/components/client-router-bootstrap.tsx
|
|
172
|
+
"use client";
|
|
173
|
+
import "@takazudo/zfb-runtime/client-router";
|
|
174
|
+
|
|
175
|
+
export default function ClientRouterBootstrap() {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Stable marker name so the SSR marker, the scanner record, and the hydration
|
|
180
|
+
// manifest agree under production minification.
|
|
181
|
+
ClientRouterBootstrap.displayName = "ClientRouterBootstrap";
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { Island } from "@takazudo/zfb";
|
|
186
|
+
import ClientRouterBootstrap from "@/components/client-router-bootstrap";
|
|
187
|
+
|
|
188
|
+
// Mount once near the end of <body>; when="load" registers the intercepts as
|
|
189
|
+
// soon as the islands runtime starts.
|
|
190
|
+
<Island when="load">
|
|
191
|
+
<ClientRouterBootstrap />
|
|
192
|
+
</Island>;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
This is the escape hatch, not the default — prefer a plain
|
|
196
|
+
`import { ClientRouter } from "@takazudo/zfb-runtime"`, which the scanner detects
|
|
197
|
+
on its own. See the [Client-Side Routing concept
|
|
198
|
+
guide](https://takazudomodular.com/pj/zudo-front-builder/docs/concepts/client-side-routing/)
|
|
199
|
+
for the full API.
|
|
200
|
+
|
|
98
201
|
### `createPageRouter(options) → PageRouter`
|
|
99
202
|
|
|
100
203
|
Build a fetch-handler that serves the supplied pages. The returned
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takazudo/zfb-runtime",
|
|
3
|
-
"version": "0.1.0-next.
|
|
3
|
+
"version": "0.1.0-next.57",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "JavaScript runtime for zfb static sites — Hono-backed page router, content snapshots, and client-side hydration.",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"react": "^19.2.3",
|
|
64
|
-
"@takazudo/zfb": "0.1.0-next.
|
|
64
|
+
"@takazudo/zfb": "0.1.0-next.57"
|
|
65
65
|
},
|
|
66
66
|
"peerDependenciesMeta": {
|
|
67
67
|
"react": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"react": "^19.2.3",
|
|
76
76
|
"typescript": "^5.9.0",
|
|
77
77
|
"vitest": "^2.1.9",
|
|
78
|
-
"@takazudo/zfb": "0.1.0-next.
|
|
78
|
+
"@takazudo/zfb": "0.1.0-next.57"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"build": "tsc",
|