3. 插件开发基础:Backstage 插件架构、前端与后端分离、插件目录结构、Hello World 插件

3.1 Backstage 插件架构总览

Backstage 的插件系统采用前端与后端分离的微内核架构。每个插件都是一个独立的功能单元,通过统一的 App 壳(App Shell)进行集成。插件可以只包含前端(UI),也可以同时包含后端(Backend)以提供 API 或数据处理能力。

核心设计原则:插件不应直接依赖其他插件,而是通过 Backstage 提供的 Service 和 Plugin API 进行通信。前端通过 createPlugin 注册,后端通过 createBackendPlugin 注册。
Backstage 插件架构分层图 App Shell(应用壳) 插件层(Plugins) 前端插件 A 前端插件 B 后端插件 C 全栈插件 D 核心服务层(Core Services) 基础设施层(Database / Catalog / Auth)

3.2 前端与后端分离机制

Backstage 强制要求插件的前端和后端代码分离到不同的包中,这有助于职责清晰、独立部署和按需加载。

维度 前端(Frontend) 后端(Backend)
包名约定 @internal/plugin-xxx @internal/plugin-xxx-backend
入口文件 src/index.ts + src/plugin.ts src/index.ts + src/plugin.ts
主要依赖 @backstage/core-plugin-api @backstage/backend-plugin-api
注册方式 createPlugin({...}) createBackendPlugin({...})
通信方式 通过 fetchApi 或 discoveryApi 调用后端 通过 httpRouter 暴露 RESTful API
最佳实践:即使插件初期只需要前端展示,也建议预留后端包结构。当需要接入真实数据源或执行权限校验时,后端包可以快速扩展,避免重构。

3.3 插件目录结构详解

一个标准的 Backstage 插件(以全栈插件为例)遵循以下目录结构。我们以 plugins/capacity-watermark 作为示例。

plugins/capacity-watermark/          # 插件根目录
├── package.json                     # 插件元数据与依赖
├── README.md                        # 插件说明文档
├── src/                             # 前端源码
│   ├── index.ts                     # 前端入口,导出插件实例
│   ├── plugin.ts                    # 使用 createPlugin 注册
│   ├── components/                  # React 组件
│   │   ├── CapacityCard.tsx
│   │   └── CapacityTable.tsx
│   ├── routes.ts                    # 路由定义
│   └── types.ts                     # TypeScript 类型定义
├── dev/                             # 本地开发模拟数据
│   └── index.ts
├── config.d.ts                      # 插件配置类型声明
└── dist/                            # 构建产物(自动生成)

如果插件包含后端,则在后端包中遵循类似结构:

plugins/capacity-watermark-backend/  # 后端插件根目录
├── package.json
├── src/
│   ├── index.ts                     # 后端入口
│   ├── plugin.ts                    # 使用 createBackendPlugin 注册
│   ├── service/                     # 业务逻辑层
│   │   ├── CapacityService.ts
│   │   └── types.ts
│   ├── router.ts                    # 路由与 API 定义
│   └── run.ts                       # 独立运行入口(可选)
└── dist/
常见错误:将后端代码直接放在前端包的 src/ 目录下。这会导致构建时打包进前端 bundle,暴露后端逻辑且无法独立部署。务必使用 -backend 后缀的独立包。

3.4 Hello World 插件实战

下面我们通过一个极简的 Hello World 插件,演示从零到注册完成的全流程。该插件只包含前端,在 Backstage 页面中显示“Hello, Backstage!”。

步骤 1:使用模板创建插件

在 Backstage 根目录执行以下命令,选择 plugin 模板:

yarn new --select plugin
# 输入插件名称:hello-world
# 选择前端插件(Frontend plugin)

命令执行后,自动生成 plugins/hello-world/ 目录及基础文件。

步骤 2:编写插件核心代码

编辑 plugins/hello-world/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/HelloWorldPage').then(m => m.HelloWorldPage),
    mountPoint: rootRouteRef,
  }),
);

编辑 plugins/hello-world/src/components/HelloWorldPage.tsx:

import React from 'react';
import { Content, Header, Page } from '@backstage/core-components';

export const HelloWorldPage = () => {
  return (
    <Page themeId="tool">
      <Header title="Hello, Backstage!" />
      <Content>
        <p>这是您的第一个 Backstage 插件。</p>
      </Content>
    </Page>
  );
};

步骤 3:注册到 App

在 packages/app/src/App.tsx 中添加路由:

import { HelloWorldPage } from '@internal/plugin-hello-world';

// 在 FlatRoutes 中添加
<Route path="/hello-world" element={<HelloWorldPage />} />

在 packages/app/src/components/Root/Root.tsx 中添加侧边栏菜单项:

import { SidebarItem } from '@backstage/core-components';

// 在 Sidebar 中添加
<SidebarItem icon={ExtensionIcon} to="/hello-world" text="Hello World" />
Hello World 插件开发流程 1. yarn new 创建插件 2. 编写 plugin.ts 3. 创建组件 4. 注册路由 关键检查点: • 插件 id 必须唯一,建议使用 kebab-case 命名 • 组件必须使用 createRoutableExtension 包装,否则无法在 App 中挂载 • 路由路径 /hello-world 与 SidebarItem 的 to 属性必须一致

步骤 4:启动验证

在 Backstage 根目录执行 yarn dev,打开浏览器访问 http://localhost:3000/hello-world,应看到页面显示“Hello, Backstage!”标题。

验证清单:
  • 侧边栏出现“Hello World”菜单项
  • 点击菜单项后页面路由正确跳转
  • 页面 Header 显示“Hello, Backstage!”
  • 浏览器控制台无 404 或模块加载错误

3.5 本章小结

本章我们掌握了 Backstage 插件的前后端分离架构、标准目录结构,并通过 Hello World 插件走通了完整的开发与注册流程。这是后续实现容量水位巡检插件的基础骨架。