@elurjs/kit 2.5.0 → 2.6.0-beta.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/CHANGELOG.md +31 -0
- package/README.md +53 -6
- package/dist/lib/cli.cjs +1 -9
- package/dist/lib/cli.cjs.map +1 -1
- package/dist/lib/cli.js +1 -9
- package/dist/lib/cli.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,37 @@ All notable changes to Elur Kit are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.6.0-beta.0]
|
|
9
|
+
|
|
10
|
+
Prerelease del canal beta alineada con `@elurjs/core@3.7.0-beta.0`
|
|
11
|
+
(motor `next-2` por defecto) y `@elurjs/vite-plugin-elur@2.2.0-beta.0`
|
|
12
|
+
(emit gating + writers especializados). Sin cambios funcionales en Kit:
|
|
13
|
+
todas las features de router next-gen y zero-JS ya shippearon en 2.5.x.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Peer ranges ampliados** — `@elurjs/core` acepta
|
|
18
|
+
`^3.6.2 || ^3.7.0-beta.0` y `@elurjs/vite-plugin-elur` acepta
|
|
19
|
+
`^2.1.0 || ^2.2.0-beta.0`, permitiendo instalar el stack beta completo
|
|
20
|
+
sin warnings de peer deps.
|
|
21
|
+
- **Lockfile migrado a `bun.lock`** — `package-lock.json` eliminado del
|
|
22
|
+
repo (el workspace usa bun).
|
|
23
|
+
|
|
24
|
+
## [2.5.1]
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **`elur-kit build` never generated image variants** — the CLI bundle
|
|
29
|
+
(`dist/lib/cli.js`) had `import("sharp")` rewritten by Vite's
|
|
30
|
+
optional-peer-dep transform into a stub that always throws
|
|
31
|
+
(`Could not resolve "sharp"`), because `sharp` was missing from the
|
|
32
|
+
externals in `vite.cli.config.ts`. `loadSharp()` caught the error and
|
|
33
|
+
permanently returned `null`, so `processImageBatch` fell back to
|
|
34
|
+
manifest-only entries (`variants: []`) and every `image()` emitted a
|
|
35
|
+
plain `<img>` instead of a `<picture>` with WebP/AVIF sources. `sharp`
|
|
36
|
+
is now external in the CLI build, so the optional peer resolves from
|
|
37
|
+
the consuming project's `node_modules` at runtime.
|
|
38
|
+
|
|
8
39
|
## [2.5.0]
|
|
9
40
|
|
|
10
41
|
All changes are additive and backwards-compatible: existing projects work
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@elurjs/kit)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
> Full-stack framework for Elur — file-based routing, SSG, SSR, ISR, streaming, islands, actions, content collections, cache adapters, and SPA-like navigation. Zero extra runtime dependencies on the client: Elur stays at ~15 KB. Optional build-time compiler lowers `
|
|
6
|
+
> Full-stack framework for Elur — file-based routing, SSG, SSR, ISR, streaming, islands, actions, content collections, cache adapters, and SPA-like navigation. Zero extra runtime dependencies on the client: Elur stays at ~15 KB. Optional build-time compiler lowers ``html` `` templates to imperative DOM code for ~25–44% faster renders.
|
|
7
7
|
|
|
8
8
|
## What is Elur Kit?
|
|
9
9
|
|
|
@@ -22,7 +22,7 @@ Elur Kit is a framework built on top of [Elur](https://elur.dev/). It brings con
|
|
|
22
22
|
|
|
23
23
|
- **Routing**: file-based with dynamic segments, optional catch-all `[[...slug]]`, route conflict detection, safe URL decoding, redirects/rewrites/route headers
|
|
24
24
|
- **Rendering**: SSG, SSR, ISR with explicit cache policy (public/private/dynamic), opt-in streaming SSR with `loading.ts` boundaries (**experimental** — ver [Streaming SSR](#streaming-ssr-experimental))
|
|
25
|
-
- **Build-time compiler** (optional, recommended): integrates [`@elurjs/core-compiler`](https://www.npmjs.com/package/@elurjs/core-compiler) via [`@elurjs/vite-plugin-elur`](https://www.npmjs.com/package/@elurjs/vite-plugin-elur) to lower `
|
|
25
|
+
- **Build-time compiler** (optional, recommended): integrates [`@elurjs/core-compiler`](https://www.npmjs.com/package/@elurjs/core-compiler) via [`@elurjs/vite-plugin-elur`](https://www.npmjs.com/package/@elurjs/vite-plugin-elur) to lower ``html` `` templates to imperative DOM code at build time — eliminates `detectContext`, `buildHTML`, and both `TreeWalker` passes in runtime
|
|
26
26
|
- **Partial attribute interpolation**: `class="btn ${size}"` works out of the box via the Vite plugin's state-machine lexer (or the kit's legacy transform as fallback)
|
|
27
27
|
- **Actions**: typed `defineAction()` with input validation, AbortSignal, idempotency, concurrency modes (latest/queue/parallel)
|
|
28
28
|
- **Cache**: `CacheAdapter` with filesystem, Redis, and Cloudflare KV storage, SHA-256 keys, atomic writes, single-flight, stale-while-revalidate, tag-based invalidation
|
|
@@ -48,7 +48,7 @@ npm install @elurjs/vite-plugin-elur
|
|
|
48
48
|
|
|
49
49
|
The plugin is an optional peer dependency. When installed, it activates:
|
|
50
50
|
|
|
51
|
-
- **Build-time compiler** — lowers `
|
|
51
|
+
- **Build-time compiler** — lowers ``html` `` to imperative DOM code
|
|
52
52
|
- **Partial attribute interpolation** — state-machine lexer (replaces the kit's legacy transform)
|
|
53
53
|
- **HMR with state preservation** — signals, stores, forms, routers survive hot updates
|
|
54
54
|
- **Scroll/focus preservation** — restored after re-mount
|
|
@@ -266,6 +266,52 @@ routes you want cached.
|
|
|
266
266
|
- Behind a reverse proxy, make sure buffering and gzip buffering are disabled
|
|
267
267
|
for streamed routes (the `X-Accel-Buffering: no` header covers nginx).
|
|
268
268
|
|
|
269
|
+
## What's new in v2.5
|
|
270
|
+
|
|
271
|
+
**0% JavaScript by default + next-generation router.**
|
|
272
|
+
|
|
273
|
+
- **Per-page JS gating** — the document shell scans the rendered body
|
|
274
|
+
for `data-elur-island` markers: pages without islands ship **0 KB of
|
|
275
|
+
JS** when `router.enabled: false`, or **only the router chunk** when
|
|
276
|
+
the router is on. Pages with islands get `entry-client.js` +
|
|
277
|
+
`router.js`, each with `<link rel="modulepreload">`. Escape hatch:
|
|
278
|
+
`defineConfig({ js: "legacy" })` restores the unconditional combined
|
|
279
|
+
entry. See [Per-page JavaScript emission](#per-page-javascript-emission).
|
|
280
|
+
- **Split client entries** — the generated entry is hydrate-only and
|
|
281
|
+
the router lives in `.elur/router.ts` → `/_elur/router.js`.
|
|
282
|
+
Single-input `vite.client.config.*` files keep working (router
|
|
283
|
+
embedded = legacy mode de facto).
|
|
284
|
+
- **Production head fix** — `/__elur-js/render` now returns
|
|
285
|
+
`{ title, body, head, data, actions, clearActionErrorCookie }` in
|
|
286
|
+
every runtime; head metadata updates on SPA navigations and the
|
|
287
|
+
action-error cookie is actually cleared.
|
|
288
|
+
- **Navigation lifecycle events** — `elur:navigate-start` /
|
|
289
|
+
`elur:navigate-end` / `elur:navigate-error` with
|
|
290
|
+
`{ pathname, search, fromCache, popstate }`, plus
|
|
291
|
+
`elur:before-render` before the swap (islands dispose while still
|
|
292
|
+
attached; `detail.persisted` lists survivors).
|
|
293
|
+
- **`data-elur-persist="key"`** — live DOM nodes are moved (not
|
|
294
|
+
re-rendered) across navigations via `Element.moveBefore()`
|
|
295
|
+
(`replaceWith` fallback); islands inside keep their state.
|
|
296
|
+
- **Router robustness** — bounded LRU prefetch cache (32 entries,
|
|
297
|
+
30 s), `history.scrollRestoration = "manual"` with per-entry scroll,
|
|
298
|
+
prefetch on `pointerenter`/`focus`/`pointerdown` + opt-in viewport
|
|
299
|
+
(`data-prefetch="viewport"`), Save-Data/2g-aware, inline `<script>`
|
|
300
|
+
re-execution after navigation, `#elur-data`/`#elur-actions` refresh.
|
|
301
|
+
- **Optional extras** — `router.morph` (idiomorph-based DOM morphing,
|
|
302
|
+
experimental), `router.loadingIndicator` (top progress bar, >200 ms
|
|
303
|
+
delay, reduced-motion aware), `router.speculation` (Speculation
|
|
304
|
+
Rules API on static pages).
|
|
305
|
+
- **`directive: "load"` is real now** — the generated entry calls
|
|
306
|
+
`hydrateIslands()` immediately; the global `requestIdleCallback`
|
|
307
|
+
wrapper is gone. `idle`/`visible` keep their deferred scheduling.
|
|
308
|
+
- **`startClientRouter(options)`** accepts
|
|
309
|
+
`{ prefetch, morph, loadingIndicator }`; `prefetch()` gains
|
|
310
|
+
`{ force: true }` to bypass network guards.
|
|
311
|
+
|
|
312
|
+
All changes are backwards-compatible; existing projects keep working
|
|
313
|
+
unchanged.
|
|
314
|
+
|
|
269
315
|
## What's new in v2.4
|
|
270
316
|
|
|
271
317
|
- **Fixed: image pipeline silently no-op** — the CLI bundle was
|
|
@@ -315,7 +361,7 @@ routes you want cached.
|
|
|
315
361
|
SSR errors are never silently swallowed — they propagate wrapped with
|
|
316
362
|
the island name and remediation hints.
|
|
317
363
|
|
|
318
|
-
|
|
364
|
+
### Using the `build` hook for sitemaps
|
|
319
365
|
|
|
320
366
|
When `site` is set in your config, the build **already generates
|
|
321
367
|
`sitemap.xml` automatically** from the scanned routes (dynamic routes,
|
|
@@ -396,7 +442,7 @@ When both plugins are installed:
|
|
|
396
442
|
| Feature | Kit only | Kit + Vite plugin |
|
|
397
443
|
| --- | --- | --- |
|
|
398
444
|
| Partial attr interpolation | Legacy transform (heuristic) | State-machine lexer (compile-time) |
|
|
399
|
-
| Build-time compiler | No | Yes (`
|
|
445
|
+
| Build-time compiler | No | Yes (``html` `` → imperative DOM) |
|
|
400
446
|
| HMR state preservation | No | Yes (signals, stores, forms, routers) |
|
|
401
447
|
| Scroll/focus preservation | No | Yes |
|
|
402
448
|
| SSR | Works (kit handles it) | Works (plugin skips compiler in SSR) |
|
|
@@ -514,6 +560,7 @@ receive the full transform pipeline.
|
|
|
514
560
|
| v2.4.2 | Integration `build` hook wired into `build()`, `BuildResult.outDir` for post-build artifacts ✅ |
|
|
515
561
|
| v2.4.3 | Client-only islands (`directive: "only"`, `options: { ssr: false, fallback }`), `isSSR()` export, SSR error wrapping ✅ |
|
|
516
562
|
| v2.4.4 | Fix: `"only"` directive now hydrates immediately like `"load"`. Fix: islands without SSR DOM use fresh `_render` mount instead of `hydrateTemplate` ✅ |
|
|
563
|
+
| v2.5 | 0% JS por defecto (gating por página + split entry/router + `js:"legacy"`), router de nueva generación (eventos de ciclo de vida, `data-elur-persist`, LRU+network-aware prefetch, morph opcional, speculation rules, loading indicator), fix head/payload del render endpoint en prod, `load` real ✅ |
|
|
517
564
|
|
|
518
565
|
## API
|
|
519
566
|
|
|
@@ -996,7 +1043,7 @@ export default defineConfig({
|
|
|
996
1043
|
|
|
997
1044
|
The Vite plugin activates:
|
|
998
1045
|
|
|
999
|
-
- **Build-time compiler** — lowers `
|
|
1046
|
+
- **Build-time compiler** — lowers ``html` `` templates to imperative DOM
|
|
1000
1047
|
code (`firstChild`/`nextSibling` navigation, inline `setAttribute`,
|
|
1001
1048
|
grouped effects, event delegation). Eliminates `detectContext`,
|
|
1002
1049
|
`buildHTML`, and both `TreeWalker` passes in runtime.
|
package/dist/lib/cli.cjs
CHANGED
|
@@ -877,14 +877,6 @@ function actionNames(actions) {
|
|
|
877
877
|
}
|
|
878
878
|
var init_scan = __esmMin((() => {}));
|
|
879
879
|
//#endregion
|
|
880
|
-
//#region __vite-optional-peer-dep:sharp:@elurjs/kit
|
|
881
|
-
var kit_exports = /* @__PURE__ */ __exportAll({ default: () => kit_default });
|
|
882
|
-
var kit_default;
|
|
883
|
-
var init_kit = __esmMin((() => {
|
|
884
|
-
kit_default = {};
|
|
885
|
-
throw new Error(`Could not resolve "sharp" imported by "@elurjs/kit". Is it installed?`);
|
|
886
|
-
}));
|
|
887
|
-
//#endregion
|
|
888
880
|
//#region src/image/service.ts
|
|
889
881
|
init_render();
|
|
890
882
|
init_scan();
|
|
@@ -898,7 +890,7 @@ async function loadSharp() {
|
|
|
898
890
|
if (sharpLoader === null) return null;
|
|
899
891
|
if (sharpLoader) return sharpLoader();
|
|
900
892
|
try {
|
|
901
|
-
const sharp = (await
|
|
893
|
+
const sharp = (await import("sharp")).default;
|
|
902
894
|
if (typeof sharp !== "function") {
|
|
903
895
|
sharpLoader = null;
|
|
904
896
|
return null;
|