跳转到内容
flamo
开始使用

导出 web-component

Flamo 可以把经过验证的 Artifact Export 投影为 W3C Custom Element。导出物使用同一 public surface 生成 attributes、DOM properties、CustomEvent、methods、light DOM slots、.d.ts 和 custom-elements.json,避免手工 wrapper 与组件事实漂移。

在画布上或左侧节点树中右键目标节点,选择“导出为 Web Component”,确认组件标签名,配置画布是否可移动、可缩放及内容适应方式,然后点击“导出”。导出目标始终是被右键的节点。普通节点也可以直接导出;临时导出边界只建立在打包副本中,原 Artifact 场景不变。

节点 card 默认导出为 flamo-card,不自动追加节点 ID 或版本。已有显式标签名会沿用;公开标签名可在导出面板编辑,确认后按节点保存到项目 .flamo/component-exports.json。后续节点改名仍沿用保存的标签,同项目导出节点重名会提示调整。版本、revision 和哈希留在 manifest 中。升级时整体替换包内资源,并检查 slot/prop/event 合同是否兼容。

默认不可移动、不可缩放、等比适应。画布背景默认透明,无需配置;节点自身设计的填充仍会保留。

“Source Map”默认不勾选。勾选后,导出包携带组件入口和用户交互脚本中可用的 Source Map,便于调试;闭源 Runtime 的 Source Map 始终不会随包导出。不勾选时不包含 .map 文件及对应引用。该配置记录在 manifest.json 的 packaging.sourceMap 字段。

“携带公共资源”默认勾选,组件包包含 Runtime 和画布适配模块,可以放到静态服务器直接使用。多个组件需要共用资源时:

  1. 取消勾选“携带公共资源”,填写公共资源根地址,例如 http://192.168.1.25:8080/common/v0.0.1/。
  2. 点击“下载公共资源包”,将解压目录中的 flamo-runtime/ 文件夹和 component-viewport.js 文件直接部署到该地址下。保留 Runtime 文件夹中的依赖与许可证,并配置 JavaScript MIME 类型及跨域模块请求所需的 CORS。
  3. 点击“导出”,获得已配置完整资源 URL 的组件包,无需修改 dist 中的 JS。上述地址会生成 http://192.168.1.25:8080/common/v0.0.1/flamo-runtime/index.es.js?v=v0.0.1 和 http://192.168.1.25:8080/common/v0.0.1/component-viewport.js?v=v0.0.1。

根地址最后一级是版本号(如 v0.0.1、0.0.1)时,自动使用该版本作为 v 查询参数;其他目录使用资源内容哈希作为 v 参数。查询参数不属于文件名。公共资源更新时,使用新的版本目录,并用新地址重新导出组件;同一版本可供多个组件共享。

interactions/ 中的项目脚本始终保留在组件包内,不会进入公共资源包,也不会被改成 CDN 脚本。它们对 Runtime 的引用会指向组件使用的同一地址。填写地址只配置引用,不会自动上传。

Runtime 公共资源包含独立的第三方依赖文件及许可正文。Runtime 核心采用混淆保护,@vue 等第三方依赖仅压缩;组件使用仍受包内 FLAMO-RUNTIME-LICENSE 和第三方许可证约束。

Runtime 不再默认携带可选的 HarfBuzz WASM 和后备字体。普通 Canvas 文字与已有字形轮廓不需要这些资源;显式使用 HarfBuzz 后备或字体处理 API 时,由使用方提供所需资源并通过 FlamoConfig.set({ wasmPath, fontPath, defaultFont }) 配置。用于布局的 Yoga WASM 仍保留在 Runtime 依赖中。

适应方式 缩放与滚动
等比适应 内容完整适配容器,保持宽高比例并居中
宽度适应 宽度填满容器,高度等比缩放;超出容器时出现纵向滚动条
高度适应 高度填满容器,宽度等比缩放;超出容器时出现横向滚动条

导出配置保存在包内 manifest.json 的 viewport 字段。用 CSS 设置自定义元素的宽高,组件会随容器尺寸变化重新适配。例如:

flamo-search-panel {
width: 100%;
height: 400px;
background: #f5f5f5;
}

未设置 CSS 尺寸时,容器默认为 300px × 150px。百分比高度需要父容器有确定高度。滚动条不受“可移动”开关限制,该开关控制用户对画布相机的平移操作。

使用 Flamo Design 插件时,也可通过 flamo_component_export 按节点和固定 Artifact revision 直接导出。先 dryRun,再 apply,下载后核对 ZIP 的 SHA-256、manifest 中的 revision 和 contractId。详见 Flamo Design 插件。

浏览器在 Custom Element 定义前会直接显示标签内的 light DOM。推荐使用导出包提供的轻量加载入口和固定尺寸占位容器;将下面的样式和资源引用放在页面 head,容器放在正文。将示例标签替换为实际导出的标签名。

<style>[data-flamo-component]:not([data-flamo-state="ready"]){opacity:0;pointer-events:none}</style>
<link rel="stylesheet" href="./dist/component-loading.css">
<script type="module" src="./dist/flamo-search-panel.loader.js"></script>
<div class="flamo-component-shell" style="width:100%;height:400px">
<flamo-search-panel data-flamo-component inert aria-busy="true" loading-label="正在加载查询面板…">
<span slot="empty">没有结果</span>
</flamo-search-panel>
<div data-flamo-status role="status" aria-live="polite">
<span data-flamo-message>正在加载查询面板…</span>
<button type="button" hidden>刷新重试</button>
</div>
</div>

占位保持组件尺寸,页面其他区域可以继续加载。组件在场景、交互、初始插槽图片和画布已请求的图片资源就绪并完成绘制后,派发 flamo-ready 并淡入;paused 组件也会完成初始绘制。模块或运行时错误显示刷新入口,等待超过 45 秒时提示检查网络,之后成功仍会恢复。data-flamo-state 为 loading、ready 或 error,aria-busy 同步更新。

可通过容器的 --flamo-loading-accent、--flamo-loading-color 自定义颜色;系统开启减少动画时关闭旋转和淡入。使用 CDN 时应同时更新对应公共 Runtime 资源。

选择 Figma 主组件,在右侧 Properties 中编辑对应 Slot property 的 description。同步并重新导出后,说明会出现在 manifest.json、custom-elements.json 和 README 真实 slot 骨架的 data-mark 中。Slot 名称精确保留大小写。已有默认内容的占位会注释,防止空 div 覆盖默认内容。

描述应说明内容用途、状态表现、未知状态和资源约束。具体 API、点位字段和实际值映射由接入项目提供,AI 不应根据 slot 缩写推导。把导出包与宿主项目交给 AI,按包内 AGENTS.md 读取真实合同、现有接口与素材后生成接入代码;业务文件放在导出目录外,便于整体升级组件包。

const component = document.querySelector('flamo-card');
component.slotStyles = '[slot="header"] { color: white; }';
// 只修改源 light DOM,Runtime 会同步各个独立 outlet。
component.querySelector('[slot="header"]').textContent = '最新内容';

slotStyles 可以在组件定义前、ready 前或 ready 后设置,空字符串清除。CSS 应限定到 slot 内容;相对资源 URL 相对于宿主文档。宿主无需查询 ShadowRoot 或复制样式到内部。源 DOM 的属性、文字、子节点变化会同步,但 JS property 和 addEventListener 不会随克隆复制;有独立交互的内容使用自行初始化、断开时清理的 Custom Element,或声明的 slot props/events。

  1. boundary 有稳定 tagName,并且只包含连字符形式的合法自定义元素名;
  2. Artifact Export 的 props/events/methods/slots 已验证;
  3. composition dependency lock、Artifact hash、surface hash 与 Runtime ABI 可追踪;
  4. 脚本、字体、图片和其他资源进入 package closure;
  5. duplicate tag、ABI mismatch、asset/module 404 与 partial mount 有失败证据。
模式 适合场景 边界
browser-esm 目录式 ESM 发布,组件、Runtime、interaction 与资源按 manifest 组织 允许静态 HTTP + import maps,无需宿主 bundler
thin-single-js 每个组件使用精简入口,共享外部 Runtime Runtime 与资源仍是外部依赖,不是完全 standalone

Flamo 不提供 standalone-single-js:不会把 Runtime、Artifact、脚本、字体、图片和全部依赖永久内联为一个巨型文件。

导出的 direct entry 会注册自定义元素:

<script type="module" src="./dist/flamo-search-panel.js"></script>
<flamo-search-panel query="Flamo">
<span slot="empty">没有结果</span>
</flamo-search-panel>
<script type="module">
const panel = document.querySelector('flamo-search-panel');
panel.query = 'Artifact'; // DOM property
panel.addEventListener('submit', event => console.log(event.detail));
await panel.focus(); // public method
</script>

如果使用不自动注册的 .module.js entry,先导入并调用 registerFlamoComponent()。同一 tagName 已由不同 identity 注册时必须失败,不能覆盖浏览器 registry 中的已有类。

每个发布模式都生成 versioned browser manifest,记录 exact Component Ref、entry、resource base、integrity、surface/composition hash、dependencies 与 assets。Loader 在 import 前应用 allowed origins、CORS、integrity、timeout、retry、cache 和 script allowlist 策略;一个模块失败时,不应污染已经运行的其他组件实例。

包中还包含 manifest.json、custom-elements.json、精确 .d.ts 和 Packaging IR;source maps 按导出时的选项携带。宿主集成以这些生成合同为准,不从内部 Artifact 结构猜 props 或事件。