Upgrading
0.6.x to 0.7.x
XWidget 0.7 is a cleanup release: the XML namespaces move to the xwidget.dev domain,
configuration and generated schemas move into a .xwidget/ directory, routes and
values files get schema validation for the first time, and the APIs deprecated during
0.x are removed. Upgrade xwidget and xwidget_builder together, and update your IDE
plugin to 0.2.0 — older plugin versions look for the schema and config at their old
locations and lose completion and validation on upgraded projects.
Release contents
| Component | Version |
|---|---|
| xwidget | 0.7.0 |
| xwidget_builder | 0.7.0 |
| xwidget_el | 0.7.0 |
| VSCode extension | 0.2.0 |
| IntelliJ plugin | 0.2.0 |
Upgrade steps
- Set
xwidget: ^0.7.0andxwidget_builder: ^0.7.0inpubspec.yaml, then runflutter pub get. While the major version is 0,^0.6.0cannot resolve to 0.7 — the constraint must be updated by hand. - Run
dart run xwidget_builder:generate. The first run migratesxwidget_config.yamlandxwidget_cloud.yamlinto.xwidget/, writes the schemas and schema catalog there, and deletes the old root-level schema. -
Update the namespace in your fragment files:
# macOS (BSD sed); on Linux drop the '' after -i find resources/fragments -name '*.xml' -exec \ sed -i '' 's|http://www.appfluent.us/xwidget|https://xwidget.dev/fragments|g' {} +generatewarns with a count while legacy-namespace fragments remain. The runtime doesn't care about the namespace — this only affects IDE validation and completion. -
Add
xmlns="https://xwidget.dev/values"to the<resources>root of your values files, andxmlns="https://xwidget.dev/routes"to your<routes>file, to get their new schema validation. - Update the IDE plugin to 0.2.0. The VSCode extension rewrites its entry in
.vscode/settings.jsonautomatically on the first generate; IntelliJ needs nothing beyond the plugin update. - Replace any of the removed APIs below.
Removed APIs
| Removed | Replacement |
|---|---|
XWidget.navigatorKey |
XRouter.navigatorKey |
XWidget.xmlCacheEnabled |
none — caching is managed by Resources |
XWidget.registerControllerFactory<T> |
XWidget.registerControllerFactoryForName |
XWidget.clearXmlCache() |
Resources.instance.clearFragmentCache() |
XWidget.navigateToFragment() |
XRouter.navigateToFragment |
XWidget.pushFragment() |
XRouter.navigateToFragment |
MaterialStatePropertyOf |
WidgetStatePropertyOf |
<debug> tag |
none |
Other breaking changes
generateno longer takes--config; configuration is always read from.xwidget/xwidget_config.yaml.schema.targetis no longer configurable — the fragment schema is always written to.xwidget/fragments_schema.g.xsd. Aschema.targetin your config is ignored with a warning.<fragment>no longer forwards itsdependenciesScopeattribute to the child fragment as an inherited attribute. This matches what the docs always said; if a nested fragment relied on the leaked value, declaredependenciesScopeon it directly.
Downgrading from 0.7.x to 0.6.x
If you need to roll back after upgrading:
- Set
xwidget: ^0.6.0andxwidget_builder: ^0.6.0inpubspec.yamland runflutter pub get. Confirmpubspec.lockshows 0.6.x. - Move
.xwidget/xwidget_config.yamland.xwidget/xwidget_cloud.yamlback to the project root. - Delete the
.xwidget/directory. - Run
dart run xwidget_builder:generateto regenerate the root-level schema and Dart code. - Revert fragment namespaces to
http://www.appfluent.us/xwidget(reverse the find-and-replace from step 3 above), and remove thexmlnsyou added to values and routes files. - The VSCode extension detects the downgrade and restores its old schema registration automatically; IntelliJ needs nothing.
0.5.x to 0.6.x
XWidget 0.6 introduces a new cloud deployment model. Deployments are now immutable and channel-agnostic: every deploy of a version mints a numbered revision, and channels are pointers that select which revision they serve. Deploying stages a bundle; publishing makes it live. Promotion and rollback are both just publishing a chosen revision.
App code using CloudResources needs no changes — the constructor and its parameters
are unchanged.
Important
Both xwidget and xwidget_builder must be upgraded together to 0.6.x. This is a
coordinated cutover with the XWidget Cloud API: 0.5.x CLI versions are rejected by
the server with an upgrade notice. Apps built on 0.5.x keep serving previously
downloaded bundles but won't receive bundles deployed with the new model — ship an
app update on 0.6 to resume over-the-air updates.
Breaking Changes
xc cloud promote is replaced by publish and unpublish
xc cloud publish -c <channel> -v <version> -r <revision> points a channel at a
revision — covering what promote did, plus rollback. xc cloud unpublish removes a
channel's pointer without deleting anything. Update any CI scripts that call
xc cloud promote.
xc cloud deploy no longer takes --channel
Deploying is channel-less: it uploads the bundle and mints the next revision. The CLI
offers to publish afterward, or run xc cloud publish separately.
xc cloud deployment delete scopes changed
Deletion now targets the project: --version plus --revision deletes one revision,
--version alone deletes all of a version's revisions. The channel-based scopes are
gone — to stop serving a version on a channel, unpublish it instead. Revisions that
are live on any channel cannot be deleted until unpublished.
Version format is stricter about build metadata, looser about pre-releases
Build metadata must now be a plain number matching Flutter's build number
(1.2.0+42); values like +build.42 or +hotfix are rejected. Pre-release
identifiers (1.0.0-beta, 1.0.0-rc.1) are now accepted. The full version string,
including the build number, identifies the deployment — bumping the build number
starts a fresh revision lineage.
BundleCache interface changed
loadETag()/saveETag() are replaced by loadMetadata()/saveMetadata() using the
new BundleMetadata record (channel, version, revision, SHA-256, ETag). This only
affects custom BundleCache implementations — the built-in caches migrate
transparently, though the first launch after upgrading re-downloads the bundle once.
Analytics event schema changed
Events now report the full version string plus a revision dimension, replacing the
old version-number/metadata split. Requires the 0.2.x analytics server. Unsent events
queued on-device by a 0.5.x app are discarded during the upgrade.
Migration Steps
-
Update both dependencies:
-
Regenerate:
-
If you implemented a custom
BundleCache, migrate it toloadMetadata()/saveMetadata(). -
Update CI scripts that use
xc cloud promoteorxc cloud deploy --channelto the deploy/publish flow. -
Deploy and publish with the 0.6 CLI so your channels serve bundles under the new model.
0.4.x to 0.5.x
XWidget 0.5 restructures initialization around a generated registry and
a pluggable resource provider model. One call in main() replaces several,
and the resource layer becomes explicit and swappable.
Important
Both xwidget and xwidget_builder must be upgraded together to 0.5.x.
Generated code from 0.4.x is not compatible with xwidget 0.5.x.
Breaking Changes
XWidget.initialize() no longer takes fragmentsPath or valuesPath
Resource paths are now configured in xwidget_config.yaml and can be overridden per-provider
via the fragmentsPath and valuesPath constructor arguments on LocalResources and CloudResources.
New register parameter on XWidget.initialize()
Registration of generated components is now a single callback. The generator
emits registerXWidgetComponents() in lib/xwidget/generated/registry.g.dart that
calls the three per-component registrations and sets XWidget.config.
New resources parameter on XWidget.initialize()
Pass an explicit Resources instance (LocalResources or CloudResources) instead
of relying on implicit cloud activation via key parameters.
Cloud parameters removed from XWidget.initialize()
projectKey, storageKey, channel, and version are no longer accepted by initialize().
Configure them on CloudResources directly, or use LocalResources.withAnalytics() for
analytics without cloud-hosted resources.
xwidget_config.yaml resource paths moved to top level
The resources group is gone. fragmentsPath and valuesPath are now top-level keys.
Before:
After:
New generated output: registry.g.dart
Initialization is simpler in 0.5. What used to take three registration calls and a handful
of config parameters is now a single function you pass to XWidget.initialize().
Less boilerplate, less to get wrong, and the generator keeps it in sync with your config automatically.
The generator produces a fourth file alongside inflaters.g.dart, icons.g.dart,
and controllers.g.dart. It exports registerXWidgetComponents() — which registers inflaters,
icons, and controllers, and applies paths from your config to XWidget.config. It's
always regenerated — --only does not skip it.
Migration Steps
-
Update both dependencies:
-
Flatten
xwidget_config.yamlresource paths (remove theresources:group, promotefragmentsPathandvaluesPathto the top level). -
Regenerate:
This produces the new registry.g.dart alongside the existing generated files.
- Update
main(). If you were using the default 0.4 pattern:
Before:
```dart
import 'package:xwidget/xwidget.dart';
import 'xwidget/generated/inflaters.g.dart';
import 'xwidget/generated/icons.g.dart';
import 'xwidget/generated/controllers.g.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await XWidget.initialize(
fragmentsPath: 'resources/fragments',
valuesPath: 'resources/values',
);
registerXWidgetIcons();
registerXWidgetInflaters();
registerXWidgetControllers();
runApp(MyApp());
}
```
After:
```dart
import 'package:xwidget/xwidget.dart';
import 'xwidget/generated/registry.g.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await XWidget.initialize(register: registerXWidgetComponents);
runApp(MyApp());
}
```
The three per-component imports collapse to one. The three registration calls collapse into the register callback. Paths come from XWidget.config, which registerXWidgetComponents populates from your xwidget_config.yaml.
- If you were using cloud resources in 0.4 (passing
projectKey,storageKey,channel,versiontoinitialize()), move those to aCloudResourcesinstance:
Before:
```dart
await XWidget.initialize(
fragmentsPath: 'resources/fragments',
valuesPath: 'resources/values',
projectKey: '<project-key>',
storageKey: '<storage-key>',
channel: 'production',
version: '1.0.0',
);
```
After:
```dart
await XWidget.initialize(
register: registerXWidgetComponents,
resources: CloudResources(
projectKey: '<project-key>',
storageKey: '<storage-key>',
channel: 'production',
version: '1.0.0',
),
);
```
-
If you want cloud analytics but are keeping UI bundled in the app, use
LocalResources.withAnalytics: -
Test your app. Fragment inflation, controller resolution, and value lookups should work unchanged.
What did not change
- Fragment XML syntax, EL expressions, and tag semantics are unchanged.
- Generated inflater, icon, and controller code shapes are unchanged.
- The default paths (
resources/fragments,resources/values) are unchanged.
What's new in 0.5
- Hot reload of fragments and values — edit a fragment or value XML file and the running app updates without a restart. Requires an XWidget IDE plugin. See Hot Reload.
0.3.x to 0.4.x
XWidget 0.4.x fixes Dart 3.4 function type compatibility and simplifies the <builder> tag.
Important
Both xwidget and xwidget_builder must be upgraded together to 0.4.x.
Generated inflaters from 0.3.x are not compatible with xwidget 0.4.x.
Breaking Changes
nullable attribute removed from <builder> tag
The nullable attribute is no longer needed. It will be silently ignored if present
in existing fragments, but should be removed.
Before:
<PageView.builder>
<builder for="itemBuilder" vars="_,index" nullable="true">
<Container>
<Text data="${toString(index)}"/>
</Container>
</builder>
</PageView.builder>
After:
<PageView.builder>
<builder for="itemBuilder" vars="_,index">
<Container>
<Text data="${toString(index)}"/>
</Container>
</builder>
</PageView.builder>
Builder tag simplified
The <builder> tag no longer manages typed wrapper functions internally. Type
adaptation is now handled by the generated inflater via addFnArg. This change is
transparent — existing fragments work without modification (aside from removing
nullable). See builder for the updated reference.
Generated inflaters require regeneration
The inflater generator now emits addFnArg for all Function-typed constructor
parameters. You must regenerate inflaters after upgrading.
Migration Steps
-
Update both dependencies:
-
Regenerate inflaters:
-
Remove any
nullableattributes from<builder>tags in your fragments. -
Test your app — all builders should work without changes.
0.2.x to 0.3.0
XWidget 0.3.0 introduces cloud integration for server-driven UI delivery and analytics.
Breaking Changes
Resources.instance.loadResources() replaced with XWidget.initialize()
The old resource loading call has been replaced with a unified initialization method that handles resources, cloud configuration, and analytics setup in one call.
Before:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Resources.instance.loadResources('resources');
// register XWidget components
registerXWidgetIcons();
registerXWidgetInflaters();
registerXWidgetControllers();
runApp(MyApp());
}
After:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await XWidget.initialize(
fragmentsPath: 'resources/fragments',
valuesPath: 'resources/values',
);
// register XWidget components
registerXWidgetIcons();
registerXWidgetInflaters();
registerXWidgetControllers();
runApp(MyApp());
}
To enable cloud resources and analytics, add the cloud parameters:
await XWidget.initialize(
projectKey: '<your-project-key>',
storageKey: '<your-storage-key>',
channel: 'production',
version: '1.0.0',
);
See CloudResources for the current cloud integration documentation.
Logging dependency changed
Replaced package:logger/logger.dart with package:logging/logging.dart. If your
code references the logger directly, update your imports.
Minimum Dart SDK increased to 3.4
Update your pubspec.yaml SDK constraint:
Migration Steps
-
Update your dependencies:
-
Replace
Resources.instance.loadResources()withXWidget.initialize()in yourmain()function. -
Update any
package:loggerimports topackage:logging. -
Regenerate components:
-
Verify your Dart SDK constraint is
>=3.4.0.
0.1.x to 0.2.0
XWidget 0.2.0 updates the Flutter and Dart minimum version requirements.
Breaking Changes
- Increased Flutter version constraint from
>=1.17.0to>=3.10.0 - Increased Dart SDK constraint from
>=2.19.6to>=3.0.0 - Updated
xwidget_eldependency from 0.2.0 to 0.2.2 - Added support for
AssetManifest.binwith fallback to.jsonfor older Flutter versions
Migration Steps
-
Ensure your Flutter version is 3.10.0 or higher:
-
Update your dependencies:
-
Regenerate components:
0.0.x to 0.1.0
XWidget 0.1.0 separates development tools from the runtime into a dedicated
xwidget_builder package.
Breaking Changes
- Code generators and initializers moved to
xwidget_builder(dev dependency). - The
dart run xwidget:generatecommand becomesdart run xwidget_builder:generate. - The
dart run xwidget:initcommand becomesdart run xwidget_builder:init.
Migration Steps
-
Install the development tools as a dev dependency:
-
Regenerate components using the new command:
-
Update any scripts or CI pipelines that reference
xwidget:generateorxwidget:initto usexwidget_builder:generateandxwidget_builder:init.