Skip to content

Releases: localvoid/ivi

v4.0.0

04 Dec 05:28
Compare
Choose a tag to compare

Switch from Babel to TypeScript

New Template Compiler and Optimizer plugin is using TypeScript library to parse javascript. Switching to TypeScript as a parser library should reduce the number of dev dependencies in modern projects.

DOM Events Hoisting

DOM Events declared as an arrow function expression will be automatically hoisted to the outermost scope. E.g.

const C = component((c) => ([a, b]) => html`
  <div
   @a=${() => console.log(global);}
   @b=${() => console.log(c);}
   @c=${() => console.log(a + b + c);}
  />
`);

Will be transformed into:

const __ivi_hoisted_1 = () => console.log(global);;
const C = component((c) => {
  const __ivi_hoisted_2 = () => console.log(c);
  return ([a, b]) => html`
    <div
     @a=${__ivi_hoisted_1}
     @b=${__ivi_hoisted_2}
     @c=${() => console.log(a + b + c);}
    />
  `;
);

Component Render Function Hoisting

Render functions in simple components that has a pattern component(() => (...) => ..., ...) will be automatically hoisted to the outermost scope. E.g.

const C = component(
  (c) => ({ text }) => text,
  shallowEq,
);

Will be transformed into:

const __ivi_hoisted_1 = ({ text }) => text;
const C = component(
  (c) => __ivi_hoisted_1,
  shallowEq,
);

@ivi/tpl syntax is removed

  • @ivi/tpl and @ivi/htm packages are removed.
  • Template functions for HTML-like syntax are now part of the ivi package.

SSR/Hydration is removed

v4.0.0-beta.1

02 Dec 10:13
Compare
Choose a tag to compare
v4.0.0-beta.1 Pre-release
Pre-release
v4.0.0-beta.1

@ivi/htm 3.0.2

12 Sep 02:35
Compare
Choose a tag to compare

3.0.2

27 May 05:45
Compare
Choose a tag to compare
v3.0.2

3.0.2

v3.0.0

08 Apr 09:59
Compare
Choose a tag to compare
  • Server-Side Rendering and Client-Side Hydration
  • Reduced public API surface
  • New HTML-like template language

v2.0.0

14 Mar 09:36
Compare
Choose a tag to compare
Release v2.0.0

v2.0.0-alpha.0

13 Mar 10:17
Compare
Choose a tag to compare
  • Removed all experimental features.
  • Significantly reduced API, so it can be easily stabilized.
  • New data structures and algorithms for UI values.

v1.0.1

04 May 10:42
Compare
Choose a tag to compare

Bug Fixes

  • Fixed getDOMNode() returning null value when first non-null node in a fragment or TrackByKey operation doesn't have any DOM nodes.
  • Fixed event dispatching algorithm visiting more nodes than it is necessary.

v1.0.0

03 Apr 09:42
Compare
Choose a tag to compare

Components

Added second prop to components.

const Button = statelessComponent<{ id: string }, Op>((props, children) => (
  button("button", props, children)
));

Button({ id: "button-id" },
  "Click Me",
);

Custom areEqual function

const View = statelessComponent<number, [number, number]>(
  (a, b) => (
    a + b[0] + b[1]
  ),
  undefined,
  shallowEqualArray,
);
View(1, [2, 3]);

Dirty Checking / Observables

Dirty checking API were redesigned to improve support for use cases with coarse-grained observable graphs and
mutable data structures.

New API for dirty checking is composable and can be used in stateless components.

  • useSelect() hook were removed.
  • Added pull-based observables.
  • Context is reimplemented with observables and it is now way much cheaper to dirty check.

Examples

Computed Values (lazy evaluation)
const a = observable(1);
const b = observable(2);
const sum = computed(() => watch(a) + watch(b));
const A = statelessComponent(() => div(_, _, watch(sum)()));
Basic selectors with immutable state
const STATE = { value: 1 };
const A = component((c) => {
  const getValue = selector(() => STATE.value);
  return () => div(_, _, watch(getValue)());
});
Memoized selector with immutable state
const STATE = { a: 1, b: 2 };
const A = component((c) => {
  const getValue = selector((prev) => (
    prev !== void 0 && prev.a === STATE.a && prev.b === STATE.b ? prev :
      { a: STATE.a, b: STATE.b, result: STATE.a + STATE.b };
  ));
  return () => div(_, _, watch(getValue)());
});
Composition
const a = observable(1);
const A = component((c) => {
  const getValue = memo((i) => computed(() => watch(a) + i));
  return (i) => div(_, _, watch(getValue(i))());
});

Boolean DOM Attribute Values

Removed automagic conversion from boolean values to empty string. Correct attribute values should be specified
explicitly.

textContent="" Optimization

This optimization has a quite noticeable impact in popular benchmarks. But in real applications, use cases that would benefit from this optimization will work significantly faster by wrapping lists into a transient DOM node.

Deep State Tracking

Deep state tracking optimization were removed. It is one of those optimizations that improve performance in benchmarks, but make it worse in real applications.

This optimization worked by updating node state flags during stack unwinding. It saved information about node subtree, so we could skip dirty checking and unmounting for subtrees that didn't have any stateful components. In applications decomposed into small components there will be many stateful components used as leaf nodes, so instead of optimizing, it will make dirty checking and reconciliation algorithms slightly slower. Also, this optimization were adding a lot of complexity to the reconciliation algorithm.

Simplified track by key algorithm

Instead of returning LIS indices, nodes that are part of LIS are now marked in the input array.

Events

Stop Propagation

Synthetic event handlers do not propagate events anymore. To propagate events, event handler should return
DispatchEvent.Propagate value.

Move Events

Removed touch/mouse/pointer move events. Move event handlers usually attached when down event is triggered. To make sure that we don't lose any move events, we can't wait until next frame is rerendered, so move event handlers should be attached with native DOM api.

Server Side Rendering

Removed. Not interested in supporting this feature.

v0.27.1

08 May 06:18
Compare
Choose a tag to compare

Deep state flags propagation algorithm were redesigned to merge flags only when going through fragments and TrackByKey nodes. New algorithm also fixes some edge cases when deep state flags were kept assigned even when subtree no longer had this state.