4. 创建第一个插件:使用 create-plugin 模板、插件目录结构、基础 Hello World 插件

在完成 Backstage 开发环境搭建与基线核验后,本章将引导你创建第一个插件。通过官方提供的 create-plugin 模板,你将快速理解插件的标准目录结构,并实现一个基础的 Hello World 插件,为后续的调试与定制打下坚实基础。

4.1 使用 create-plugin 模板创建插件

Backstage 提供了 yarn new 命令,用于从内置模板快速生成插件骨架。该命令会自动处理依赖安装、配置注册等繁琐步骤。

操作前提:确保已成功运行 yarn dev 并能在浏览器中访问 Backstage 应用。建议在 packages/app 目录下执行创建命令,以便插件自动注册到前端应用。

4.1.1 执行创建命令

# 进入 Backstage 根目录
cd backstage

# 使用 yarn new 创建插件
yarn new --select plugin

# 根据提示输入插件名称,例如:hello-world
# 插件 ID: hello-world
# 插件所有者: user:default/guest

命令执行完成后,控制台会输出成功信息,并在 plugins/ 目录下生成名为 hello-world 的文件夹。

4.1.2 验证插件注册

模板会自动完成以下注册步骤,无需手动修改配置文件:

  • 前端路由注册:在 packages/app/src/App.tsx 中自动添加路由引用。
  • 侧边栏菜单注册:在 packages/app/src/components/Root/Root.tsx 中自动添加侧边栏导航项。
  • 插件包依赖:在 packages/app/package.json 中自动添加对 @internal/plugin-hello-world 的引用。
基线核验点:重新运行 yarn dev,在侧边栏应能看到新增的 "Hello World" 菜单项,点击后页面显示 "Welcome to hello-world!" 字样。

4.2 插件目录结构解析

生成的插件骨架遵循 Backstage 官方推荐的模块化结构。下表列出了核心文件及其职责:

文件/目录 类型 职责说明
src/index.ts 入口文件 导出插件实例、路由绑定、扩展点注册
src/plugin.ts 插件定义 创建 createPlugin 实例,定义插件元数据
src/components/ExampleComponent/ 组件目录 存放插件主页面组件,默认包含 ExampleComponent.tsx
src/routes.ts 路由定义 声明插件内部路由路径与引用
package.json 包配置 插件名称、版本、依赖、导出路径
README.md 文档 插件说明、开发指引、维护信息
dev/ 开发目录 独立运行插件的开发入口,用于本地调试

下图展示了插件目录的核心层级关系与数据流向:

Backstage 插件目录结构图 插件目录结构(hello-world) plugins/hello-world/ src/ dev/ package.json index.ts plugin.ts routes.ts components/ ExampleComponent.tsx 说明: dev/ 目录用于独立调试插件, 不参与生产构建。 package.json 定义插件元数据与依赖。

4.3 基础 Hello World 插件实现

模板生成的 ExampleComponent.tsx 已经包含一个基础页面。我们将其改造为更清晰的 Hello World 示例,并理解核心代码逻辑。

4.3.1 核心文件代码解读

1. 插件定义文件(src/plugin.ts)

import { createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';
import { rootRouteRef } from './routes';

export const helloWorldPlugin = createPlugin({
  id: 'hello-world',
  routes: {
    root: rootRouteRef,
  },
});

export const HelloWorldPage = helloWorldPlugin.provide(
  createRoutableExtension({
    name: 'HelloWorldPage',
    component: () => import('./components/ExampleComponent').then(m => m.ExampleComponent),
    mountPoint: rootRouteRef,
  }),
);

2. 页面组件文件(src/components/ExampleComponent/ExampleComponent.tsx)

import React from 'react';
import { Typography, Grid } from '@material-ui/core';
import { InfoCard, Header, Page, Content } from '@backstage/core-components';

export const ExampleComponent = () => (
  <Page themeId="tool">
    <Header title="Hello World 插件" subtitle="服务目录平台基线核验示例" />
    <Content>
      <Grid container spacing={3}>
        <Grid item xs={12}>
          <InfoCard title="欢迎使用 Backstage 插件">
            <Typography variant="body1">
              这是你的第一个 Backstage 插件。插件已成功注册并运行。
            </Typography>
            <Typography variant="body2" color="textSecondary">
              插件 ID: hello-world | 框架版本: @backstage/core-plugin-api
            </Typography>
          </InfoCard>
        </Grid>
      </Grid>
    </Content>
  </Page>
);

4.3.2 插件运行流程

下图展示了从用户点击侧边栏到页面渲染的完整调用链路:

Hello World 插件运行流程 Hello World 插件运行流程 用户点击侧边栏 "Hello World" 菜单 路由匹配 App.tsx 路由表 插件加载 plugin.ts 实例化 组件渲染 ExampleComponent 关键路径说明: 1. 侧边栏菜单在 Root.tsx 中通过 SidebarItem 注册 2. 路由绑定在 App.tsx 中通过 FlatRoutes 完成 3. 插件懒加载:点击菜单时才加载组件代码

4.4 常见问题与基线核验清单

注意:如果创建插件后侧边栏未显示或页面报错,请优先检查以下三项:
1. packages/app/package.json 中是否包含 @internal/plugin-hello-world 依赖。
2. packages/app/src/App.tsx 中是否导入 HelloWorldPage 并注册到路由。
3. 是否重新执行了 yarn install 或 yarn dev 使配置生效。

完成本章操作后,请对照以下清单进行基线核验:

核验项 预期结果 状态
插件目录生成 plugins/hello-world/ 目录存在,包含 src、dev、package.json ☐ 通过
侧边栏菜单 左侧导航栏出现 "Hello World" 菜单项 ☐ 通过
页面渲染 点击菜单后显示 "Hello World 插件" 标题与欢迎卡片 ☐ 通过
控制台无报错 浏览器开发者工具无红色错误日志 ☐ 通过
热更新生效 修改组件文本后,浏览器自动刷新显示新内容 ☐ 通过

至此,你已经成功创建并运行了第一个 Backstage 插件。该插件虽然简单,但完整覆盖了插件注册、路由绑定、组件渲染的核心链路,为后续开发复杂功能插件提供了可复用的骨架模板。