ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Backstage Search 深度定制指南:自定义 Search API、索引字段与搜索结果渲染

Backstage Search 深度定制指南:自定义 Search API、索引字段与搜索结果渲染 Backstage Search 深度定制指南自定义 Search API、索引字段与搜索结果渲染【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage搜索是 Backstage 开发者门户中用户高频使用的基础能力而开箱即用的默认实现往往无法覆盖所有定制诉求。本指南以仓库内 docs/features/search/how-to-guides.md 为核心骨架面向新前端系统New Frontend System系统讲解四条高级定制路线自定义SearchApi实现、通过 collator 的entityTransformer/documentTransformer定制 Software Catalog 与 TechDocs 的索引字段、用统一主题定制搜索结果高亮样式以及用SearchResultListItemBlueprint扩展渲染搜索结果项。读完本文你将能够在自己的 Backstage 应用中独立完成上述全部定制并理解其背后的源码实现原理。本文面向新前端系统新 Backstage 应用默认启用。如果你的应用仍在使用旧前端系统请阅读对应的旧版指南。一、认识 Search 插件与默认的 SearchApiSearch 插件默认提供并注册了一个核心 API——SearchApi它的职责是负责与search-backend通信、查询搜索结果。SearchApi是一个纯 TypeScript 接口定义在 plugins/search-react/src/api.tsexport interface SearchApi { query( query: SearchQuery, options?: { signal?: AbortSignal }, ): PromiseSearchResultSet; }它只要求实现一个query方法传入SearchQuery含 term、filters、types、pageCursor 等查询参数可选AbortSignal用于取消请求返回SearchResultSet。同文件中还提供了MockSearchApi可直接用于测试与 Storybook 场景。默认实现是 plugins/search/src/apis.ts 中的SearchClient其核心逻辑如下export class SearchClient implements SearchApi { private readonly discoveryApi: DiscoveryApi; private readonly fetchApi: FetchApi; constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) { this.discoveryApi options.discoveryApi; this.fetchApi options.fetchApi; } async query( query: SearchQuery, options?: { signal?: AbortSignal }, ): PromiseSearchResultSet { const queryString qs.stringify(query); const url ${await this.discoveryApi.getBaseUrl( search, )}/query?${queryString}; const response await this.fetchApi.fetch(url, { signal: options?.signal, }); if (!response.ok) { throw await ResponseError.fromResponse(response); } return response.json(); } }可以看到默认实现依赖DiscoveryApi解析 search 后端的 base URL依赖FetchApi发起带凭据的请求并通过qs序列化查询参数。这为自定义实现提供了一个清晰的范本你需要自行处理请求地址、认证与错误转换。二、自定义 SearchApi 实现当你需要对接自己的搜索后端、或对默认查询行为做深度改造时可以按两步实现自己的SearchApi第一步按需实现SearchApi接口。export class SearchClient implements SearchApi { // your implementation }注意SearchClient只是一个类名示例你可以命名为任何你喜欢的名字关键是实现query方法并满足SearchApi的类型契约。你可以参考默认实现中ResponseError.fromResponse(response)的错误处理方式来自backstage/errors保证接口契约一致。第二步用自定义 API 扩展覆盖默认扩展。默认的searchApi扩展在 plugins/search/src/alpha.tsx 中定义它通过ApiBlueprint.make注册使用searchApiRef作为 API 引用factory里直接new SearchClient({ discoveryApi, fetchApi })export const searchApi ApiBlueprint.make({ params: defineParams defineParams({ api: searchApiRef, deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef }, factory: ({ discoveryApi, fetchApi }) new SearchClient({ discoveryApi, fetchApi }), }), });要替换它只需用createApiExtension创建自定义 API 扩展并安装到应用中。关于如何创建与安装自定义 API 扩展的完整说明参见 Utility APIs 文档其中涵盖了创建、消费、配置与测试 Utility API 的全部细节例如用backstage/frontend-test-utils的mockApis对核心 Utility API 打桩。三、定制 Software Catalog 或 TechDocs 索引字段搜索索引的内容由collator采集器决定。当你希望控制进入搜索索引的数据、或针对特定kind定制数据时可以通过向DefaultCatalogCollatorFactory传入entityTransformer回调实现DefaultTechDocsCollatorFactory也支持同样的行为。你既可以简单修改默认行为也可以编写一个全新的文档但需遵循必要的基础结构。重要限制authorization和location字段无法通过entityTransformer修改location只能通过locationTemplate修改。3.1 Catalog collator 的 entityTransformer以下示例位于packages/backend/src/plugins/search.tsconst catalogEntityTransformer: CatalogCollatorEntityTransformer ( entity: Entity, ) { if (entity.kind SomeKind) { return { // customize here output for SomeKind kind }; } return { // and customize default output ...defaultCatalogCollatorEntityTransformer(entity), text: my super cool text, }; }; indexBuilder.addCollator({ collator: DefaultCatalogCollatorFactory.fromConfig(env.config, { discovery: env.discovery, tokenManager: env.tokenManager, /* highlight-add-next-line */ entityTransformer: catalogEntityTransformer, }), });其中defaultCatalogCollatorEntityTransformer是仓库内置的默认转换器实现在 plugins/search-backend-module-catalog/src/collators/defaultCatalogCollatorEntityTransformer.ts它输出的默认文档结构为{ title: entity.metadata.title ?? entity.metadata.name, text: getDocumentText(entity), // description、用户/组的 displayName、用户 email 拼接 componentType: entity.spec?.type?.toString() || other, type: entity.spec?.type?.toString() || other, namespace: entity.metadata.namespace || default, kind: entity.kind, lifecycle: (entity.spec?.lifecycle as string) || , owner: (entity.spec?.owner as string) || , }因此在原默认结构上做增强例如示例中的...defaultCatalogCollatorEntityTransformer(entity), text: my super cool text是最稳妥的写法——你既继承了全部默认字段又覆盖了text的取值。从源码看DefaultCatalogCollatorFactory见 plugins/search-backend-module-catalog/src/collators/DefaultCatalogCollatorFactory.ts的entityTransformer默认值就是defaultCatalogCollatorEntityTransformer且在execute()中通过catalog.queryEntities分批batchSize游标式拉取实体对每个实体执行yield { ...this.entityTransformer(entity), authorization: { resourceRef: stringifyEntityRef(entity), }, location: this.applyArgsToFormat(this.locationTemplate, { namespace: ..., kind: ..., name: ..., }), };这也印证了文档中的限制说明authorization基于实体 ref 的权限引用与location基于locationTemplate生成是在 transformer 之外由工厂强制写入的因此 transformer 无法触碰它们。3.2 TechDocs collator 的 entity 与 document 转换器TechDocs collator 更进一步提供了两个转换钩子entityTransformer负责将 Catalog 实体转换为文档骨架documentTransformer负责处理 TechDocs 生成器产出的 mkdocs 搜索索引文档MkSearchIndexDocconst techDocsEntityTransformer: TechDocsCollatorEntityTransformer ( entity: Entity, ) { return { // add more fields to the index tags: entity.metadata.tags, }; }; const techDocsDocumentTransformer: TechDocsCollatorDocumentTransformer ( doc: MkSearchIndexDoc, ) { return { // add more fields to the index bost: doc.boost, }; }; indexBuilder.addCollator({ collator: DefaultTechDocsCollatorFactory.fromConfig(env.config, { discovery: env.discovery, tokenManager: env.tokenManager, /* highlight-add-next-line */ entityTransformer: techDocsEntityTransformer, /* highlight-add-next-line */ documentTransformer: techDocsDocumentTransformer, }), });示例中bost: doc.boost为示意写法实际字段名请以你的索引结构为准。仓库内置的默认实现见 defaultTechDocsCollatorEntityTransformer.ts输出kind、namespace、annotations、name、title、text、componentType、type、lifecycle、owner、path等字段与 defaultTechDocsCollatorDocumentTransformer.ts。DefaultTechDocsCollatorFactory的完整可配置项见 DefaultTechDocsCollatorFactory.ts还包括locationTemplate默认/docs/:namespace/:kind/:name/:path、parallelismLimit、legacyPathCasing、entityFilterFunction、customCatalogApiFilters等。3.3 可配置项与默认值Catalog collator 的运行时配置读取逻辑位于 plugins/search-backend-module-catalog/src/collators/config.ts配置键为search.collators.catalog默认值如下配置项默认值说明schedule.frequency{ minutes: 10 }采集任务执行频率schedule.timeout{ minutes: 15 }单次采集超时时间schedule.initialDelay{ seconds: 3 }启动后的初始延迟locationTemplate/catalog/:namespace/:kind/:name生成location字段的模板占位符会被替换并统一转为小写filter无不过滤Catalog 实体过滤条件EntityFilterQuerybatchSize500每次queryEntities拉取的实体数量需要说明的是示例代码中使用的env.config/env.discovery/env.tokenManager是旧版后端插件写法在新后端系统中应改用auth、catalog等核心服务注入DefaultCatalogCollatorFactoryOptions当前接受auth: AuthService与catalog: CatalogService实际接入方式以你的 Backstage 版本为准。四、自定义搜索结果高亮样式默认情况下搜索结果中匹配词的高亮样式取自浏览器对markHTML 标签的默认样式。如需定制高亮效果可以遵循 Backstage 的自定义应用 UI 指南创建带自定义样式的主题覆盖。例如使用统一主题Unified Theme方法以下配置可以让高亮词变为加粗 下划线import { createBaseThemeOptions, createUnifiedTheme, palettes, UnifiedTheme, } from backstage/theme; export const myLightTheme: UnifiedTheme createUnifiedTheme({ ...createBaseThemeOptions({ palette: palettes.light, }), defaultPageTheme: home, components: { /** ts-ignore This is temporarily necessary until MUI V5 transition is completed. */ BackstageHighlightedSearchResultText: { styleOverrides: { highlight: { color: inherit, backgroundColor: inherit, fontWeight: bold, textDecoration: underline, }, }, }, }, });关键点是components.BackstageHighlightedSearchResultText.styleOverrides.highlight这一层级——它精确命中搜索结果高亮组件的内部样式槽。color与backgroundColor设为inherit表示沿用当前主题色而fontWeight与textDecoration决定了高亮词的视觉强调方式你可以按需替换为任意 CSS 属性。自定义主题在新前端系统中以扩展extension的形式安装。安装自定义主题的详细方法见扩展配置文档。五、使用扩展渲染搜索结果搜索结果扩展Search result extensions让你能够定制用于渲染搜索结果项的组件。你可以提供自己的搜索结果项扩展也可以直接使用插件包提供的现成扩展。5.1 提供搜索结果列表项扩展在新前端系统中搜索结果列表项扩展通过backstage/plugin-search-react/alpha导出的SearchResultListItemBlueprint创建import { SearchResultListItemBlueprint } from backstage/plugin-search-react/alpha; export const YourSearchResultListItem SearchResultListItemBlueprint.make({ name: your-result-item, params: { predicate: result result.type YOUR_RESULT_TYPE, component: async () { const { YourSearchResultListItem } await import(./components); return YourSearchResultListItem; }, }, });从源码看SearchResultListItemBlueprint.tsx该 Blueprint 的params支持三个字段component必填异步返回结果项组件predicate可选判断某条结果是否应由本扩展渲染默认返回true即渲染所有类型的结果icon可选结果项的图标。该 Blueprint 会自动挂载到page:search的items输入上并支持noTrack配置默认false用于控制是否上报分析事件组件本身由ExtensionBoundary包裹以保证独立性与容错。扩展创建后从插件的 alpha 入口导出插件安装时会被自动发现。仓库内已有现成范例Catalog 插件在 plugins/catalog/src/alpha/searchResultItems.tsx 中即通过该 Blueprint 提供自己的搜索结果项。5.2 从应用侧提供扩展如果你需要在应用侧而非插件提供搜索结果列表项扩展需要将它包在前端模块frontend module中再传给createAppimport { createFrontendModule } from backstage/frontend-plugin-api; import { YourSearchResultListItem } from ./YourSearchResultListItem; export const searchCustomizations createFrontendModule({ pluginId: search, extensions: [YourSearchResultListItem], });import { createApp } from backstage/frontend-defaults; import { searchCustomizations } from ./search/searchModule; const app createApp({ features: [searchCustomizations], }); export default app.createRoot();注意这里pluginId: search必须与目标插件search 插件的 ID 一致扩展才会被正确附加到搜索页面上。5.3 搜索结果项排序规则当安装了多个搜索结果列表项扩展时搜索页面会按以下规则渲染页面依据各扩展的predicate函数对结果进行匹配第一个 predicate 命中的扩展负责渲染该条结果没有 predicate 的扩展充当兜底渲染器fallback renderer应放在最后以保证它能接住所有未被特定扩展匹配的结果。因此在组织扩展顺序时应将带predicate的专用结果项放在前面将无 predicate 的通用兜底项放在最后。另外还有其他更细分的搜索结果布局组件同样接受结果项扩展可参考SearchResultList与SearchResultGroup两个组件的 Storybook 示例搜索with result item extensions相关 story了解如何在分组列表中注入自定义结果项。六、小结本指南围绕 Backstage Search 的四个高级定制点给出了完整实践路径并提供了源码级依据定制诉求核心入口源码依据自定义搜索后端/查询行为实现SearchApicreateApiExtension覆盖默认扩展apis.ts、alpha.tsx定制 Catalog/TechDocs 索引字段collator 的entityTransformer/documentTransformerDefaultCatalogCollatorFactory.ts、DefaultTechDocsCollatorFactory.ts定制高亮样式统一主题的BackstageHighlightedSearchResultTexttheming 文档定制结果项渲染SearchResultListItemBlueprint frontend moduleSearchResultListItemBlueprint.tsx需要注意的记忆点authorization与location字段由 collator 工厂在转换器之外强制写入不可通过entityTransformer修改location仅可通过locationTemplate调整。希望这篇指南能帮助你在不修改 Backstage 框架代码的前提下把搜索能力打磨成完全贴合自己门户的产品。【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表