create-pracht 0.6.0 → 0.6.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/package.json +1 -1
- package/skills/audit-bundles/SKILL.md +8 -0
- package/skills/migrate-nextjs/SKILL.md +9 -0
- package/skills/pracht-debug/SKILL.md +8 -0
- package/skills/pracht-deploy/SKILL.md +8 -4
- package/skills/pre-deploy/SKILL.md +8 -2
- package/skills/typed-routes/SKILL.md +6 -2
- package/skills/upgrade-pracht/SKILL.md +5 -2
- package/src/index.js +5 -0
package/package.json
CHANGED
|
@@ -137,6 +137,14 @@ overrides the route-level strategy for a single anchor (and accepts the extra
|
|
|
137
137
|
option), so a route can stay on `"intent"` while its primary-nav link opts
|
|
138
138
|
into `"viewport"` or `"render"`.
|
|
139
139
|
|
|
140
|
+
If every route ends up on `"none"`, do not stop there — the prefetch listeners
|
|
141
|
+
still ship, in a chunk the router lazily imports on every page. Recommend
|
|
142
|
+
`pracht({ client: { prefetch: false } })` instead, which compiles the whole
|
|
143
|
+
mechanism out (~2.6 KB gzip and one fewer request). Confirm nothing relies on
|
|
144
|
+
prefetching first: the router silently stops honouring `route({ prefetch })` and
|
|
145
|
+
`<Link prefetch>`, and the imperative `prefetch()` export becomes a no-op. See
|
|
146
|
+
`docs/PERFORMANCE.md#switching-off-js-prefetching`.
|
|
147
|
+
|
|
140
148
|
## Step 7: Report
|
|
141
149
|
|
|
142
150
|
Three sections:
|
|
@@ -424,6 +424,15 @@ the `@pracht/image/client` types once in a `.d.ts`, and keep
|
|
|
424
424
|
`width`/`height`/`blurDataURL` exactly like Next's static imports. Pracht's
|
|
425
425
|
blur is CSS-only (no fade animation, no inline event handlers).
|
|
426
426
|
|
|
427
|
+
For apps that relied on `next/image` producing files during a static export,
|
|
428
|
+
use `?pracht&pracht-static` instead. It emits cached responsive WebP variants
|
|
429
|
+
and bypasses the runtime loader while retaining plain, hydration-free `<img>`
|
|
430
|
+
markup. When Markdown content contains relative images, prefer
|
|
431
|
+
`defineMarkdownCollection()` from `@pracht/markdown`; it applies the same
|
|
432
|
+
static pipeline to normal `` syntax. Keep root-relative
|
|
433
|
+
`public/` and remote image URLs unchanged, and use an absolute Vite `base` for
|
|
434
|
+
static variants.
|
|
435
|
+
|
|
427
436
|
#### `useRouter` → navigation
|
|
428
437
|
|
|
429
438
|
```tsx
|
|
@@ -72,6 +72,14 @@ Work through these in order, stopping when you find the root cause:
|
|
|
72
72
|
- Date/time rendering differences
|
|
73
73
|
- Browser-only APIs used during SSR (`window`, `document`, `localStorage`)
|
|
74
74
|
- Conditional rendering based on client state
|
|
75
|
+
- Two copies of `@pracht/core` in the SSR module graph. The tell is that
|
|
76
|
+
`useLocation()` returns `/`, `useParams()` returns `{}`, and
|
|
77
|
+
`useRouteData()` returns `undefined` in the server-rendered HTML for
|
|
78
|
+
*every* page, while the hydrated client is correct — the provider and the
|
|
79
|
+
hooks hold different `createContext()` objects. The plugin prevents this by
|
|
80
|
+
keeping `@pracht/*` in `ssr.noExternal` (dev and build alike); listing a
|
|
81
|
+
`@pracht/*` package in `ssr.external` overrides that and brings the split
|
|
82
|
+
back.
|
|
75
83
|
- **Missing shell**: Referencing an unregistered shell name throws at manifest resolution — `Unknown shell "..." for route "...". Did you mean "..."? Registered shells: ...` — and shows up in the dev error overlay as soon as the server loads the manifest. Verify the shell is registered in `defineApp({ shells: { ... } })` and assigned to the route/group.
|
|
76
84
|
- **404 page**: Route not matched — check manifest wiring (step 1). In `pracht dev`, unmatched navigations render a dev-only 404 page listing every registered route with its render mode; compare the requested path against that table. The route table is also printed on dev-server startup and available via `pracht inspect routes`. Apps that declare `defineApp({ notFound })` render their own 404 page instead (in dev and production alike), so the route table is not shown — check `pracht inspect routes` directly. A 404 on a URL you *do* expect to work usually means the loader threw `notFound()`, not that matching failed.
|
|
77
85
|
|
|
@@ -133,7 +133,7 @@ pracht build
|
|
|
133
133
|
npx wrangler deploy
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
To smoke-test the built worker locally first, run `pracht preview` — it builds and then delegates to `wrangler dev`, which serves the wrangler config's `main` entry, `dist/server/worker.js`.
|
|
136
|
+
To smoke-test the built worker locally first, run `pracht preview` — it builds and then delegates to `wrangler dev`, which serves the wrangler config's `main` entry, `dist/server/worker.js`. Keep `no_bundle: true` and the JavaScript `ESModule` rule: Pracht's Vite output is already bundled and can contain lazy server chunks that Wrangler must upload separately.
|
|
137
137
|
|
|
138
138
|
Wrangler owns the Worker's binding environment. Put local-only secrets such as
|
|
139
139
|
`PRACHT_CONFIRMATION_SECRET` and `PRACHT_REVALIDATE_TOKEN` in a gitignored
|
|
@@ -151,8 +151,10 @@ pracht build
|
|
|
151
151
|
npx wrangler dev --config wrangler.local.jsonc --port 3000
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
-
The local config must keep `main: "dist/server/worker.js"
|
|
155
|
-
|
|
154
|
+
The local config must keep `main: "dist/server/worker.js"`, keep
|
|
155
|
+
`no_bundle: true`, include the JavaScript `ESModule` rule, and omit the
|
|
156
|
+
production route. `pracht preview` does not forward Wrangler's `--config`
|
|
157
|
+
flag.
|
|
156
158
|
|
|
157
159
|
### Wrangler Configuration
|
|
158
160
|
|
|
@@ -161,6 +163,8 @@ production route. `pracht preview` does not forward Wrangler's `--config` flag.
|
|
|
161
163
|
{
|
|
162
164
|
"name": "my-pracht-app",
|
|
163
165
|
"main": "dist/server/worker.js",
|
|
166
|
+
"no_bundle": true,
|
|
167
|
+
"rules": [{ "type": "ESModule", "globs": ["**/*.js", "**/*.mjs"] }],
|
|
164
168
|
"compatibility_date": "2026-04-06",
|
|
165
169
|
"assets": {
|
|
166
170
|
"binding": "ASSETS",
|
|
@@ -170,7 +174,7 @@ production route. `pracht preview` does not forward Wrangler's `--config` flag.
|
|
|
170
174
|
}
|
|
171
175
|
```
|
|
172
176
|
|
|
173
|
-
`"binding": "ASSETS"
|
|
177
|
+
`"no_bundle": true`, the JavaScript `ESModule` rule, `"binding": "ASSETS"`, and `"run_worker_first": true` are required. Without the first two settings, Wrangler either re-bundles Pracht's Vite output and folds lazy server chunks into the entry or omits those chunks from the upload. Without the binding, the worker's `env.ASSETS` resolves to nothing and the runtime silently falls back to `null` — headers and ISG manifests load empty, so SSG serving, ISG revalidation, and per-route headers all silently no-op. The canonical config lives at `examples/cloudflare/wrangler.jsonc`. If you rename the binding with `assetsBinding` (below), the wrangler `binding` value must match.
|
|
174
178
|
|
|
175
179
|
### Bindings (KV, D1, R2)
|
|
176
180
|
|
|
@@ -98,6 +98,10 @@ a markdown summary (graph diff + verify + budgets) worth attaching to it.
|
|
|
98
98
|
validates every named export of the deploy entry and rejects the build
|
|
99
99
|
metadata (`buildTarget`, manifests, `resolvedApp`, ...) that `server.js`
|
|
100
100
|
exports for the prerender pass.
|
|
101
|
+
- `no_bundle` is `true`, with an `ESModule` rule whose globs include
|
|
102
|
+
`"**/*.js"`. Pracht's Vite output is already bundled and may contain lazy
|
|
103
|
+
server chunks; these settings make Wrangler upload the chunks as separate
|
|
104
|
+
modules instead of folding them into the entry file.
|
|
101
105
|
- `assets.directory` points to `dist/client`.
|
|
102
106
|
- `compatibility_date` is set, and is a date the installed workerd supports.
|
|
103
107
|
It must not be *newer* than the runtime: workerd refuses to start with
|
|
@@ -128,8 +132,10 @@ a markdown summary (graph diff + verify + budgets) worth attaching to it.
|
|
|
128
132
|
gateway with a normalized `cf.cacheKey`; also check that markdown-capable
|
|
129
133
|
routes normalize `Accept` at the gateway when variant fan-out matters.
|
|
130
134
|
- Bundle size: measure what actually deploys — `dist/server/worker.js` plus
|
|
131
|
-
its `dist/server/server.js` import
|
|
132
|
-
|
|
135
|
+
its `dist/server/server.js` import and lazy chunks (`no_bundle: true` plus
|
|
136
|
+
the JavaScript `ESModule` rule uploads the pre-built module graph;
|
|
137
|
+
`worker.js` alone is a few lines).
|
|
138
|
+
Workers limit is ~1 MB
|
|
133
139
|
compressed for free tier, ~10 MB on paid. Warn at 80% of the active limit.
|
|
134
140
|
|
|
135
141
|
### Vercel (`@pracht/adapter-vercel`)
|
|
@@ -107,8 +107,12 @@ same-origin anchor. It also accepts navigation-behavior props:
|
|
|
107
107
|
`prefetch="none" | "hover" | "intent" | "viewport" | "render"` (per-link
|
|
108
108
|
prefetch strategy, default `"intent"`), `preserveScroll` (keep the scroll
|
|
109
109
|
position), and `viewTransition` (animate the navigation with the View Transitions API
|
|
110
|
-
where supported).
|
|
111
|
-
|
|
110
|
+
where supported). Set `speculate={false}` on links that browser speculation
|
|
111
|
+
rules must not prefetch or prerender. Because it is independent of the JS
|
|
112
|
+
`prefetch` strategy, use both `speculate={false}` and `prefetch="none"` for GET
|
|
113
|
+
links with side effects. There is also an imperative
|
|
114
|
+
`prefetch()` export and a `useNavigation()` hook for pending
|
|
115
|
+
navigation/submission state.
|
|
112
116
|
|
|
113
117
|
### Outside components
|
|
114
118
|
|
|
@@ -33,8 +33,9 @@ pnpm list --depth 1 --json | grep -A2 '@pracht/' # or read package.json + lock
|
|
|
33
33
|
|
|
34
34
|
The family: `@pracht/core`, `@pracht/cli`, `@pracht/vite-plugin`,
|
|
35
35
|
`@pracht/adapter-node`, `@pracht/adapter-cloudflare`, `@pracht/adapter-vercel`,
|
|
36
|
-
`@pracht/preact-ssr-precompile`, `@pracht/
|
|
37
|
-
|
|
36
|
+
`@pracht/preact-ssr-precompile`, `@pracht/content`, `@pracht/markdown`,
|
|
37
|
+
`@pracht/image`. Get the latest published versions with
|
|
38
|
+
`npm view <pkg> version`.
|
|
38
39
|
|
|
39
40
|
## Step 2: Understand the versioning model
|
|
40
41
|
|
|
@@ -75,6 +76,8 @@ https://raw.githubusercontent.com/JoviDeCroock/pracht/main/packages/<dir>/CHANGE
|
|
|
75
76
|
| `@pracht/vite-plugin` | `packages/vite-plugin` |
|
|
76
77
|
| `@pracht/adapter-node` / `-cloudflare` / `-vercel` | `packages/adapter-*` |
|
|
77
78
|
| `@pracht/preact-ssr-precompile` | `packages/preact-ssr-precompile` |
|
|
79
|
+
| `@pracht/content` | `packages/content` |
|
|
80
|
+
| `@pracht/markdown` | `packages/markdown` |
|
|
78
81
|
| `@pracht/image` | `packages/image` |
|
|
79
82
|
|
|
80
83
|
Changelogs are changesets-generated: `## X.Y.Z` sections containing
|
package/src/index.js
CHANGED
|
@@ -1298,6 +1298,11 @@ function createWranglerConfig(projectName) {
|
|
|
1298
1298
|
// validates every named export of the deployed entry module and rejects the
|
|
1299
1299
|
// build metadata (buildTarget, manifests, ...) server.js also exports.
|
|
1300
1300
|
' "main": "dist/server/worker.js",',
|
|
1301
|
+
// Pracht's Vite build is the authoritative bundle and may contain lazy
|
|
1302
|
+
// server chunks. A second Wrangler bundle would inline them again; the
|
|
1303
|
+
// module rule makes Wrangler upload those chunks next to the entry.
|
|
1304
|
+
' "no_bundle": true,',
|
|
1305
|
+
' "rules": [{ "type": "ESModule", "globs": ["**/*.js", "**/*.mjs"] }],',
|
|
1301
1306
|
` "compatibility_date": ${JSON.stringify(compatibilityDate)},`,
|
|
1302
1307
|
' "assets": {',
|
|
1303
1308
|
' "binding": "ASSETS",',
|