Version 0.21.0
Release notes and breaking changes.
TLDR / Overview
Version 0.21.0 comes with a major overhaul of the component syntax, making it easier and even more familiar to write components. It also ships a new jaspr migrate command for automatic migrations to new versions, and adds support for five new css properties.
TL;DR
- Simplified Build Methods: All component
buildmethods now return a singleComponentinstead of anIterable<Component>, making code more concise and Flutter-like. - Unified Component Factories: New factory constructors on the core
Componentclass replaceDomComponent(),Text(), andFragment()for a more consistent API. - Automatic Migration Command: The CLI now includes a
jaspr migratecommand to help you automatically update your codebase for breaking changes. - Improved Base Handling: The
baseparameter of theDocument()component can now be set tonullto suppress the<base>element. - Expanded CSS Support: Eight new CSS properties are now available for more flexible styling:
all,aspectRatio,appearance,justifyItems,justifySelf,alignContent,filter, andbackdropFilter.
Additionally, a new version of the Jaspr VSCode extension was released that contains a major improvement to the developer experience. Read more in the Extension Release Notes.
Build Method Improvement
All component build methods now return a single Component instead of an Iterable<Component>. This includes:
-
The
build()methods ofStatelessComponentandStatefulComponentsState:@override Iterable<Component> build(BuildContext context) sync* { yield ... Component build(BuildContext context) { return ... } -
The
builderparameter ofBuilder,ListenableBuilder,FutureBuilder,StreamBuilderandAsyncBuilder, e.g.:return Builder( builder: (context) sync* { yield ... builder: (context) { return ... } ); -
The
build()method ofAsyncStatelessComponent:Stream<Component> build(BuildContext context) async* { yield ... Future<Component> build(BuildContext context) async { return ... }
Migration
After upgrading Jaspr CLI to 0.21.0, you can use the jaspr migrate command to automatically migrate your components to the new build method signature.
The automatic migration will be able to migrate most of your components (90% to 99%).
In case you need or want to manually migrate single components to the new build method, migrating is straightforward and in most cases trivial:
- Change the method signature to
Component build(BuildContext context)for normal components/builders, andFuture<Component> build(BuildContext context)for async components/builders. - For build methods
yielding a single child, simply remove thesync*modifier andreturnthat child intead. - For build methods
yielding multiple children, return aFragmentand provide the children as aList<Component>.
Reason for the Change
We noticed that in practice most components already only return/yield a single child component. For those components, changing to a single child build method is the natural choice.
Additionally, this change allows to discontinue the special sync*/yield syntax used before and instead aligns more closely with Flutter's widget syntax. And while this syntax is not officially deprecated, it is not really recommended by the Dart team as it lacks certain performance optimizations (especially in the js compiler) and doesn't support newer language features (e.g. no null-aware yield).
Lastly, changing to single-child components allowed for major simplifications and optimizations of the internal framework code of Jaspr, resulting in a less-complex, easier to maintain and more performant implementation.
Foundational Component Factories
New factory constructors on the core Component class have been introduced and replace the separate DomComponent(), Text() and Fragment() constructors:
return DomComponent(tag: 'div', ...);
return Component.element(tag: 'div', ...);
return Text("...");
return Component.text("...");
return Fragment(children: [...]);
return Component.fragment([...]);
The DomComponent, Text and Fragment classes still exist in the implementation, but cannot be created directly anymore.
Additionally, a new Component.empty() convenience constructor was added to create an empty fragment.
The html utility methods (div(), button() etc.) still exist and are still recommended over using the Component.element constructor. Same goes for the text() method and the new fragment() method for consistency, both of which are now also part of the 'prefer_html_methods' lint of jaspr_lints.
Migration
After upgrading Jaspr CLI to 0.21.0, you can use the jaspr migrate command to automatically migrate your components to the new factory API.
The automatic migration will be able to migrate 99% of your components.
In case you need or want to manually migrate single components to the new factory API, migrating is straightforward and in most cases trivial:
- Replace any
DomComponent()invocation withComponent.element(). - Replace any
Text()invocation withComponent.text(). - Replace any
Fragment()invocation withComponent.fragment()(orComponent.empty()if it is an empty fragment).
Reason for the Change
This change was made to improve the API in terms of concistency and discoverability.
It is also designed to work well with the new dot shorthand syntax introduced in Dart 3.10. This allows you to omit the type name (in this case Component) when accessing a static member in a context where that type is expected (in this case e.g. a component's build method or children parameter).
It also better encapsulates the concept that Jaspr has (different to Flutter) a fixed set of foundational component types (instead of allowing to write any number of custom render objects), and thus better aligns with the internal implementation.
In real-world use we don't expect this to make much of a difference, as most Jaspr code should use the HTML utility methods anyways.
New Migrate Command
The CLI will include a new migrate command meant for helping with the migration of breaking changes in new versions. This will not only be used for the Build Method Change and Component Factories Change of this release, but also for any future change that allows for automatic migration.
Using the command is straightforward and follows the same style as the dart fix command:
- Running
jaspr migratewith no options will check only show which migrations are available for the currently used Jaspr version, e.g. Build Method Migration for version 0.21.0 and newer. - Running
jaspr migrate --dry-runwill compute and print all proposed migrations, but makes no changes to the code. - Running
jaspr migrate --applywill compute, print and apply all migrations.

Base Handling
The base parameter of the Document() component can now be set to null, which causes the <base> head element to not be rendered. Previously this defaulted to / even when explicitly set to null. The default when not specifying the parameter is still /.
When setting to null, the script src path of the generated client script is now corrected and does not produce an error.
There is no migration needed, as the behavior for normal usage is still the same.
New CSS Properties
The following css properties have been added to Styles() and css.styles():
// For resetting default styles.
All all
// For box sizing and layout.
AspectRatio aspectRatio
Appearance appearance
// For flexbox and grid layouts.
JustifyItems justifyItems
JustifySelf justifySelf
AlignContent alignContent
// For applying graphical effects like blur or color shift.
Filter filter
Filter backdropFilter
-
JustifyItems,JustifySelfandAlignContentare enums with values likeJustifyItems.center,JustifySelf.startorAlignItems.spaceAround. -
Filterdefines several filter methods likeFilter.blur(8.px),Filter.hueRotate(90.deg),Filter.opacity(0.5)orFilter.none.

