ARTICLE DETAIL

资讯详情

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

在 Backstage 中集成 Confluence 搜索:Collator 与结果项组件的完整接入指南

在 Backstage 中集成 Confluence 搜索:Collator 与结果项组件的完整接入指南 在 Backstage 中集成 Confluence 搜索Collator 与结果项组件的完整接入指南【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage[!NOTE] 本文内容基于仓库contrib/search/confluence目录下的原始实现整理。该目录文档已标注为弃用deprecated官方推荐改用社区维护的backstage-community/plugin-search-backend-module-confluence-collator插件。本文仅用于帮助读者理解 Backstage 搜索插件接入第三方文档源Collator的完整技术原理与历史实现路径若用于生产环境请优先评估社区插件方案。导读Backstage 搜索插件通过「Collator文档收集器」从各类数据源抓取文档并构建全文索引。本篇文章聚焦仓库 contrib/search/confluence 提供的 Confluence 搜索集成方案完整讲解如何把 Atlassian Confluence 空间与页面作为搜索源接入 Backstage包括后端ConfluenceCollator的 REST API 调用逻辑、前端ConfluenceResultListItem结果项组件以及前后端注册代码的落地位置。读完本文你将掌握 Backstage 搜索插件中「数据收集器 结果展示组件」双端协作的标准接入范式并能据此扩展出任意第三方文档源的搜索集成。集成概述把 Confluence 变成 Backstage 的搜索源Backstage 的搜索插件采用「索引构建器IndexBuilder 调度器Scheduler 搜索引擎」的架构Collator 负责从数据源收集文档并归一化为可索引结构Decorator 负责对文档做加工搜索引擎负责存储与检索。本目录提供的两个文件正是这条链路中的两端文件角色部署位置ConfluenceCollatorConfluenceCollator.md 中的参考实现后端文档收集器调用 Confluence REST API 拉取空间与页面packages/backend/src/plugins/search/ConfluenceResultListItemConfluenceResultListItem.md 中的参考实现前端搜索结果项组件渲染标题、摘要并跳转原页面packages/app/src/components/search/接入流程分为三步先把两个文件复制到 Backstage 应用的对应目录再在前端SearchPage.tsx中为confluence类型注册渲染组件最后在后端search.ts中把ConfluenceCollator注册进indexBuilder。弃用说明与社区替代方案目录 README.md 开头的[!NOTE]明确指出本文档已弃用将在未来移除官方建议使用社区插件backstage-community/plugin-search-backend-module-confluence-collator。这意味着本文讲解的ConfluenceCollator.ts与ConfluenceResultListItem.tsx属于早期的参考实现其主要价值在于揭示搜索插件扩展机制的原理。生产环境部署时应优先查看社区插件仓库的安装与配置文档。后端接入复制 Collator 文件到搜索插件目录按照 README.md 的指引首先把本目录下的两个文件复制到 Backstage 应用的packages/backend/src/plugins/search/路径下。该路径是旧版非新后端系统Backstage 应用后端插件默认的代码组织位置后端搜索插件的路由与 Collator 注册通常都集中在这里packages/backend/src/plugins/search/ ├── ConfluenceCollator.ts # 新增Confluence 文档收集器 └── ConfluenceResultListItem.tsx # 注意该组件实际应置于前端见下文需要说明的是ConfluenceResultListItem是 React 组件实际使用位置是前端packages/app/src/components/search/README 中的代码示例也印证了这一点。原 README 要求将本目录两个文件都放到后端 search 路径下的表述更像一份宽松的放置说明实操时建议把 Collator 放后端、结果组件放前端保持前后端职责清晰。前端接入在 SearchPage 中渲染 Confluence 结果在 Backstage 应用前端的 SearchPage.tsx 中搜索页通过useSearch拿到查询结果后会根据文档的type字段选择对应的结果项组件渲染。接入 Confluence 需要在两处改动1. 引入结果项组件import { ConfluenceResultListItem } from ./ConfluenceResultListItem;2. 在类型分发中注册 confluence 分支搜索结果组件通常维护一个从document.type到渲染组件的映射在SearchPage.tsx中补上confluence分支即可case confluence: return ( ConfluenceResultListItem key{document.location} result{document} / );这里的关键关联点是document.typeCollator 通过public readonly type: string confluence声明了自己的文档类型详见后文前端正是靠这个 type 值把搜索结果路由到ConfluenceResultListItem。result属性接收的是IndexableDocument即搜索插件定义的统一文档结构。IndexableDocument 的字段契约ConfluenceResultListItem的 Props 类型定义如下type Props { result: IndexableDocument; };它依赖result的text、title、location三个字段title文档标题显示为结果项的主标题text文档正文用于生成摘要该组件会先截取前 500 字符做 HTML 标签剥离再取前 80 字符展示location文档的跳转链接指向 Confluence 页面 web UI。这恰好对应后端 Collator 返回的文档结构{ title, text, location }前后端通过IndexableDocument这一契约完成对接。IndexableDocument接口定义在 plugins/search-common/src/types.ts是搜索插件所有 Collator 输出与搜索结果的通用数据形状。结果项组件解析剥离 HTML 与展示摘要ConfluenceResultListItem.md 提供了ConfluenceResultListItem.tsx的完整参考实现它展示了三个值得关注的处理点1. 手工剥离 HTML 标签Confluence REST API 返回的body.storage.value是富文本 HTML。组件在渲染摘要前用一个简单的字符级状态机把...标签剥离掉只保留纯文本const chars []; let isTag false; for (const c of result.text.substring(0, 500)) { if (c ) { isTag true; continue; } if (c ) { isTag false; chars.push( ); continue; } if (!isTag) { chars.push(c); } } const excerpt chars.join().substring(0, 80) (result.text.length 80 ? ... : );处理策略总结先截取原文前 500 字符控制计算量剔除标签后取前 80 字符若原文超过 80 字符则追加...。这是早期参考实现的做法实际生产中可以替换为更健壮的 DOM 解析方案。2. 结果项布局Link to{result.location} ListItem alignItemscenter ListItemIcon img width20 height20 srchttps://cdn.worldvectorlogo.com/logos/confluence-1.svg / /ListItemIcon ListItemText primaryTypographyProps{{ variant: h6 }} primary{result.title} secondary{excerpt} / /ListItem Divider / /LinkLink来自backstage/core-componentsto指向result.location点击即可跳转到原始 Confluence 页面ListItem/ListItemIcon/ListItemText/Divider来自 Material-UI当前仓库该历史实现使用的版本为material-ui/core用于组织列表布局图标使用 Confluence 的 SVG Logo作为结果项的视觉标识。3. 组件导出方式该组件以命名导出export const ConfluenceResultListItem ...方式暴露这符合 Backstage 仓库自身的编码约定——ADRs 中明确提倡避免默认导出参见 adr003-avoid-default-exports.md因此在SearchPage.tsx中需要用import { ConfluenceResultListItem } from ./ConfluenceResultListItem的形式引入。后端核心ConfluenceCollator 的 REST API 调用链ConfluenceCollator.md 给出了ConfluenceCollator.ts的完整参考实现它实现了backstage/plugin-search-common的DocumentCollator接口。整个收集过程分为三个阶段对应三次对 Confluence REST API 的调用阶段一获取全部全局空间getSpacesasync function getSpaces(): Promisestring[] { const data await getConfluenceData( ${ConfluenceUrlBase}/space?limit1000typeglobalstatuscurrent, ); // 从 data[results] 中逐个取出 result[key] 作为空间 key }调用 Confluence REST API 的/wiki/rest/api/space端点带limit1000、typeglobal、statuscurrent参数拉取所有处于 current 状态的全局空间仅保留每个空间的key字段。阶段二按空间分页拉取页面getDocumentsFromSpaceslet requestUrl ${ConfluenceUrlBase}/content?limit1000statuscurrentspaceKey${space}; while (next) { const data await getConfluenceData(requestUrl); // 收集 data[results][]._links.self页面详情 URL if (data[_links][next]) { requestUrl data[_links][base] data[_links][next]; } else { next false; } }对每个空间调用/wiki/rest/api/content端点按spaceKey过滤、limit1000分页从results中收集每个页面的_links.self即页面详情资源的 URL。分页通过_links.next与_links.base拼接下一页 URL直到没有下一页为止。阶段三逐页拉取正文并归一化getDocumentInfoconst data await getConfluenceData(documentUrl ?expandbody.storage); if (data[status] data[status] current) { const documentMetaData { title: data[title], text: data[body][storage][value], location: data[_links][base] data[_links][webui], }; documentInfo.push(documentMetaData); }对每个页面 URL 追加?expandbody.storage参数一次性取回标题、HTML 正文与页面 Web 地址组装成{ title, text, location }结构——这正是前端ConfluenceResultListItem消费的数据形态。status current的判断确保已归档或已删除的页面不会被收录。统一出口execute() 与 type 声明export class ConfluenceCollator implements DocumentCollator { public readonly type: string confluence; async execute() { const spacesList await getSpaces(); const documentsList await getDocumentsFromSpaces(spacesList); const documentMetaDataList await getDocumentInfo(documentsList); return documentMetaDataList; } }type confluence是文档类型标识后端IndexBuilder会以它为索引名/类型名见下文源码前端也用它做结果项路由execute()串联三个阶段返回文档元数据数组。鉴权方式Basic Auth 与 CONFLUENCE_TOKEN 环境变量所有 API 请求都通过统一封装的getConfluenceData发起const res await fetch(requestUrl, { method: get, headers: { Authorization: Basic ${process.env.CONFLUENCE_TOKEN}, }, });使用 HTTP Basic 鉴权process.env.CONFLUENCE_TOKEN存放 base64 编码后的用户名:API Token凭据需要提前在 Backstage 后端进程的环境变量中配置网络请求使用cross-fetch历史实现当前仓库的核心依赖已迁移到 Node 原生fetch可参见 ADR adr014-use-fetch.md失败兜底请求失败或响应非ok时返回空对象{}调用方对results做空值判断后安全退出保证单个空间或页面失败不会拖垮整个收集任务。后端注册把 Collator 挂进 indexBuilder在packages/backend/src/plugins/search.ts中完成两步注册1. 引入 ConfluenceCollatorimport { ConfluenceCollator } from ./search/ConfluenceCollator;2. 注册到索引构建器indexBuilder.addCollator({ defaultRefreshIntervalSeconds: 600, collator: new ConfluenceCollator(), });defaultRefreshIntervalSeconds: 600表示每 600 秒10 分钟重新执行一次收集任务让新发布的 Confluence 页面能被周期性收录进索引。注册完成后indexBuilder.build()会把所有已注册 Collator 编译成调度任务交给Scheduler周期性执行。源码印证addCollator 的调度与类型注册机制通过阅读当前仓库源码可以确认indexBuilder.addCollator的底层行为。IndexBuilder类定义在 plugins/search-backend-node/src/IndexBuilder.ts其addCollator实现如下addCollator(options: RegisterCollatorParameters): void { const { factory, schedule } options; this.logger.info( Added ${factory.constructor.name} collator factory for type ${factory.type}, ); this.collators[factory.type] { factory, schedule, }; this.documentTypes[factory.type] { visibilityPermission: factory.visibilityPermission, }; }以factory.type为键存储 collator并同步登记文档类型信息documentTypesRegisterCollatorParameters接口见 plugins/search-backend-node/src/types.ts要求提供schedule调度器任务运行器与factory返回文档收集器的工厂。README 示例中defaultRefreshIntervalSeconds这种简写形式属于旧版IndexBuilder.addCollator的便捷参数最终都会被编译为对应的调度任务注册完成后build()会将 Collator 包装进Scheduler见 plugins/search-backend-node/src/Scheduler.ts由调度器在后台按间隔周期触发execute()把结果送入搜索引擎索引。DocumentCollator接口本身定义在 plugins/search-common/src/types.ts对每个 Collator 的要求正是type文档类型/索引名与getCollator()旧接口为execute()两要素ConfluenceCollator的实现完全符合这一契约。常见问题与排查要点搜索不到 Confluence 内容检查后端进程是否正确设置了CONFLUENCE_TOKEN环境变量确认indexBuilder.addCollator的注册代码已生效且build()被调用首次索引建立后需等待一个刷新周期或触发一次收集。部分页面缺失确认页面状态为currentAPI 会过滤非 current 页面检查空间是否属于global类型且为current状态分页是否被_links.next完整遍历。前端点开结果无跳转确认ConfluenceResultListItem收到的result.location是完整的 Confluence Web 地址由_links.base _links.webui拼接且SearchPage.tsx的case confluence分支已正确注册。类型不匹配前端case分支的字符串必须与 Collator 的type属性confluence完全一致否则搜索结果无法路由到对应组件。生产环境选型本实现已弃用若要在生产环境接入 Confluence 搜索请改用官方推荐的社区插件backstage-community/plugin-search-backend-module-confluence-collator其功能与配置方式以该插件仓库文档为准。小结contrib/search/confluence目录完整演示了 Backstage 搜索插件接入第三方文档源的端到端路径后端用ConfluenceCollator通过 REST API 拉取空间、分页抓取页面、归一化为{ title, text, location }文档并周期性送入索引前端用ConfluenceResultListItem按类型路由渲染搜索结果并跳转原文。虽然这份参考实现已被社区插件取代但其揭示的「Collator 类型契约 IndexBuilder 注册 前端类型分发渲染」的扩展模式适用于任何文档源的搜索集成是理解 Backstage 搜索插件架构的一份高质量样例。相关仓库资源集成说明与弃用声明contrib/search/confluence/README.md后端收集器参考实现contrib/search/confluence/ConfluenceCollator.md前端结果项参考实现contrib/search/confluence/ConfluenceResultListItem.md搜索文档契约接口plugins/search-common/src/types.ts索引构建器与调度机制plugins/search-backend-node/src/IndexBuilder.ts、plugins/search-backend-node/src/Scheduler.ts搜索后端插件注册入口plugins/search-backend/src/plugin.ts相关架构决策记录adr014-use-fetch.md、adr003-avoid-default-exports.md【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表