Skip to content

Releases: ryansolid/dom-expressions

v0.23.0

13 Nov 09:39
Compare
Choose a tag to compare
  • Change SSR key to data-hk to pass HTML validation
  • Simplify component spreads removing extra wrappers with flag
  • Typedefs for role attribute
  • Add web stream API (support Cloudflare Worker streaming)
  • Remove extra function wrappers on DOM insert expressions when simple function call signal() becomes signal instead of () => signal()

v0.20.0

24 Aug 04:02
Compare
Choose a tag to compare
  • Added support for synchronous and streaming SSR modes.
  • More granular SSR escaping.
  • Changed props wrapping for JSX to be inline
  • Fixes:
    • ref forms when passed from a function
    • SVG class property

v0.19.0

19 Jun 05:44
Compare
Choose a tag to compare
  • Fixes to handling to static expressions in textNodes
  • Better attribute handling to handle attribute removal
  • Optimize function refs
  • Improve SSR performance
  • Fix CSS property Types
  • Add basic support for JSX attribute namespaces
  • Fix HyperScript when given null props

v0.18.0 - String SSR

02 May 05:23
Compare
Choose a tag to compare

This release represents a complete restructure of the project. Both for handling multiple render targets for the Babel plugin, and to move away from EJS for building the runtime. Instead using Babel to rewrite the entry. This drastically simplifies the process of using it.

Breaking Changes

  • Runtime methods have been renamed, and method of using the runtime is completely different.
  • removed forwardRef and merged the functionality with ref.
  • New approach to TypeScript involving packaging with library rather than shipped with Babel Plugin.
  • Changed Babel Plugin generate options. Old DOM SSR is "dom-ssr".

New Features

  • String SSR

Fixes

  • Support for hyphenated attributes on components
  • Fixed attributes in spreads

v0.17.0

24 Mar 02:40
Compare
Choose a tag to compare

Breaking Changes to Event System

  • Removed casing consideration. All on____ events handled the same. If they are not non-composable or non-bubbling they will be delegated by default otherwise level 1 events.
  • Renamed the events binding as the on binding. This adds typical level 3 event handlers for irregular events or events you do not wish to delegate.
  • Removed model mechanism. Bound events are now using an array syntax inspired by Inferno [handler, boundValue] where the handler takes the boundValue as the first parameter and the event as the second.

Other Improvements

  • Drastically shrunk list reconciler based on udomdiff
  • Changed template checking method to count tags instead of string compare to reduce false warnings.
  • Improved ternary heuristics to reduce unnecessary wrapping.
  • Added the static @once indicator to force not wrapping expressions.

v0.15.0

12 Jan 06:18
2bb63f8
Compare
Choose a tag to compare

A lot of updates and tweaks since the last minor version:

  • Update SSR:
    • use async capable renderToString method
    • Provides a generator for script for event capture for progressive hydration
  • Update hydration:
    • Support multiple contexts (partial hydration)
    • Event capture and replay (progressive hydration)
  • Support for ternaries and binary operators in JSX templates
  • Better classList binding performance
  • Better handling of children in spreads
  • Pass props to render function in class components

v0.14.0

28 Oct 03:11
Compare
Choose a tag to compare

Change template cloning to support rehydration of SVG partials

v0.13.0

18 Oct 07:55
a8a2c93
Compare
Choose a tag to compare

Breaking Change - Removal of Explicit Binding "Parens" Syntax

The new heuristic for how bindings will be reactive will work as follows:

There are certain types of syntax that will never be reactive like function declarations, literal values.

// these bindings never need to be wrapped
<div onClick={() => setState({clicked: true})} name={"mydiv"} />

Similarly since reactivity requires access only function calls or property accesses can be reactive. So simple variables will never need to be wrapped

// also never needs to be wrapped
<div name={myName} maxlength={count * 2} />

So we can limit wrapping to only expressions that could be reactive like:

// wrap because they could be reactive
<div name={props.name} title={getTitle()} />

Also for Component props that take Components like fallback or children we will wrap any expression with a tag to allow deferred evaluation.

// these will be wrapped
<Show when={state.accepted} fallback={<Denied />}>
  <Accepted />
</Show>

What if you wish for these things to be static? Hoist the value access. Since normal variables aren't reactive just assign it to a variable. This is JSX so we have all the power of JavaScript at our side and do not need a special syntax.

const name = props.name;
// not wrapped as simple variable
<div name={name} />

v0.12.0

27 Sep 05:50
Compare
Choose a tag to compare

Hydration & SVG Support

This release adds experimental hydration support for Server Side Rendering and basic (non-namespaced) SVG support.

v0.11.0

18 Jul 08:30
Compare
Choose a tag to compare

Major Breaking Changes

This release removes several features by taking a fundamental architecture switch. Overall this is a huge simplification and code reduction.

Removing Control Flow

Instead of hard compiling Control Flows, the library is putting the work on Components in userland. This is infinitely more flexible and opens up different solutions to fit the library that uses it. It meant beefing up the core reconciler to be able to handle pretty much whatever gets thrown at it.

Fragments as Arrays

Document Fragments have this pesky characteristic of losing their child nodes. Using arrays is a must if you wish to retain references and pass them around. Which is necessary change if control flow is outside of the main library. This reduces the Node creation in many places, but it also means multi-nested fragments end up getting reconciled all at the same time on update. So there are some performance characteristic changes.

insert at entry

With these changes, the returned code from JSX is no longer guaranteed to be a DOM node. It may be an array or a function. In so if you use top-level child components or fragments your mount method should use insert to ensure different inputs are handled properly.

props.children changes

Now when you pass a single child you get a single value and multi-children are represented as arrays. This is consistent with how React handles children and allows a lot of different capacities for Component design. JSX element children by default are handled as dynamic and are lazily evaluated. Allowing for more powerful templating with Components.

Removing Custom Directives

Also, custom directives have been removed. They were a confusing alternative way to do things and did not play well with Typescript. Using forwardRef can achieve the same thing. The naming is under consideration and whether the library should be concerned with multiple instances on the same element (technically it works).

Better TypeScript support

Removal of Control Flow, Custom Directives, and consistent handling of JSX Children all improve TypeScript support.

Wide Open Future

While on the surface many of these changes may seem like detractors this widely opens up the ecosystem. Components or custom methods can benefit from all the performance capable here. The reactive system feeds into the renderer instead of being so closely entwined. It makes custom logic much simpler to write in the libraries without having to worry about markers and node ranges.

Look forward to updates in related Libraries over the coming weeks.