Skip to content

Latest commit

 

History

History
292 lines (212 loc) · 13.2 KB

File metadata and controls

292 lines (212 loc) · 13.2 KB

Migrating from previous versions

FASTGlobal version tracking (v2 → v3)

Removed API

Removed Replacement
FAST.versions No replacement. Multiple FAST versions on the same page are unsupported in v3.

Removed configuration

Removed Replacement
fast-kernel="share" / fast-kernel="share-v2" / fast-kernel="isolate" No replacement. FAST now uses a single shared kernel contract, and multiple FAST versions on the same page are unsupported.

Migration steps

  1. Remove any runtime checks that read FAST.versions.
  2. Fix duplicate FAST installs in your bundler or dependency graph instead of relying on version tracking at runtime.
  3. Remove any fast-kernel script attributes. They no longer affect FAST initialization.

Native globalThis requirement (v2 → v3)

Changed behavior

  • Native globalThis required: @microsoft/fast-element no longer installs a globalThis polyfill as a side effect. The package only keeps the requestIdleCallback / cancelIdleCallback fallback for environments that still lack those APIs.

Migration steps

  1. Verify that the browsers and JS runtimes you support provide native globalThis.
  2. If you still target an older runtime without globalThis, load that polyfill before importing @microsoft/fast-element.

Declarative HTML moved into fast-element (v3)

Declarative HTML APIs now ship from @microsoft/fast-element instead of the removed @microsoft/fast-html package.

Import changes

Before After
@microsoft/fast-html @microsoft/fast-element/declarative.js
@microsoft/fast-html/utilities.js @microsoft/fast-element/declarative/utilities.js

Migration steps

  1. Update declarative runtime imports to @microsoft/fast-element/declarative.js.
  2. Update declarative utility imports such as deepMerge to @microsoft/fast-element/declarative/utilities.js.
  3. Import core FAST Element helpers from focused entrypoints such as @microsoft/fast-element/attr.js, @microsoft/fast-element/observable.js, and @microsoft/fast-element/template.js. The root @microsoft/fast-element export now only provides FASTElement.
  4. Keep declarative APIs on @microsoft/fast-element/declarative.js; they are still separate from the root export surface.

Export path cleanup (v3)

Optional binding helpers remain on their dedicated public sub-entrypoints, and hydration utilities now live on @microsoft/fast-element/hydration.js:

  • @microsoft/fast-element/binding/two-way.js
  • @microsoft/fast-element/binding/signal.js
  • @microsoft/fast-element/hydration.js

Removed exports

Import Replacement
@microsoft/fast-element/testing.js No public replacement
@microsoft/fast-element/element-hydration.js @microsoft/fast-element/hydration.js
@microsoft/fast-element/install-element-hydration.js No replacement needed
@microsoft/fast-element/install-hydratable-view-templates.js No replacement needed
@microsoft/fast-element/metadata.js No public replacement
@microsoft/fast-element/pending-task.js No public replacement

Migration steps

  1. Move attr, observable, html, css, and other helpers off the root @microsoft/fast-element barrel onto focused subpaths.
  2. Replace @microsoft/fast-element/element-hydration.js with @microsoft/fast-element/hydration.js.
  3. Remove any direct imports from metadata.js, testing.js, pending-task.js, install-element-hydration.js, or install-hydratable-view-templates.js.
  4. Keep optional binding helpers on their dedicated binding/* subpaths.

Declarative event handler e removal (v3)

Removed behavior

Removed Replacement
Bare e event arguments in declarative event handlers $e
TemplateParser.hasDeprecatedEventSyntax No replacement

Only $e and $c are reserved event handler arguments in declarative templates. Bare e now resolves like any other binding path on the current data source.

Migration steps

  1. Replace declarative event bindings such as @click="{handleClick(e)}" with @click="{handleClick($e)}".
  2. Remove any TemplateParser.hasDeprecatedEventSyntax checks or warnings from custom tooling.

Prerendered Content Optimization (v2 → v3)

Removed exports

Export Replacement
HydratableElementController ElementController (prerendered path built in)
HydrationControllerCallbacks ElementHydrationCallbacks via ElementController.configHydration()
needsHydrationAttribute ElementController.isPrerendered
deferHydrationAttribute Template-pending guard in ElementController.connect()

Removed side-effect imports

Import Replacement
@microsoft/fast-element/install-element-hydration.js No replacement needed — prerendered path is built into ElementController
@microsoft/fast-element/install-hydratable-view-templates.js No replacement needed — ViewTemplate.hydrate() is built into the template runtime

@microsoft/fast-element/declarative.js still exposes declarative-only APIs, but it no longer patches hydration behavior through installer side effects.

Changed behavior

  • attributeChangedCallback during upgrade: When isPrerendered is true and the element has not yet connected, attribute change callbacks are suppressed. After connection, all attribute changes are processed normally.
  • connect() with deferred template: When templateOptions is "defer-and-hydrate" and no template is available, connect() returns early automatically. The Observable subscription on "template" retriggers connection when the template arrives. No defer-hydration attribute is needed.
  • Binding evaluation with existing shadow root: When an existing shadow root is detected, attribute and booleanAttribute bindings skip their initial DOM update. All other binding types (event, content, property, tokenList) run normally.

New APIs

  • ElementController.isPrerendered (Promise<boolean>): Resolves to true after prerendered content has been hydrated, or false when the component is client-side rendered. Component authors can await this to know when the element is fully interactive.
  • ViewController.isPrerendered (Promise<boolean> | undefined): Available to custom directives. Resolves to true when the view's content was prerendered, false otherwise.

Migration steps

  1. Remove HydratableElementController.install() calls.
  2. Remove import "@microsoft/fast-element/install-element-hydration.js" and import "@microsoft/fast-element/install-hydratable-view-templates.js" side-effect imports.
  3. Replace element.$fastController instanceof HydratableElementController checks with await element.$fastController.isPrerendered.
  4. Remove defer-hydration and needs-hydration attributes from server-rendered markup.

Hydration Marker Format (v3)

Changed format

The hydration markers embedded in SSR output have been simplified from verbose, index-embedded comment markers to compact, data-free sequential markers.

Comment markers

Marker type Old format New format
Content binding start <!-- fe-b$$start$$<index>$$<scopeId>$$fe-b --> <!--fe:b-->
Content binding end <!-- fe-b$$end$$<index>$$<scopeId>$$fe-b --> <!--fe:/b-->
Repeat item start <!-- fe-repeat$$start$$<itemIndex>$$fe-repeat --> <!--fe:r-->
Repeat item end <!-- fe-repeat$$end$$<itemIndex>$$fe-repeat --> <!--fe:/r-->
Element boundary start <!-- fe-eb$$start$$<elementId>$$fe-eb --> <!--fe:e-->
Element boundary end <!-- fe-eb$$end$$<elementId>$$fe-eb --> <!--fe:/e-->

Attribute binding markers

Old format New format
data-fe-b="0 1 2" (space-separated indices) data-fe="N" (binding count)
data-fe-b-0 (enumerated, one per factory) data-fe="N"
data-fe-c-0-3 (compact, start index + count) data-fe="N"

Removed APIs

Export Replacement
HydrationMarkup.contentBindingStartMarker(index, scopeId) HydrationMarkup.contentBindingStartMarker()
HydrationMarkup.contentBindingEndMarker(index, scopeId) HydrationMarkup.contentBindingEndMarker()
HydrationMarkup.isContentBindingStartMarker(data) HydrationMarkup.isContentBindingStartMarker(data) (unchanged signature, new implementation)
HydrationMarkup.isContentBindingEndMarker(data) HydrationMarkup.isContentBindingEndMarker(data) (unchanged signature, new implementation)
HydrationMarkup.parseAttributeBinding(element) HydrationMarkup.parseAttributeBindingCount(element)
HydrationMarkup.parseRepeatStartMarker(data) HydrationMarkup.isRepeatViewStartMarker(data)
HydrationMarkup.parseRepeatEndMarker(data) HydrationMarkup.isRepeatViewEndMarker(data)
HydrationMarkup.parseElementBoundaryStartMarker(content) HydrationMarkup.isElementBoundaryStartMarker(node)
HydrationMarkup.parseElementBoundaryEndMarker(content) HydrationMarkup.isElementBoundaryEndMarker(node)

Impact

This is a breaking change for SSR output format. Any system that produces or parses hydration markers must be updated to use the new format. The @microsoft/fast-build Rust crate and WASM binary have been updated accordingly.

  • Marker parsing uses string equality checks (data === "fe:b") instead of regex
  • Start/end pairing uses balanced depth counting instead of embedded IDs
  • The hydration walker uses a sequential factory pointer instead of index-based lookup
  • SSR and client versions must match — mixing old SSR output with new client code (or vice versa) will fail

Async define/compose/register API (v3)

Removed APIs

Removed Replacement
FASTElement.defineAsync() FASTElement.define() (now returns Promise<TType>)
FASTElementDefinition.composeAsync() FASTElementDefinition.compose() (now returns Promise<FASTElementDefinition>)
FASTElementDefinition.registerAsync() FASTElementDefinition.register() (same Promise<Function> return type)

Changed behavior

  • FASTElement.define() now returns Promise<TType>. When a template is provided at definition time, the Promise resolves immediately. When templateOptions is "defer-and-hydrate" and no template is provided, the Promise resolves after a template is supplied (e.g. via <f-template>).
  • FASTElement.compose() now returns Promise<FASTElementDefinition>. The Promise always resolves immediately.
  • FASTElementDefinition.compose() now returns Promise<FASTElementDefinition>. The Promise always resolves immediately.
  • @customElement decorator calls define() internally but does not return the Promise (fire-and-forget). For complete definitions with a template, the element is registered via a microtask.

Migration steps

  1. Replace defineAsync() calls with define():

    // Before
    MyElement.defineAsync({
        name: "my-element",
        templateOptions: "defer-and-hydrate",
    });
    
    // After
    MyElement.define({
        name: "my-element",
        templateOptions: "defer-and-hydrate",
    });
  2. Replace composeAsync() calls with compose() and add await:

    // Before
    const def = await FASTElementDefinition.composeAsync(MyElement, name);
    
    // After
    const def = await FASTElementDefinition.compose(MyElement, name);
  3. Replace registerAsync() calls with register():

    // Before
    const el = await FASTElementDefinition.registerAsync(name);
    
    // After
    const el = await FASTElementDefinition.register(name);
  4. Add await to compose() calls that chain .define():

     // Before
     FASTElementDefinition.compose(MyElement, options).define();
    
     // After
     (await FASTElementDefinition.compose(MyElement, options)).define();

Dynamic stylesheet behaviors (v3)

Removed API

Removed Replacement
ElementStyles.withBehaviors() Move the runtime condition into the element and call this.$fastController.addStyles() / this.$fastController.removeStyles() directly.
ElementStyles.behaviors Move any runtime behavior out of the stylesheet and into the element or controller lifecycle.
CSS bindings in css (for example ``css`color: ${x => x.color}```) Move the dynamic value into the element and update classes, attributes, or inline styles from element code.
CSSDirective.createCSS(add) Update directives to implement createCSS() and return only static CSS content.

Changed behavior

  • css and css.partial() no longer compose HostBehaviors.
  • css no longer accepts function or Binding interpolations.
  • ElementStyles is now a fully static style container.

Migration steps

  1. Keep the conditional ElementStyles in a separate css value.
  2. Move the external listener or condition (for example matchMedia() or an app event subscription) into the element lifecycle.
  3. Call this.$fastController.addStyles(styles) when the condition is active and this.$fastController.removeStyles(styles) when it is inactive or during cleanup.
  4. If you previously interpolated bindings or behavior-producing directives into css, replace them with element state and standard DOM or controller updates.