Backstage 声明式集成搜索插件(Declarative Integrated Search)完整指南
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
本文围绕 Backstage 仓库中的 docs/features/search/declarative-integration.md 展开,讲解如何在不编写前端代码的前提下,通过声明式集成(declarative integration)在基于新前端系统的 Backstage 应用中启用并定制搜索功能,同时结合仓库源码剖析其背后的扩展(Extension)机制、配置项与自定义扩展开发流程。读完本文,你将掌握:扩展数据流的核心概念、
Search插件的安装与app-config.yaml配置、使用SearchResultListItemBlueprint构建自定义搜索结果项扩展,以及noTrack等内置配置项的用法。
实验性功能声明:声明式集成目前仍处于实验阶段,官方不推荐在生产环境使用,本文所有内容均以实验/评估用途为前提。
一、声明式集成:不写代码也能定制 Backstage
Backstage 的声明式集成(declarative integration)理念是:通过配置而非代码来定制 Backstage 实例。这意味着应用维护者可以把原本需要在 TypeScript 代码中完成的插件组装、页面挂载、侧边栏导航项注册等工作,下沉到app-config.yaml中完成。
在新前端系统(New Frontend System)中,所有扩展 Backstage 核心能力的单元都被称为扩展(Extension)——它可以是一个 API 提供者,也可以是一个页面组件,甚至是一条路由。扩展之间通过"产出物(output artifacts)"和"输入(inputs)"进行组合:每个扩展产出若干工件,这些工件又被其他扩展作为输入消费,从而形成一条可组合的扩展链。
Search插件正是以这种方式实现搜索功能的典型代表,理解扩展的数据流是掌握声明式搜索的基础。
二、扩展数据流:从搜索结果项到路由渲染
上图为仓库中的 search-extensions-example.drawio.svg(源码位于docs/assets/search/目录),它完整展示了搜索功能中三类扩展的协作方式:
SearchResultItem扩展(id: plugin.search.result.item):产出一个组件(Component)。它通过挂载点plugin.search.page/items把该组件注入到SearchPage扩展的items输入上。SearchPage扩展(id: plugin.search.page):消费items输入中注入的搜索结果项组件,将其组合成一个完整的搜索页面元素,并同时产出**路由路径(PATH)与页面元素(ELEMENT)**两个工件;这两个工件随后通过core.router/routes挂载点注入到CoreRoutes扩展(id: core.router)。CoreRoutes扩展:当浏览器地址与搜索页面路径匹配时,渲染对应的页面元素,完成从"搜索结果项"到"用户可见页面"的完整链路。
这一连串"输出 → 挂载点 → 输入"的关系,正是理解声明式Search插件工作方式的关键。
三、Search 插件与其提供的扩展
3.1 安装:仅需一步
在声明式集成模式下,启用搜索功能只需安装两个包:
yarn add @backstage/plugin-catalog @backstage/plugin-search之所以必须同时安装@backstage/plugin-catalog,是因为Search插件依赖Catalog API(@backstage/plugin-catalog提供了该 API 的扩展实现)。安装完成后无需额外注册代码,插件扩展即通过新前端系统的自动发现机制生效,仓库中的示例应用可参考 packages/app。
3.2 Search 插件提供的扩展预设
Search插件(声明式入口见 plugins/search/src/alpha.tsx)提供了一组扩展预设:
| 扩展 | 产出物 | 输入去向 | 作用 |
|---|---|---|---|
| SearchApi | Search API的具体实现 | 挂载到Core的 apis 持有器 | 为整个应用提供搜索查询能力 |
| SearchPage | 高级搜索页面组件 | 期望接收Search搜索结果项组件作为输入 | 以自定义方式渲染搜索结果 |
| SearchNavItem | 侧边栏搜索导航项数据 | 输入到Core的 nav 扩展 | 在主应用侧边栏中显示搜索入口 |
对应到源码,plugins/search/src/alpha.tsx 中:
searchApi通过ApiBlueprint.make声明,factory基于discoveryApi与fetchApi构造SearchClient,实现searchApiRef;searchPage通过PageBlueprint.makeWithOverrides声明,其inputs定义了三个挂载点——items(搜索结果项)、resultTypes(结果类型过滤器)、searchFilters(搜索过滤器),并在loader中把items输入映射给SearchPage组件(见 plugins/search/src/alpha/SearchPage.tsx),路由路径固定为/search;- 插件通过
createFrontendPlugin注册,pluginId: 'search'。
从源码结构看,searchPage的三个输入挂载点设计为未来把过滤器(filter)也扩展化预留了空间(详见下文"未来增强机会")。
四、通过 app-config.yaml 配置 Search 扩展
所有Search扩展都可以在app-config.yaml的app.extensions字段中,以扩展 ID 作为配置键进行配置。扩展 ID 的命名规则为kind:name,例如搜索页面的扩展 ID 为page:search。
4.1 禁用搜索页面扩展
# app-config.yaml app: extensions: - page:search: false # ✨ 禁用搜索页面将该扩展的值设为false即可关闭搜索页面(同时侧边栏入口也会随之消失)。
4.2 设置搜索页面标题(用于侧边栏)
# app-config.yaml app: extensions: - page:search: # ✨ 自定义标题 config: title: 'Search Page'title配置会显示在侧边栏的搜索导航项上。源码层面,searchPage在 plugins/search/src/alpha.tsx 中通过PageBlueprint.makeWithOverrides提供了configSchema,其中包含noTrack: z.boolean().default(false),并在渲染侧边栏条目与页面时应用title、icon等默认值。
4.3 已知限制
目前尚无法在配置文件中为侧边栏项打开模态框(modal),也无法通过配置文件指定不同的图标——这两个能力已在维护者的规划中。
也就是说,page:search的图标与交互行为在当前版本中只能使用插件默认实现。
五、自定义搜索结果项扩展:SearchResultListItemBlueprint
插件开发者可以使用@backstage/plugin-search-react/alpha导出的SearchResultListItemBlueprint构建自己的搜索结果项扩展。
5.1 Blueprint 的源码级参数说明
查阅 plugins/search-react/src/alpha/blueprints/SearchResultListItemBlueprint.tsx 可以看到,该 Blueprint 的核心定义如下:
kind: 'search-result-list-item',自动挂载到page:search的items输入(即上文的plugin.search.page/items挂载点);configSchema内置noTrack: z.boolean().default(false),用于控制是否关闭该结果项的自动埋点;params支持三个字段:component:必需的扩展组件工厂,接收{ config: { noTrack?: boolean } },返回一个异步组件;predicate:可选的结果匹配谓词,返回true表示该结果应由本扩展渲染;默认谓词恒返回true,即渲染所有类型的结果;icon:可选的结果项图标。
在factory内部,BluePrint 使用lazy加载component工厂产出的组件,并用ExtensionBoundary包裹,再通过SearchResultListItemExtension注入rank、result、noTrack等属性,最终以searchResultListItemDataRef数据引用输出——这正是SearchPage的items输入所消费的数据格式。
对应地,plugins/search/src/alpha/SearchPage.tsx 中的getResultItemComponent会遍历items,用每个结果项的predicate匹配当前result,命中则使用该扩展的component,否则回退到DefaultResultListItem渲染。
5.2 创建自定义 TechDocs 搜索结果项扩展
// plugins/techdocs/src/alpha.tsx import { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha'; export const TechDocsSearchResultListItemExtension = SearchResultListItemBlueprint.make({ name: 'techdocs', params: { predicate: result => result.type === 'techdocs', component: async ({ config }) => { const { TechDocsSearchResultListItem } = await import( './components/TechDocsSearchResultListItem' ); return props => <TechDocsSearchResultListItem {...props} {...config} />; }, }, });上述代码中,插件开发者提供了一个专门渲染type === 'techdocs'结果的组件:predicate限定只处理 TechDocs 类型的搜索结果,component异步加载自定义结果项组件并把config(含noTrack)透传给渲染组件。
该自定义结果项扩展在@backstage/plugin-techdocs安装后会默认启用,采纳者无需在配置文件中手动启用。
仓库中 TechDocs 插件的实际实现见 plugins/techdocs/src/alpha/index.tsx:techDocsSearchResultListItemExtension更进一步使用了makeWithOverrides,额外扩展了configSchema:
configSchema: { title: z.string().optional(), // 可选标题 lineClamp: z.number().default(5), // 结果摘要行数截断 asLink: z.boolean().default(true), // 是否渲染为链接 asListItem: z.boolean().default(true), // 是否渲染为列表项 },并通过predicate: result => result.type === 'techdocs'与icon: <DocsIcon />完善了 TechDocs 专属的结果项行为,最终经createFrontendPlugin(pluginId: 'techdocs')把该扩展注册进插件扩展列表。
5.3 禁用内置的 TechDocs 搜索结果项
如果采纳者在安装 TechDocs 插件后不想要自定义的 TechDocs 搜索结果项,可通过配置禁用:
# app-config.yaml app: extensions: - search-result-list-item:techdocs: false扩展 ID 中的search-result-list-item正是SearchResultListItemBlueprint的kind(源码见 SearchResultListItemBlueprint.tsx),techdocs则是make时指定的name。
5.4 使用内置 noTrack 配置关闭自动埋点
SearchResultListItemBlueprint内置了noTrack配置项,可用于禁用该结果项扩展的自动分析事件追踪:
# app-config.yaml app: extensions: - search-result-list-item:techdocs: config: noTrack: true源码层面,noTrack由 Blueprint 的configSchema声明(z.boolean().default(false)),默认值为false(即默认开启埋点),随后被传入SearchResultListItemExtension与你的自定义组件config中。
5.5 测试验证
仓库中 SearchResultListItemBlueprint.test.tsx 提供了该 Blueprint 的单元测试,验证了两个关键行为:
- 未提供
predicate时使用"恒为真"的默认谓词(测试中显式传入predicate: () => true并快照断言扩展的挂载点为page:search/items、kind为search-result-list-item); noTrack配置会正确传递给组件:分别以默认配置与{ config: { noTrack: true } }渲染测试扩展,页面分别呈现noTrack: false与noTrack: true,证明配置默认值与覆盖传递均生效。
这对插件开发者是很好的参考用例——自定义结果项扩展可以按同样的方式用createExtensionTester进行验证。
六、未来增强机会
- 扩展替换(Extension Replacement):Backstage 维护者正在推进扩展替换能力,届时采纳者将可以直接替换插件提供的扩展,而不仅仅是启用/禁用,相关文档会随版本更新。
- 过滤器扩展化:第一版
SearchPage扩展的inputs(items、resultTypes、searchFilters)设计为搜索插件维护者未来将过滤器也转化为扩展留好了余地。如果你对这个方向感兴趣,可以打开 issue 并提交 PR 参与协作。
七、小结
声明式集成为 Backstage 搜索功能提供了一条低代码路径:安装@backstage/plugin-catalog与@backstage/plugin-search即可获得完整的搜索页面、侧边栏入口与 API;通过app.extensions配置可以禁用/定制扩展;借助SearchResultListItemBlueprint与predicate/component/icon/noTrack等参数可以快速接入自定义结果项(如 TechDocs 的实现方式)。由于该能力仍处于实验阶段,建议仅在评估与演示环境中使用,并持续关注维护者对扩展替换与过滤器扩展化的后续更新。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考