Backstage 插件配置完全指南:从安装、特性发现到 app.extensions 深度定制
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
本篇指南面向使用 Backstage 新前端系统(New Frontend System,新创建应用中的默认方案)的开发者,围绕如何为 Backstage App 安装既有插件、利用特性发现(Feature Discovery)免代码接入插件、通过app.extensions静态配置深度定制扩展,以及手动安装插件的完整流程展开。读完本文,你将掌握从yarn安装一个前端插件到通过配置文件控制其启用状态、挂载位置与参数配置的完整实战能力,并能理解底层实现原理。
前置说明:新旧前端系统的区别
本文档默认你使用的是新前端系统(New Frontend System),它是新创建的 Backstage 应用的默认方案。如果你的应用仍在使用旧前端系统(基于FlatRoutes、SidebarItem等组件手动装配路由与导航),请阅读旧版指南 configure-app-with-plugins--old.md,那里保留了旧系统下的完整操作步骤(手动添加Route、在Root.tsx中维护SidebarItem)。
另外,Backstage 插件主要使用 TypeScript、Node.js 和 React 编写,理解这三项技术有助于后续自定义工作。插件生态非常丰富:官方维护了插件目录,社区也通过 Community Plugins 仓库共享了大量覆盖 CI/CD、监控、审计等常见基础设施需求的插件。
插件、扩展与应用装配:先理解核心概念
在新前端系统中,Backstage 的功能由插件(Plugin)承载,而插件的能力通过扩展(Extension)对外暴露。应用实例(App Instance)本身不做具体工作,它只负责把各插件以"特性(Feature)"的形式提供出来的扩展装配成一棵应用扩展树(App Extension Tree):树中每个节点都是一个扩展,节点从子节点接收数据、向父节点传递数据,最终由内置的根扩展输出 React 元素完成渲染。
从源码看,createApp是装配入口:它依次加载配置、通过特性发现收集插件、再与显式传入的features合并后交给prepareSpecializedApp构建应用树(见 createApp.tsx)。理解这一模型后,下面四种插件接入方式就都顺理成章了。
第一步:安装插件包
假设你已经创建好了 Backstage 应用(参考 创建应用指南),现在以社区流行的Tech Radar 插件为例,说明如何为应用添加一个既有插件。
首先在应用根目录执行:
yarn --cwd packages/app add @backstage-community/plugin-tech-radar需要注意几点:
- 包被添加到
packages/app包,而不是根package.json。Backstage 应用是采用 Yarn Workspaces 搭建的 monorepo:前端 UI 插件一般加到app文件夹,后端插件则加到backend文件夹。上面命令中的--cwd packages/app正是为了把依赖写进app包。 - 每个插件通常自带安装与配置文档,安装前建议先查阅对应插件的说明。
第二步:验证插件可用(特性发现机制)
新前端系统下,插件装好即用——无需修改任何代码。这是因为应用默认开启了特性发现(Feature Discovery),它会自动扫描app包的依赖并安装其中的插件。该机制由app-config.yaml中的默认配置启用:
app: packages: all开启后,直接yarn start启动应用,浏览器访问/tech-radar即可看到 Tech Radar 页面。
特性发现的工作原理
从源码实现看,特性发现依赖@backstage/cli的构建过程:CLI 在 Webpack 编译时扫描app包的兼容依赖,把它们注入到window['__@backstage/discovered__']全局对象中;应用启动后,discovery.ts 读取app.packages配置,再对注入的模块列表做 include/exclude 过滤,最终将匹配的模块转换为可装配的特性。因此使用特性发现的前提是你的应用由@backstage/cli构建(所有新 Backstage 应用默认如此)。
用 include / exclude 精确控制发现范围
如果不希望"全部扫描",可以改用过滤器精确控制哪些包参与发现:
app: packages: include: - '@backstage/plugin-catalog' - '@backstage/plugin-scaffolder'app: packages: exclude: - '@backstage/plugin-catalog'两点提示:
- 配置值
all之外的字符串是非法的,源码会在 readPackageDetectionConfig 中直接抛错; - 你不需要把同时在代码里手动安装的包加入 exclude——应用会对插件实例做去重,两种方式并存不会造成冲突。
这个例子中的 Tech Radar 是独立使用的页面型插件;而有些插件是用于注解或支撑软件目录(Software Catalog)中特定实体(Entity)的,它们会被挂在应用的其他位置(如实体页卡片),接入方式会略有不同。
第三步(可选):通过 app.extensions 配置插件
插件接入后,还可以在app-config.yaml的app.extensions节下对其扩展做静态配置。例如为 Tech Radar 页面指定挂载路径:
app: extensions: - page:tech-radar: config: path: /tech-radar扩展配置的完整 Schema
app.extensions是一个数组(而不是对象),每个数组项最完整的写法如下:
app: extensions: - <id>: attachTo: id: <parent-id> input: <input-name> disabled: <true/false> config: <extension-specific-config>其中attachTo、disabled、config三个顶层字段都是可选的——每个扩展实现都必须为其提供默认值。各字段含义:
| 字段 | 作用 | 说明 |
|---|---|---|
attachTo | 指定扩展挂载到哪个父扩展的哪个输入槽 | 含id(父扩展 ID)与input(输入槽名)两个必填字符串 |
disabled | 启用 / 禁用该扩展 | 接受布尔值,也接受字符串'true'/'false'(见下文环境变量场景) |
config | 传入扩展专属的静态配置 | 必须是对象,具体键值取决于扩展自身定义 |
三种简化写法(Shorthand)
除完整对象外,还提供多种简写形式:
1. 仅写扩展 ID 字符串——等价于disabled: false:
app: extensions: - '<id>'2. 以布尔值启用 / 禁用单个扩展:
app: extensions: - <id>: <true/false>3. 用环境变量控制开关。由于配置中的环境变量替换总是产出字符串而非真正的布尔值,disabled字段以及上面的布尔简写都额外接受字符串'true'和'false',因此可以这样写,让开关来自环境变量:
app: extensions: - <id>: ${SOME_EXTENSION_ENABLED}从源码看配置是如何被解析的
app.extensions的解析逻辑位于 readAppExtensionsConfig.ts 与 expandShorthandExtensionParameters,源码明确约束了以下几点:
app.extensions必须是数组,否则抛出类型错误;- 数组项必须是字符串或单键对象,且扩展 ID 不能为空、不能包含首尾空白;
- 字符串
'true'/'false'会被显式转换为布尔值(对应环境变量替换场景); - 对象形式下仅识别
attachTo、disabled、config三个键,出现其他键会报unknown parameter错误; attachTo.id、attachTo.input必须是非空字符串。
仓库中的真实配置示例
当前仓库的 app-config.yaml 就是一份丰富的参考样板,例如:
- 禁用某个扩展:
- home-page-widget:home/random-joke: false; - 配置 Home 页各 Widget 的网格布局(
page:home的defaultConfig按行列与宽高排布搜索栏、收藏实体、世界时钟等组件); - 配置目录实体页(
page:catalog/entity)的 tab 分组、标题、图标,甚至可以- development: false禁用某个默认分组; - 配置各类实体卡片(
entity-card:*)的显示参数,如entity-card:org/user-profile的maxRelations、hideIcons; - 重定向实体内容(
entity-content:*)到指定分组,例如- entity-content:api-docs/apis的group: documentation。
这些示例演示了"插件装好只是开始,真正贴合业务的是按需配置扩展"。更全面的格式说明参见 配置扩展指南;某个插件具体支持哪些config键,以该插件自身文档为准。
第四步(可选):手动安装插件
如果你需要更精细地控制插件安装,或应用未开启特性发现,可以改为手动安装:导入插件并传入createApp的features数组。
import { createApp } from '@backstage/frontend-defaults'; import techRadarPlugin from '@backstage-community/plugin-tech-radar/alpha'; const app = createApp({ features: [techRadarPlugin], }); export default app.createRoot();从 createApp.tsx 的源码可以看到,createApp内部会把自动发现的特性与options.features中手动传入的特性合并后一起装配,这正是"手动安装与自动发现并存不会冲突"的实现基础。手动安装的典型场景包括:
- 需要控制插件顺序,例如自定义路由优先级时;
- 应用未开启
app.packages: all; - 使用尚未适配新前端系统的第三方插件——此时可借助
@backstage/core-compat-api的转换工具(如convertLegacyPlugin、convertLegacyAppRoot)将旧插件包装为新特性。当前仓库的 App.tsx 就同时演示了手动传入插件、convertLegacyAppRoot包装旧路由,以及用plugin.withOverrides覆盖 catalog 扩展图标等多种做法,是非常值得对照的完整示例。
更全面的安装方式与替代方案参见 安装插件指南。
侧边栏是怎么工作的
新前端系统下,提供页面的插件会自动在侧边栏注册导航项,绝大多数插件都无需你手动添加SidebarItem。如果你需要自定义侧边栏行为——比如调整顺序、分组、加入自定义条目——可以通过覆盖内置的app/nav扩展实现,具体做法参见 迁移指南的侧边栏章节。
进阶:插件信息与运行时覆盖
除了上述扩展级配置,新前端系统还支持在app.extensions之外对插件本身的信息做静态覆盖。在 app-config.yaml 中可以看到app.pluginOverrides的真实用法:可按pluginId或packageName匹配插件(支持/<pattern>/正则写法),并覆写ownerEntityRefs、description等信息,例如把 catalog 相关插件的负责人统一指向某个团队。这与createApp中自定义pluginInfoResolver的能力共同构成了插件元信息体系,详见 应用架构文档。
小结
至此,一条从"安装插件"到"深度定制"的完整链路已经打通:
- 安装:
yarn --cwd packages/app add <插件包>,依赖写入app包; - 自动接入:
app.packages: all开启特性发现,装完即用,无需改代码; - 静态配置:在
app.extensions数组中以完整对象或简写形式控制扩展的挂载(attachTo)、启停(disabled)与参数(config); - 手动安装:需要精细控制时,通过
createApp({ features: [...] })显式装配,并可对旧插件做兼容转换; - 导航与元信息:页面插件的侧边栏导航自动生成,插件信息可经
pluginOverrides静态覆盖。
无论你是要快速接入社区插件,还是希望把应用扩展编排得完全贴合团队规范,以上配置方式都构成了 Backstage 前端定制的基础能力。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考