Core migration from 2.x to 3.x
FAST Element 3.x focuses the client runtime on browser Window environments and
removes several APIs that previously supported alternate registration,
hydration, and declarative HTML flows. Complete this core migration for every
application, then follow the add-on migration path that matches the extra
functionality your application uses.
| Migration path | Use it when |
|---|---|
| Core FAST Element migration | You author components with FASTElement, html, css, define(), compose(), @attr, FAST, or ElementStyles.withBehaviors(). |
| Hydration and SSR migration | You server-rendered FAST components, emitted FAST hydration markers, used @microsoft/fast-ssr, or installed FAST hydration helpers. |
| Declarative HTML migration | You used the removed @microsoft/fast-html package, <f-template>, RenderableFASTElement, TemplateElement, or declarative map options. |
Audit your application
Before changing code, review your application for removed APIs, changed imports, and add-on migration triggers.
| Area | Look for | What to update |
|---|---|---|
| Element registration | compose(), defineAsync(), composeAsync(), registerAsync() |
Replace owned element registration with subclass define(). Use fastElementRegistry.whenRegistered() only when code needs to wait for a tag name owned elsewhere. |
| FAST global and kernel usage | globalThis.FAST, FAST.versions, FAST.getById(), KernelServiceId, or fast-kernel script attributes |
Import FAST services directly from @microsoft/fast-element and remove runtime version/kernel configuration. |
| Styles | ElementStyles.withBehaviors(), ElementStyles.behaviors, CSS bindings inside css, or behavior-producing CSS directives |
Move runtime style decisions into element/controller lifecycle code and add or remove styles as state changes. |
| Boolean attributes | FAST boolean-mode attributes that render literal string values such as "false", or direct calls to booleanConverter |
Omit boolean attributes to represent false. Review direct converter usage because 3.x follows native HTML boolean attribute semantics. |
| Hydration and SSR | @microsoft/fast-ssr, HydratableElementController, hydration marker inspection, defer-hydration, needs-hydration, or hydration side-effect imports |
Complete the Hydration and SSR migration after this core migration. |
| Declarative HTML | @microsoft/fast-html, <f-template>, RenderableFASTElement, TemplateElement, TemplateOptions, templateOptions, or declarative attributeMap / observerMap options |
Complete the Declarative HTML migration after this core migration. |
Recommended upgrade order
- Replace
compose(),defineAsync(), andcomposeAsync()registration flows with subclassdefine(). - Update imports that moved to changed public package paths.
- Move dynamic stylesheet behavior out of
cssand into the element or controller lifecycle. - Update your package versions so all FAST packages are on matching 3.x versions. Do not mix old SSR output or declarative runtime code with the 3.x client.
- If you server-render or hydrate FAST components, complete the Hydration and SSR migration.
- If you use declarative HTML, complete the Declarative HTML migration.
- Rebuild and manually verify the upgraded components in the browser.
Runtime requirements
FAST Element 3.x targets client-side browser Window runtimes. Do not import or
run the FAST Element client runtime in workers, server-side JavaScript runtimes,
or other non-window hosts. Server rendering tools may emit HTML, but hydration
and client rendering run in the browser window where DOM, Custom Elements,
Shadow DOM, and requestAnimationFrame are available.
FAST Element 3.x also no longer installs a globalThis polyfill and no longer
installs or depends on a requestIdleCallback / cancelIdleCallback fallback.
Load a globalThis polyfill before importing FAST only if you still support an
older browser that lacks it. You do not need to polyfill requestIdleCallback
or cancelIdleCallback for FAST Element itself.
See the package migration guide for the complete native globals and scheduler migration steps.
Package and path exports
The root @microsoft/fast-element import remains supported. Update only the
public imports that moved from older nested paths to focused package paths.
| Look for | Use | Named exports |
|---|---|---|
@microsoft/fast-element/binding/two-way.js |
@microsoft/fast-element/two-way.js |
twoWay, TwoWayBindingOptions, TwoWaySettings |
@microsoft/fast-element/binding/signal.js |
@microsoft/fast-element/signal.js |
signal, Signal |
Older nested children directive imports |
@microsoft/fast-element/children.js |
children, ChildrenDirective, ChildListDirectiveOptions, ChildrenDirectiveOptions, SubtreeDirectiveOptions |
Older nested ref directive imports |
@microsoft/fast-element/ref.js |
ref, RefDirective |
Older nested repeat directive imports |
@microsoft/fast-element/repeat.js |
repeat, RepeatBehavior, RepeatDirective, RepeatOptions |
Older nested slotted directive imports |
@microsoft/fast-element/slotted.js |
slotted, SlottedDirective, SlottedDirectiveOptions |
Older nested when directive imports |
@microsoft/fast-element/when.js |
when |
Hydration and declarative HTML import changes are covered in their add-on migration pages. See the Path Exports reference for the full current package export list.
Element registration
FASTElement.compose() removed
FASTElement.compose() and subclass compose() calls have been removed from the
public authoring API. If your code immediately registered the element after
composing it, call define() on the subclass instead.
// Before
MyElement.compose({
name: "my-element",
template,
styles,
}).define();
// After
MyElement.define({
name: "my-element",
template,
styles,
});
defineAsync() and composeAsync() removed
FASTElement.defineAsync() and FASTElementDefinition.composeAsync() have been
removed. Use subclass define() instead. The returned Promise is available
only for code that explicitly needs to observe registration completion.
// Before
MyElement.defineAsync({
name: "my-element",
template,
styles,
});
// After
MyElement.define({
name: "my-element",
template,
styles,
});
Replace FASTElementDefinition.compose() calls that chain .define() the same
way:
// Before
FASTElementDefinition.compose(MyElement, options).define();
// After
MyElement.define(options);
If old code used registerAsync() only to wait for a custom element tag name to
become available, replace that wait with fastElementRegistry.whenRegistered().
Use subclass define() when the code owns the element definition.
See the
package migration guide
for complete define(), compose(), and register() API mappings.
Registry lookups
The static FASTElementDefinition.isRegistered map is no longer public. Import
fastElementRegistry from @microsoft/fast-element/registry.js instead.
import { fastElementRegistry } from "@microsoft/fast-element/registry.js";
const definition = await fastElementRegistry.whenRegistered("my-element");
Use fastElementRegistry.getByType(type) or
fastElementRegistry.getForInstance(instance) when you already have a
constructor or element instance.
FAST global changes
globalThis.FAST removed
The FAST object is no longer attached to globalThis. It is now a
module-scoped export from @microsoft/fast-element.
// Before
globalThis.FAST.addMessages({ ... });
// After
import { FAST } from "@microsoft/fast-element";
FAST.addMessages({ ... });
FAST.versions and fast-kernel modes removed
FAST.versions has been removed and multiple FAST versions on the same page are
unsupported in 3.x. Remove runtime checks that read FAST.versions and fix
duplicate FAST installs in your bundler or dependency graph instead.
The fast-kernel="share", fast-kernel="share-v2", and
fast-kernel="isolate" script attributes no longer affect FAST initialization.
Remove them during migration.
FAST.getById() and kernel service IDs removed
The FAST.getById(id, initializer) slot registry has been removed. Kernel
services such as the update queue and observable system are resolved through
standard ES module imports. Remove FASTGlobal and KernelServiceId type usage
and import the service APIs directly.
Debug entrypoint
@microsoft/fast-element/debug.js no longer configures FAST just by being
imported. Call enableDebug() explicitly instead.
// Before
import "@microsoft/fast-element/debug.js";
// After
import { enableDebug } from "@microsoft/fast-element/debug.js";
enableDebug();
If you want debug behavior enabled automatically, keep using the root package
development export or the debug rollup bundle.
CSS and styles
css moved to @microsoft/fast-element
css, CSSTemplateTag, and CSSValue are imported from
@microsoft/fast-element. Other style APIs such as ElementStyles,
CSSDirective, cssDirective, ComposableStyles, HostBehavior,
HostController, StyleStrategy, and StyleTarget are also available from the
root package export.
import { css, ElementStyles } from "@microsoft/fast-element";
Dynamic stylesheet behaviors removed
ElementStyles.withBehaviors(), ElementStyles.behaviors, CSS bindings inside
css, and behavior-producing CSS directives have been removed. ElementStyles
is now a static style container. Move runtime conditions into the element or
controller lifecycle, then add and remove styles as conditions change.
import { css, FASTElement } from "@microsoft/fast-element";
const compactStyles = css`
:host {
gap: 4px;
}
`;
class MyElement extends FASTElement {
#media = globalThis.matchMedia("(max-width: 600px)");
connectedCallback() {
super.connectedCallback();
this.#media.addEventListener("change", this.#syncCompactStyles);
this.#syncCompactStyles();
}
disconnectedCallback() {
this.#media.removeEventListener("change", this.#syncCompactStyles);
this.$fastController.removeStyles(compactStyles);
super.disconnectedCallback();
}
#syncCompactStyles = () => {
if (this.#media.matches) {
this.$fastController.addStyles(compactStyles);
} else {
this.$fastController.removeStyles(compactStyles);
}
};
}
If you previously interpolated bindings or behavior-producing directives into
css, replace them with element state and standard DOM, class, attribute,
inline-style, or controller updates.
See the package migration guide for detailed dynamic stylesheet migration steps.
Attribute and converter behavior
booleanConverter now matches native HTML boolean attributes
@attr({ mode: "boolean" }) and booleanConverter now match how the platform
treats native boolean attributes such as disabled and required:
- Attribute to property is presence-based:
setAttribute(name, anyString)sets the property totrue; onlyremoveAttribute(name)makes itfalse. - Property to attribute uses
Boolean()coercion: any JavaScript truthy value adds the attribute with value""; any falsy value removes it.
The main 2.x to 3.x difference is that setAttribute(name, "false") now resolves
to property true.
<my-element my-bool="false"></my-element>
// 2.x
element.myBool === false;
// 3.x
element.myBool === true;
booleanConverter 2.x to 3.x result differences:
| Call | 2.x | 3.x |
|---|---|---|
fromView("false") |
false |
true |
fromView("") |
true |
false |
fromView(NaN) |
true |
false |
toView(true) or any truthy value |
"true" |
"" |
toView(false) or any falsy value |
"false" |
null |
For mode: "boolean", FAST writes attributes through presence-based boolean
attribute logic and reads them as value !== null. The converter methods still
apply to property assignment, explicit converter calls, and booleanConverter
paired with mode: "reflect".
Migration steps:
- Audit boolean-mode attributes for the literal string
"false"in templates or SSR HTML. Omit the attribute to express the falsy state. - Audit code that calls
booleanConverter.toView()directly or pairsbooleanConverterwithmode: "reflect". - If you need a tri-state attribute that preserves an explicit
"false"string value, usenullableBooleanConverterwithmode: "reflect"instead ofmode: "boolean".
Core exports added in 3.x
| Export | Package | Description |
|---|---|---|
ElementController.isPrerendered |
@microsoft/fast-element |
Promise<boolean> that resolves true when an element had Declarative Shadow DOM at connect time. |
ElementController.isHydrated |
@microsoft/fast-element |
Promise<boolean> that resolves true only when hydration ran successfully. |
ViewController.isPrerendered |
@microsoft/fast-element |
Promise<boolean> for custom directives that need prerender detection. |
ViewController.isHydrated |
@microsoft/fast-element |
Promise<boolean> for custom directives that need hydration status. |
fastElementRegistry |
@microsoft/fast-element/registry.js |
Public registry lookup helper for registered FAST element definitions. |
Hydration-specific exports are covered in the Hydration and SSR migration, and declarative HTML exports are covered in the Declarative HTML migration.