LabHub
学习 学习路径 课程

CBA — Backstage 认证助理

Backstage 应用仓库与插件接线

在 LabHub 中继续学习

目标

亲手搭建 create-app 生成的 Backstage 应用仓库结构,并创建一个内部插件,将其接入前端和后端。实验 Pod 无法访问互联网,不能下载 Node 依赖,因此不进行构建,只处理目录结构和接线。

为什么重要

使用 Backstage 意味着你会拥有一个自己的 monorepo。如果无法回答“该修改哪个文件”,就无法进行任何定制,而且这个答案也无法从界面上找到。实践中尤其有三个问题反复阻碍开发者。第一,package.json 中的一个角色标记就决定该包的构建方式。第二,在新后端系统中,插件和模块不是同一种东西;名称含 module 的包若没有与之配套的插件,就不会做任何事。第三,如果只在实体页面添加标签页而不注册应用路由,标签页虽然可见,点击后却是空白页,也不会显示错误。本实验将亲手搭建这三个关键位置。

步骤

  1. 编写 /root/cba-app/package.json:设置 private: true;在 workspaces.packages 中加入 packages/*plugins/*;在 scripts 中加入 devbuild:alltsctest:allbuild:all 必须是以 backstage-cli repo build 开头的命令,test:all 必须是以 backstage-cli repo test 开头的命令。
  2. 编写 /root/cba-app/packages/app/package.json:设置 name: appbackstage.role: frontend,并让 scripts.startbackstage-cli package start。同时编写 /root/cba-app/packages/backend/package.json:设置 name: backendbackstage.role: backend,让 main 指向以 dist/ 开头的路径,并让 scripts.start 使用相同命令。
  3. 编写 /root/cba-app/packages/backend/src/index.ts:从 @backstage/backend-defaults 导入并调用 createBackend,准确写七次 backend.add(import('...'))。注册以下包:@backstage/plugin-app-backend@backstage/plugin-catalog-backend@backstage/plugin-catalog-backend-module-github@backstage/plugin-scaffolder-backend@backstage/plugin-techdocs-backend@backstage/plugin-auth-backend@backstage/plugin-auth-backend-module-github-provider。最后调用 backend.start(),且不要留下 createRouterPluginEnvironmentapiRouter 等旧后端方式的痕迹。
  4. 编写 /root/cba-app/plugins/oncall/package.json:设置 name: @internal/plugin-oncallbackstage.role: frontend-pluginsideEffects: false,并在 dependencies 中加入 @backstage/core-plugin-api。同时编写 /root/cba-app/plugins/oncall-backend/package.json:设置 name: @internal/plugin-oncall-backendbackstage.role: backend-plugin,让 main 指向以 dist/ 开头的路径,并在 dependencies 中加入 @backstage/backend-plugin-api
  5. /root/cba-app/plugins/oncall/src/ 下编写三个文件。routes.ts 使用 createRouteRef 创建并导出 id: 'oncall'rootRouteRefplugin.ts./routes 导入该引用,用 createPlugin 创建 oncallPlugin,再用 createRoutableExtension 创建 OncallPage,并设置 mountPoint: rootRouteRef。不要在 plugin.ts 中再次调用 createRouteRefindex.ts 重新导出 oncallPluginOncallPage
  6. 编写 /root/cba-app/packages/app/src/components/catalog/EntityPage.tsx:从 @internal/plugin-oncall 导入 OncallPage,并在 isKind('component') 条件中使用 EntityLayout.Route 添加 path="/oncall"title="On-call" 的标签页。同时编写 /root/cba-app/packages/app/src/App.tsx:导入同一插件,并在 path="/oncall" 路由中把 <OncallPage /> 设为 element。
  7. /root/cba-app/packages.txt 中,逐行写出 packages/plugins/ 下所有包的名称与角色,格式为 이름=역할,去重并排序。
  8. 编写 /root/cba-app/.github/workflows/ci.yaml:使用 pull_request 触发器和 jobs.build.runs-on: ubuntu-latest,并准确设置六个 steps。第一步使用 actions/checkout,第二步使用 actions/setup-node,随后四步依次通过 run 执行 yarn install --immutableyarn tscyarn build:allyarn test:all

提示

工作区根目录

编写 /root/cba-app/package.json:设置 private: true;在 workspaces.packages 中加入 packages/*plugins/*;在 scripts 中加入 devbuild:alltsctest:allbuild:all 必须是以 backstage-cli repo build 开头的命令,test:all 必须是以 backstage-cli repo test 开头的命令。

根包不会发布。如果不把内部插件上传到注册表,要直接使用它们,就必须在工作区路径中包含插件目录。

两个应用及其角色

编写 /root/cba-app/packages/app/package.json:设置 name: appbackstage.role: frontend,并让 scripts.startbackstage-cli package start。同时编写 /root/cba-app/packages/backend/package.json:设置 name: backendbackstage.role: backend,让 main 指向以 dist/ 开头的路径,并让 scripts.start 使用相同命令。

backstage-cli 根据 package.json 中的一个角色标记选择构建方式。后端包的入口必须指向构建产物,而不是源代码。

新后端系统接线

编写 /root/cba-app/packages/backend/src/index.ts:从 @backstage/backend-defaults 导入并调用 createBackend,准确写七次 backend.add(import('...'))。注册以下包:@backstage/plugin-app-backend@backstage/plugin-catalog-backend@backstage/plugin-catalog-backend-module-github@backstage/plugin-scaffolder-backend@backstage/plugin-techdocs-backend@backstage/plugin-auth-backend@backstage/plugin-auth-backend-module-github-provider。最后调用 backend.start(),且不要留下 createRouterPluginEnvironmentapiRouter 等旧后端方式的痕迹。

新后端系统无需手动连接路由。名称含 module 的包不能独立工作,因此必须同时注册与之配套的插件。

内部插件包

编写 /root/cba-app/plugins/oncall/package.json:设置 name: @internal/plugin-oncallbackstage.role: frontend-pluginsideEffects: false,并在 dependencies 中加入 @backstage/core-plugin-api。同时编写 /root/cba-app/plugins/oncall-backend/package.json:设置 name: @internal/plugin-oncall-backendbackstage.role: backend-plugin,让 main 指向以 dist/ 开头的路径,并在 dependencies 中加入 @backstage/backend-plugin-api

内部插件不发布到注册表,因此使用内部作用域名称。前端插件声明无副作用,让打包器可以移除未使用的代码。

插件的三个源文件

/root/cba-app/plugins/oncall/src/ 下编写三个文件。routes.ts 使用 createRouteRef 创建并导出 id: 'oncall'rootRouteRefplugin.ts./routes 导入该引用,用 createPlugin 创建 oncallPlugin,再用 createRoutableExtension 创建 OncallPage,并设置 mountPoint: rootRouteRef。不要在 plugin.ts 中再次调用 createRouteRefindex.ts 重新导出 oncallPluginOncallPage

创建路由引用的位置必须只有一个。把该引用设为页面扩展的挂载点。

实体页面标签与应用路由

编写 /root/cba-app/packages/app/src/components/catalog/EntityPage.tsx:从 @internal/plugin-oncall 导入 OncallPage,并在 isKind('component') 条件中使用 EntityLayout.Route 添加 path="/oncall"title="On-call" 的标签页。同时编写 /root/cba-app/packages/app/src/App.tsx:导入同一插件,并在 path="/oncall" 路由中把 <OncallPage /> 设为 element。

添加标签页和注册路由位于不同文件。只完成一边时,界面不会报错,却什么也不会显示。

包清单

/root/cba-app/packages.txt 中,逐行写出 packages/plugins/ 下所有包的名称与角色,格式为 이름=역할,去重并排序。

角色值由每个包自行声明。不要手工填写,应从文件中读取并汇总。

CI 门禁

编写 /root/cba-app/.github/workflows/ci.yaml:使用 pull_request 触发器和 jobs.build.runs-on: ubuntu-latest,并准确设置六个 steps。第一步使用 actions/checkout,第二步使用 actions/setup-node,随后四步依次通过 run 执行 yarn install --immutableyarn tscyarn build:allyarn test:all

门禁必须在合并前运行,且安装后应先进行类型检查。如果安装步骤允许修改锁文件,门禁就失去了保障作用。