☰
FAST HTML 迁移指南:从 `@microsoft/fast-html` v1-alpha 到 v1 的完整升级路径
2026/9/25 12:33:39 网站建设 项目流程
  • 前端
  • UI组件

【免费下载链接】fast

The adaptive interface system for modern web experiences.

项目地址:https://gitcode.com/gh_mirrors/fa/fast
点击查看免费下载

本文基于 packages/fast-element/docs/migration/fast-html.md 编写,全面讲解从@microsoft/fast-htmlv1-alpha 迁移到 v1 时涉及的 hydration 标记格式变更、预渲染内容优化、声明式 API 重组(Schema / ObserverMap / AttributeMap)以及@microsoft/fast-build配套工具的行为调整。读者将掌握:新旧标记格式对照表、删除prepare()/RenderableFASTElement等废弃 API 的替换写法、declarativeTemplate()+attributeMap()+observerMap()的函数式声明式 API 用法,以及attribute-name-strategy等配置项的迁移要点。

一、迁移背景与文档定位

@microsoft/fast-html是 FAST(The adaptive interface system for modern web experiences)生态中负责声明式 HTML(declarative HTML)运行时的早期实验包。进入 v1 阶段后,其声明式能力被正式收编进@microsoft/fast-element的模块化架构中:声明式运行时发布在@microsoft/fast-element/declarative.js,hydration(水合)能力独立为@microsoft/fast-element/hydration.js,映射扩展拆分为@microsoft/fast-element/attribute-map.js与@microsoft/fast-element/observer-map.js。本迁移指南(fast-html.md)记录的就是这一整合过程中的所有破坏性变更与替代方案。

适用前提:以下所有 API 与行为均以当前仓库(FAST v3 分支)的实际源码为准,适用于从@microsoft/fast-htmlv1-alpha 升级到 v1 的开发者;若你的工具链还在解析旧版 hydration 标记或仍在使用RenderableFASTElement、TemplateElement等已移除导出,则本文的迁移步骤直接可落地。

二、Hydration 标记格式(v1-alpha → v1)

2.1 标记格式对照表

v1 简化了 SSR 输出中的 hydration 标记格式。任何检查或生成 hydration 标记的工具都必须更新为使用新格式。新旧格式对照如下(迁移指南原文表格):

旧标记新标记
<!-- fe-b$$start$$...$$fe-b --><!--fe:b-->
<!-- fe-b$$end$$...$$fe-b --><!--fe:/b-->
<!-- fe-repeat$$start$$...$$fe-repeat --><!--fe:r-->
<!-- fe-repeat$$end$$...$$fe-repeat --><!--fe:/r-->
data-fe-b="0 1 2"/data-fe-b-0/data-fe-c-0-3data-fe="N"

迁移时需注意:

  1. 新标记不再内嵌索引与 scopeId,SSR 输出体积更小、格式更稳定;
  2. data-fe="N"中的N表示属性绑定数量,取代了旧版以空格分隔的索引列表、逐 factory 枚举、以及"起始索引 + 计数"三种写法;
  3. SSR 与客户端版本必须匹配——旧版 SSR 输出配新版客户端代码(或反之)都会导致解析失败(详见fast-element-3.md中 "Hydration Marker Format (v3)" 一节,该节记录了fe-eb/fe-eb元素边界标记以及HydrationMarkup.*系列 API 的重命名,如parseAttributeBinding→parseAttributeBindingCount)。

2.2@microsoft/fast-build的配套行为

@microsoft/fast-build的 WASM 二进制会自动产出新格式标记。升级后必须重新构建所有 fixtures 与 SSR 输出。从源码结构看,microsoft-fast-convert(crates/microsoft-fast-convert)承担了声明式模板的语法转换与校验工作:它支持webui-prerelease与fast-v3-ts两个输出目标,并校验输入必须包含恰好一个带非空name的<f-template>与恰好一个内层<template>——这保证了由构建工具产出的 SSR 标记始终符合新格式。

三、预渲染内容优化(v1-alpha → v1)

3.1 已移除导出与概念

移除的导出替代方案
RenderableFASTElement直接继承扩展FASTElement
移除的概念替代方案
prepare()生命周期钩子在connectedCallback中设置状态,由响应式系统更新 DOM
渲染标记中的defer-hydration属性ElementController.connect()中的模板待定保护(template-pending guard)
渲染标记中的needs-hydration属性ElementController中的hasExistingShadowRoot检测
waitForAncestorHydration()不再需要——预渲染内容与连接顺序无关,始终正确

这里值得注意的是:从源码看,defer-hydration并未被完全删除,而是以deferHydrationAttribute常量保留在enable-hydration.ts中,用于视口相交(Intersection Observer)场景下的按需 hydration 渲染(源码注释标注为@beta)。而needs-hydration的职责则由ElementController的hasExistingShadowRoot标志接管:当元素带着既有 shadow root 连接时,控制器据此判定走 hydrate 路径而非重新渲染(见element-controller.ts中hasExistingShadowRoot = true的设置与isPrerenderedPromise 的 resolve 逻辑)。

3.2 迁移步骤

步骤 1:RenderableFASTElement→MyComponent.define()+declarativeTemplate()

将RenderableFASTElement(MyComponent).defineAsync({...})替换为MyComponent.define({...}),并在声明式模板场景下使用declarativeTemplate()。如果代码显式观察define()返回的 Promise,它会在匹配的<f-template>提供具体模板之后 resolve:

// 迁移前 import { RenderableFASTElement } from "@microsoft/fast-html"; RenderableFASTElement(MyComponent).defineAsync({ name: "my-component", templateOptions: "defer-and-hydrate", }); // 迁移后 MyComponent.define({ name: "my-component", template: declarativeTemplate(), });

步骤 2:移除prepare()方法

将所有初始化逻辑迁移到connectedCallback:

// 迁移前 class MyComponent extends FASTElement { async prepare() { this.data = await fetchData(); } } // 迁移后 class MyComponent extends FASTElement { connectedCallback() { super.connectedCallback(); this.loadData(); } async loadData() { this.data = await fetchData(); } }

步骤 3:从服务端渲染标记中移除defer-hydration与needs-hydration

<!-- 迁移前 --> <my-component defer-hydration needs-hydration text="Hello"> <template shadowrootmode="open">...</template> </my-component> <!-- 迁移后 --> <my-component text="Hello"> <template shadowrootmode="open">...</template> </my-component>

步骤 4:用$fastController.isPrerendered检测预渲染组件

isPrerendered是一个Promise<boolean>,在连接时若元素带有声明式 shadow root(DSD)则 resolve 为true(无论 hydration 是否实际运行):

connectedCallback() { super.connectedCallback(); this.$fastController.isPrerendered.then(prerendered => { if (!prerendered) { this.fetchData(); } }); }

3.3 预渲染优化带来的运行时行为

当 hydration 启用(调用enableHydration())且 FAST 元素连接时带有既有 shadow root,ElementController会检测到并执行 hydrate 而非重新渲染。这带来若干优化(与迁移指南配套的 README 与源码相互印证):

  • 用 hydrate 替代 re-render:模板调用hydrate()将既有 DOM 节点映射到绑定目标,而不是克隆新 DOM;
  • 声明式模板解析:declarativeTemplate()会在define()完成前等待匹配的<f-template>,因此已连接的预渲染元素能用具体模板进行 hydrate;
  • 属性跳过:onAttributeChangedCallback()在元素预渲染的初次 upgrade 期间跳过处理——服务端已渲染出的属性值是正确的;
  • 绑定跳过:HTMLBindingDirective.bind()在视图预渲染时,对attribute与booleanAttribute两种 aspect 跳过updateTarget。

四、Schema、ObserverMap、AttributeMap 模块化

4.1 导入路径变更

配置类型从template.ts迁移到各自所属模块。如果你直接从内部路径导入类型,请更新导入:

迁移前迁移后
import type { ObserverMapConfig } from "./template.js"import type { ObserverMapConfig } from "./observer-map.js"
import type { AttributeMapConfig } from "./template.js"import type { AttributeMapConfig } from "./attribute-map.js"

公开的声明式导入现在统一走以下路径:

  • 声明式 API:@microsoft/fast-element/declarative.js(替代@microsoft/fast-html);
  • 声明式工具函数:@microsoft/fast-element/declarative-utilities.js(如deepMerge);
  • 映射扩展:@microsoft/fast-element/attribute-map.js与@microsoft/fast-element/observer-map.js。

从declarative/index.ts的导出清单可以看到,declarative.js入口汇聚了declarativeTemplate、TemplateParser、Schema、schemaRegistry、各类CachedPath/JSONSchema类型,以及FASTElementDefinition、AttributeDefinition等核心类型。

4.2 Schema 变更

Schema.jsonSchemaMap(静态属性)被替换为:

  • 每个Schema实例上的实例级schemaMap(私有);
  • 模块级的schemaRegistry导出,用于跨元素查找。
迁移前迁移后
Schema.jsonSchemaMap.get('my-element')import { schemaRegistry } from "@microsoft/fast-element"; schemaRegistry.get('my-element')

源码印证:在schema.ts中,schemaRegistry被定义为CachedPathMap(Map<string, Map<string, JSONSchema>>),每个Schema实例在构造时将自己注册进该 registry,从而实现跨元素$ref解析(例如嵌套元素的 schema 引用)。

4.3 公开导出一览

公开入口导出函数式声明式 API:

导出用途
declarativeTemplate()为 FAST 元素定义解析<f-template>标记
attributeMap()定义扩展,自动注册@attr属性
observerMap()定义扩展,自动深度观察
SchemaJSON schema 构建器类
schemaRegistry跨元素 schema 查找的模块级注册表
JSONSchemaJSON Schema 类型接口
CachedPathMapSchema 注册表映射类型

4.4declarativeTemplate()的底层行为

从源码看,declarativeTemplate()(template.ts)返回一个FASTElementTemplateResolver,其核心逻辑为:

  1. ensureTemplateElementDefined(definition.registry)——在目标 registry 中惰性定义内部的<f-template>元素(若 registry 中已存在同名元素且不是 FAST 的实现,会抛出错误);
  2. 通过declarativeTemplateBridge.requestTemplate(definition)等待匹配的<f-template name="...">连接并发布模板;
  3. <f-template>在connectedCallback中注册为 publisher;发布时校验内层<template>数量(多于 1 个抛moreThanOneTemplateProvided,0 个抛noTemplateProvided);
  4. 解析 schema(definition.schema ?? new Schema(name)并回写definition.schema),经TemplateParser解析出strings与values,最终创建ViewTemplate。

如果多个匹配的<f-template>连接,第一个连接的提供模板,后续重复项不会重新赋值。

五、简化后的 ObserverMap 与 AttributeMap 默认行为

显式的ObserverMapOption.all与AttributeMapOption.all常量已移除。现在:

  • 无参调用observerMap()→ 观察所有发现的根属性;
  • 无参调用attributeMap()→ 映射所有发现的叶子绑定。
迁移前迁移后
observerMap(ObserverMapOption.all)observerMap()
attributeMap(AttributeMapOption.all)attributeMap()

源码层面,ObserverMapConfig与AttributeMapConfig的默认值逻辑如下:

  • observerMap(observer-map.ts):ObserverMap.defineProperties()遍历schema.getRootProperties(),对每个根属性定义Observable属性与${propertyName}Changed处理器;配置中的properties字段可逐根属性控制观察范围(布尔值或ObserverMapPathNode,$observe控制节点自身是否被观察,缺省时继承最近祖先的取值,根级默认为true)。当属性值从undefined变为对象时,处理器会用代理(Proxy)包装对象并递归注入 observable 访问器;若目标已被代理包装过,则通过deepMerge深合并新值到既有代理中(见observer-map-utilities.ts的assignObservables/deepMerge);
  • attributeMap(attribute-map.ts):AttributeMap.defineProperties()只对叶子属性创建@attr式访问器——即 schema 条目没有嵌套properties、没有type、没有anyOf的属性(如纯{{foo}}绑定)。已存在访问器(来自@attr或@observable装饰器)的属性会被跳过,避免重复定义。

两个扩展在解析顺序上:当二者同时存在时,attribute mapping 先于 observer mapping 运行(源码中attributeMapSchemaTransformPriority = 0,observerMapSchemaTransformPriority = 1,优先级数值越小越先执行)。

六、属性名策略默认值变更

声明式属性映射的默认attribute-name-strategy现在是"camelCase"(此前为"none")。例如绑定键{{firstName}}默认映射到firstName属性与first-nameHTML 属性。若你的模板依赖字面属性名,可以显式恢复旧行为:

import { attributeMap } from "@microsoft/fast-element/attribute-map.js"; MyElement.define( { name: "my-element", template: declarativeTemplate(), }, [attributeMap({ "attribute-name-strategy": "none" })], );

源码实现印证:camelToKebab将fooBar转为foo-bar;"none"策略下属性名与属性名均按绑定键原样使用({{foo-bar}}→ 属性foo-bar、属性foo-bar)。属性定义通过AttributeDefinition写入 class prototype 的访问器,并同步更新observedAttributes数组、definition.attributeLookup/propertyLookup与definition.attributes;若定义已注册(isDefined),还会调用trackLateAttributeDefinition追踪迟到的属性定义。

使用@microsoft/fast-build时,请保持服务端与客户端设置一致:

fast build --attribute-name-strategy=none

七、声明式 TemplateElement API 移除

公开的声明式 API 已切换为函数式 API。<f-template>的实现变为内部细节,由declarativeTemplate()自动定义,使用者不应直接导入或定义它。

移除项替代方案
TemplateElement公开导出每个 FAST 元素定义上的declarativeTemplate()
TemplateElement.define({ name: "f-template" })无需手动定义;declarativeTemplate()在目标 registry 中定义内部 publisher
TemplateElement.config(callbacks)/HydrationLifecycleCallbacksenableHydration().whenHydrated(tagName)(按标签等待 hydration)与enableHydration().whenHydrated()(等待当前活跃 hydration 批次)
TemplateElement.options({ "my-el": { attributeMap, observerMap } })定义扩展:MyElement.define(definition, [attributeMap(...), observerMap(...)])
ElementOptions/ElementOptionsDictionary无替代
旧声明式公开面中的AttributeMap/ObserverMap类导出attributeMap()/observerMap()扩展辅助函数及其配置类型

Hydration 也不再由@microsoft/fast-element自动安装。当需要复用预渲染的声明式 Shadow DOM 时,必须在 FAST 元素连接之前调用enableHydration()(从@microsoft/fast-element/hydration.js导入)。源码印证(enable-hydration.ts):enableHydration()通过ElementController.installHydrationHook安装 hook,hook 会调用模板的hydrate()映射既有 DOM 节点,并设置isPrerendered/isHydrated两个 Promise;函数可被多次安全调用,后续调用会把 options 合并进共享的 tracker,且默认在初始批次完成后停止对新的预渲染元素进行 hydration——对于流式追加 DSD 的场景,可用stopHydration: StopHydration.never保持 hook 活跃(此模式下whenHydrated()会因 hydration 永无全局完成点而有意保持 pending)。

八、Schema 驱动的映射与可选定义 Schema

attributeMap()与observerMap()现在是由 schema 驱动的扩展,且与声明式模板解耦,声明式与非声明式场景均可从@microsoft/fast-element导入:

import { attributeMap } from "@microsoft/fast-element/attribute-map.js"; import { observerMap } from "@microsoft/fast-element/observer-map.js";

FASTElementDefinition.schema现在是可选的。declarativeTemplate()在解析<f-template>标记时会自动为其赋值。手动使用 schema 的开发者可以在元素定义中传入 schema,observerMap()也可以在配置中直接接收 schema:

import { FASTElement, Schema } from "@microsoft/fast-element"; import { observerMap } from "@microsoft/fast-element/observer-map.js"; class MyElement extends FASTElement {} const schema = new Schema("my-element"); schema.addPath({ rootPropertyName: "user", pathConfig: { type: "default", parentContext: null, currentContext: null, path: "user.name", }, childrenMap: null, }); MyElement.define({ name: "my-element" }, [observerMap({ schema })]);

源码印证:Schema.addPath(schema.ts)根据pathConfig.type(default/access/repeat/event)与childrenMap(子元素引用,生成anyOf的$ref)在根属性 schema 中构建properties、$defs与上下文信息。observerMap扩展在无 template resolver 时直接消费config.schema ?? definition.schema定义观察者;若两者都缺失则抛出错误,提示使用observerMap({ schema })、在元素定义上提供 schema 或改用declarativeTemplate()。

九、迁移检查清单

完成@microsoft/fast-htmlv1-alpha → v1 迁移后,建议逐项核对:

  1. hydration 标记:所有 SSR fixtures 与输出均由@microsoft/fast-build重新生成,标记为<!--fe:b-->/<!--fe:r-->与data-fe="N"格式;SSR 与客户端版本一致;
  2. 导出替换:RenderableFASTElement→ 继承FASTElement;TemplateElement/ElementOptions不再使用;Schema.jsonSchemaMap→schemaRegistry;
  3. 生命周期:prepare()逻辑迁移至connectedCallback;不再调用waitForAncestorHydration();
  4. 标记清理:SSR 标记中移除defer-hydration与needs-hydration(defer-hydration仍保留为deferHydrationAttribute常量,仅用于视口相交按需渲染场景);
  5. 扩展默认行为:observerMap(ObserverMapOption.all)→observerMap();attributeMap(AttributeMapOption.all)→attributeMap();
  6. 属性名策略:确认attribute-name-strategy期望为camelCase(默认)还是none,并保持@microsoft/fast-build与客户端配置一致;
  7. hydration 显式启用:需要复用预渲染 DSD 时,在元素连接前调用enableHydration();流式场景使用StopHydration.never,诊断场景可传入hydrationDebugger()。

十、进一步阅读

  • 迁移指南:@microsoft/fast-elementv2 → v3(含 v3 hydration 标记格式的完整 API 变更)
  • README:FAST Element v3 的声明式 HTML、预渲染优化与 define 扩展用法
  • 声明式模板语法与实现细节
  • 声明式运行时源码入口
  • declarativeTemplate()与<f-template>实现
  • Schema 构建与schemaRegistry
  • ObserverMap 扩展实现
  • AttributeMap 扩展实现与属性名策略
  • enableHydration()与 hydration hook 安装
  • @microsoft/fast-build的语法转换工具microsoft-fast-convert
  • 前端
  • UI组件

【免费下载链接】fast

The adaptive interface system for modern web experiences.

项目地址:https://gitcode.com/gh_mirrors/fa/fast
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询