Skip to content

v0.4.0

Choose a tag to compare

@dannote dannote released this 03 Oct 08:22
· 86 commits to master since this release

Breaking changes

  • Require Elixir 1.19, vize 0.16.1, OXC 0.18, QuickBEAM 0.11.2, and Volt 0.19.4, dropping the older versions 0.3.4 also accepted. Volt is now a required dependency, used at compile time only. Building vize from source requires Rust 1.95.
  • The browser code is TypeScript in priv/ts, exported through the package's package.json: import patchLiveSocket from phoenix_vapor and getHybridHooks from phoenix_vapor/hybrid. priv/js/hybrid-bridge.js is gone, and patchLiveSocket was not in the Hex package before.
  • A hybrid module exports __mount(el, bridge, props), which returns applyProps/1 and unmount/0 for that instance, in place of the module-level __applyProps, __setBridge, and __unmount. Hybrid wrappers are phx-update="ignore", and their server HTML has no phx-* event attributes.
  • Full-runtime LiveViews take a :globals option mapping each package their bundle provides to its global, such as %{"reka-ui" => "RekaDialog"}. Only vue is mapped by default; reka-ui and @vueuse/* were hardcoded for the demo's bundle.
  • Reactive mount/3 assigns only the URL params the template reads.
  • An unknown :runtime option raises at compile time instead of falling back to detecting the mode.

Added

  • A page can mount the same hybrid component several times. Each mount has its own props and bridge.
  • defineProps is read in its object and TypeScript forms as well as as an array, using Vize's script analysis.
  • Guides for getting started and for each mode, and a cheatsheet.

Changed

  • Templates compiled into a module parse their expressions and compute fingerprints at compile time. Rendering a 500-row v-for went from 55 ms to 0.5 ms.
  • vize 0.16's vapor_split reports events and v-model as data, and PhoenixVapor renders them as phx-* attributes itself.
  • The full runtime reads its bundle once and caches it until the file changes, instead of reading it on every mount.
  • @vue/reactivity for Reactive mode is pinned in priv/ts/package.json and vendored by mix volt.priv.vendor, replacing a hand-copied build of 3.5.30.
  • Slot positions for direct DOM patching come from the browser's HTML parser instead of a hand-written one, which mishandled > inside attribute values.
  • Scoped CSS uses the scope ID from Vize.SFC.scope_id/2, passed to Vize, instead of one read back out of the compiled CSS.

Fixed

  • Hybrid server actions threw in the browser: they referenced __serverProps and triggerRef, which the generated module never defined.
  • Hybrid components re-render when LiveView sends new props. Only the first render used them.
  • Hybrid components keep working across server updates, and a prop change sends only the new props JSON instead of the whole tree.
  • Hybrid components get every prop the template or client-side code reads. Props used only in the template were left out, so they rendered empty once the client mounted.
  • Server actions send the values of refs and computeds instead of serialized Ref objects.
  • Before the client mounted, LiveView acted on hybrid phx-click attributes such as phx-click="pick(c)" and pushed the handler source to the server as an event name.
  • The hybrid bridge applies the initial props before mounting and unmounts the component when the hook is destroyed.
  • A QuickBEAM runtime leaked on every hybrid render.
  • Rendering never creates atoms. Reactive mount/3 turned every URL param into an atom, and change tracking, component props, v-for variables, and hybrid props and computeds converted names at render time, which PhoenixVapor.render/2 does for templates built at runtime.
  • Computeds may read computeds declared after them, and block-bodied computeds work in Reactive mode.
  • Expressions with methods that aren't evaluated in Elixir fall back to QuickBEAM. list.filter(fun) and list.map(fun) with a function reference returned the list unchanged, and methods such as padStart rendered nothing.
  • Scope and Vapor metadata attributes go after the root tag's name. They were inserted before the first >, which could be inside an attribute value such as title="a > b".
  • A <script lang="elixir"> block is left out of the hybrid client module, even after <script setup>.
  • Full-runtime LiveViews raise the JavaScript error from mount and events instead of a MatchError.
  • The Hex package contains only PhoenixVapor's own JavaScript. It included all of priv/js, so a locally built bundle such as reka-dialog.js would have been published.