ripple@0.4.3
Ripple-TS/rippleripple@0.4.3Sep 17, 2026by github-actions[bot]
Upgrading?
AI Summary
This release focuses on performance optimizations, including smaller bundle sizes, improved compiler lowering for static templates, and a new API for tracking read-only values.
Key Highlights
- Replaced `readOnly()` method with `trackReadOnly(value)` function
- Optimized static component rendering and `@if`/`@for` loops to reduce anchor nodes
- Reduced bundle size by removing unused runtime modules and static methods
- Improved tree-shaking for dynamic attributes and class composition
Breaking Changes
- The `readOnly()` method on tracked values has been removed and replaced with `trackReadOnly(value)`
New Features
- Optimized event delegation and anchor node materialization
- Support for SVG and MathML namespace templates without overhead
Full Release Notes
### Patch Changes
- [#1486](https://github.com/Ripple-TS/ripple/pull/1486)
[`304ba6c`](https://github.com/Ripple-TS/ripple/commit/304ba6c2d9098752396fff6c2545e3ef2546381c)
Thanks [@leonidaz](https://github.com/leonidaz)! - perf: a static component,
template `@if`, or template `@for` followed by a static element sibling inserts
before that element instead of before a `<!>` placeholder of its own: the
element is part of the template and never moves, so the compiled template holds
no comment node for it and the client reuses the element's variable where
hydration steps to the sibling. The `RippleArray` statics (`from`, `of`,
`fromAsync`) lower to standalone runtime functions, so a bundle that never
constructs a `RippleArray` drops the array proxy instead of keeping it through
property assignments on the constructor's compiled form (the server's
`fromAsync` lowering previously named a function that did not exist).
- [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
Thanks [@leonidaz](https://github.com/leonidaz)! - perf: smaller production
bundles without a runtime cost. The compiler lowers a static `onBlur`-style
handler (an event its name keeps off delegation) to a direct `listen` call with
the DOM name and phase resolved at compile time, packs the locals a hoisted
`@if`/`@switch` captures under positional keys, writes template strings without
attribute quotes or implied end tags where the parser reads them back the same,
gives a plain function no `_$_.scope()` call when its body never reads the
block, and omits `set_class`'s default trailing arguments. The runtime keeps its
hydration paths (template adoption, expression text, append cursor, streamed
boundaries) in a module `hydrate()` installs and its `trackAsync` machinery in a
module that registers with the runtime on first use, and the catch routing is
registered by the first boundary, so a client-only mount without `trackAsync`
ships neither and the core runtime no longer imports the boundary module; the
try boundary state, the root event ref and the template cache use short keys,
the keyed and reference list diffs share one patch helper, and symbol constants
carry no descriptions. The runtime's errors are thrown as in Svelte: the message
and a link to `https://ripple-ts.com/e/<code>` in development, the link alone in
production, so the message text stays out of production bundles; `set_class`
composes non-string values with its own clsx-style joiner instead of importing
`clsx`; hoisted render blocks store captured locals under positional keys; a
`template()` with no flags passes none; and the hash a `track()` call carries
encodes the same 32 bits in base 36. The Vite plugin leaves Vite's modulepreload
polyfill out of production builds unless `build.modulePreload` is configured.
- [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
Thanks [@leonidaz](https://github.com/leonidaz)! - feat: build shapes.
`ripple({ ssr: false })` builds a client-only app: components compile without
the hydration cursor or `track()` serialization hashes (`hydration: false` on
the compiler), the runtime's hydration paths are compiled out through its
`HYDRATION` build constant, and `hydrate()` throws; `ssr: true` compiles every
module for the server. `prerender()` on `ripple/server` renders a component to
static HTML with every boundary settled and the CSS as text, and a `RenderRoute`
marked `prerender: true` is rendered through the built server entry at build
time into `<outDir>/client<path>/index.html`, which the node and bun adapters
now serve for a directory request before the server renders. The client build's
`index.html` template moves to the server output so a static handler never
serves its placeholders.
- [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
Thanks [@leonidaz](https://github.com/leonidaz)! - perf: a `class` expression
the compiler can prove to be a string writes through a string-only `set_class`,
so the clsx-style joiner ships only with a bundle that composes classes from
arrays or objects; templates in the SVG or MathML namespace parse through a
`template_ns` entry that an HTML-only bundle never loads; and the class joiner
is one module shared by the client and server renderers, so `ripple` no longer
depends on `clsx`. `ripple({ rootBoundary: false })` builds an app that renders
without the default root try/pending/catch boundary and leaves the boundary
runtime out of the bundle; a `rootBoundary` option on `mount()` or `hydrate()`
then throws. The `ripple` package declares `sideEffects: false`, and dynamic
attribute, style and spread helpers live in their own runtime module, so a
bundle that never sets an attribute dynamically drops them along with the
attribute tables they consult. The plugin's `ssr: false` and
`rootBoundary: false` rewrite the runtime's build-constant imports to literals
at transform time, which every bundler folds while tree-shaking.
- [#1484](https://github.com/Ripple-TS/ripple/pull/1484)
[`1ea71f1`](https://github.com/Ripple-TS/ripple/commit/1ea71f14fcee5a976ea81e2bedf5010251eaa70c)
Thanks [@leonidaz](https://github.com/leonidaz)! - perf: a template `@if` that
closes the trailing run of an element's children (nothing rendered follows it)
never materializes an anchor node: the element's tail is its position for its
whole life. An `@if (outer === item.key)` in a `@for` body lowers to the loop's
selector like an attribute comparison, and a comparison against the item's key
reads the block's key (fixed for its life) rather than the item, so a change of
the outer value re-runs the ifs of its previous and next key alone and a
replaced item leaves its ifs untouched; comparisons against the same outer value
share one selector per loop. Event delegation reads the composed path only for a
nested root and looks the handler property up by one string, and `checked` is
compared against the element instead of a cached write.
- [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
Thanks [@leonidaz](https://github.com/leonidaz)! - `trackReadOnly(value)`
replaces the `readOnly()` method on tracked and derived values: it returns a
derived that follows a tracked or writable derived, or a read-only derived as it
is. The method is removed, so `count.readOnly()` becomes `trackReadOnly(count)`,
imported from `ripple`. Dropping the prototype methods lets a bundle that never
takes a read-only view leave the code out.
- Updated dependencies
[[`304ba6c`](https://github.com/Ripple-TS/ripple/commit/304ba6c2d9098752396fff6c2545e3ef2546381c),
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1),
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1),
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1),
[`1ea71f1`](https://github.com/Ripple-TS/ripple/commit/1ea71f14fcee5a976ea81e2bedf5010251eaa70c),
[`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)]:
- @tsrx/ripple@0.2.2Related Repositories
affaan-m/ECC★ 285,772
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
react/react★ 251,624
The library for web and native user interfaces.
nodejs/node★ 122,521
Node.js JavaScript runtime ✨🐢🚀✨
Leonxlnx/taste-skill★ 100,621
Agent skills that give coding agents taste: art direction, reference images and a browser check instead of generic AI pages
louislam/uptime-kuma★ 92,731
A fancy self-hosted monitoring tool