SuperAPI AI 工具集

creating-backstage-entity-page-extension

编程与开发

查看项目

更新于 10-16 02:24

技能介绍

用途

该技能用于为 Backstage 的目录实体页面(catalog entity page)创建扩展。典型场景包括:

  • 在目录实体的 Overview 标签页中添加一张卡片,例如在关联 Jira 项目的 Component 上展示 Jira 项目信息。
  • 为目录实体页面添加一个完整的标签页(带独立 URL 路径的内容面板),例如在 Component 上添加 /incidents 标签页,列出该组件的故障事件。
  • 根据实体 kind、spec type、注解是否存在或任意自定义谓词,控制扩展何时出现。

这是脚手架生成 frontend-plugin-module 最常见的原因。所编写的插件通过这些蓝图扩展宿主应用的 catalog 插件。

主要能力

该技能提供两种蓝图模式:

  • 实体 Overview 标签页上的卡片:使用 EntityCardBlueprint.make({ name, params: { loader, filter?, type? } }),参考 references/card.md。
  • 实体页面上的完整标签页(带独立 URL 路径):使用 EntityContentBlueprint.make({ name, params: { path, title, loader, filter?, group?, icon? } }),参考 references/content.md。

两种蓝图均来自 @backstage/plugin-catalog-react/alpha,共享以下特性:

  • 一个 loader:() => Promise<JSX.Element>,用于对渲染组件进行代码分割。
  • 一个 filter 参数,用于控制扩展何时出现。

组件在 catalog 实体上下文中渲染,可通过 @backstage/plugin-catalog-react 的 useEntity() 读取当前实体。

使用方式

该技能有两种调用模式:

  • 独立模式:编辑一个以 catalog 为目标的现有 frontend-plugin-module,选择合适的参考(card 或 content)并添加扩展。
  • 脚手架后模式(由 creating-backstage-plugin 针对以 catalog 为目标的 frontend-plugin-module 模板调用):根据用户描述脚手架生成扩展及其渲染的组件。

实体过滤

两种蓝图上的 filter 参数决定扩展适用于哪些实体,接受三种形式:

  • 字符串(最常见):'kind:component'、'kind:component,spec.type:service'、'metadata.annotations.acme.com/jira-project'。逗号分隔表示 AND,同一键的多种形式表示 OR。
  • FilterPredicate(结构化):经 Zod 校验的对象形式,用于更丰富的逻辑。需对照 ../backstage/packages/filter-predicates/src/ 核实确切结构。
  • 函数:(entity: Entity) => boolean,完全程序化控制。应谨慎使用——字符串过滤器与上游的配置覆盖系统组合得更好。

如果省略 filter,扩展会出现在所有实体 kind 上。这几乎总是错误的——即使只是 'kind:component',也应设置过滤器。

适用场景

  • 需要向 Backstage 目录实体的概览页添加信息卡片。
  • 需要为目录实体页面新增带独立路由的标签页。
  • 需要按实体属性(kind、spec type、注解等)精确控制扩展的显示范围。
  • 正在编写以 catalog 插件为扩展目标的 frontend-plugin-module。

限制与注意事项

  • 蓝图来自 @backstage/plugin-catalog-react/alpha(当前为 @alpha)。需对照 ../backstage/plugins/catalog-react/src/alpha/blueprints/ 跟踪导入路径。
  • 组件本身从 @backstage/plugin-catalog-react(主入口,而非 /alpha)导入 useEntity。该 hook 返回 { entity },类型为 Entity——使用 @backstage/catalog-model 的目录实体模型对 metadata、spec 等进行类型化访问。
  • useEntity 只能在这些蓝图渲染的组件内部使用——在 catalog 实体上下文之外调用会抛出异常。
  • 必须使用 loader: () => Promise<JSX.Element> 形式以实现代码分割。不要传入同步组件导入——应使用 () => import('./MyCard').then(m => <m.MyCard />)。
  • 对于实体特定的数据获取,将 useEntity 与 using-backstage-frontend-system 中的数据 hook 约定结合使用(一个围绕 fetchApi.fetch 包装 useAsync 的 hook)。将 entity.metadata.name 或某个注解作为缓存键。
  • 宿主应用的 catalog 插件拥有路由 entity-content:catalog/overview(卡片挂载处)和 page:catalog/entity(内容标签页挂载处)。模块安装到与 catalog 插件相同的后端——采用者通过 backend.add(...) 和 app.installPlugin(...) 安装,无需其他操作。