为现有 Monorepo 应用程序添加自定义插件
2020 年 9 月 15 日 - v0.1.1-alpha.21
This document takes you through setting up a new plugin for your existing > monorepo with a GitHub provider already setup. If you don't have either of > those, you can clone > simple-backstage-app > which this document builds on. > > This document does not cover authoring a plugin for sharing with the Backstage > community. That will have to be a later discussion. > > We start with a skeleton plugin install. And after verifying its > functionality, extend the Sidebar to make our life easy. Finally, we add > custom code to display GitHub repository information. > > This document assumes you have Node.js 16 active along with Yarn and Python. > Please note, that at the time of this writing, the current version is > 0.1.1-alpha.21. This guide can still be used with future versions, just, > verify as you go. If you run into issues, you can compare your setup with mine > here > > [simple-backstage-app-plugin](https://github.com/johnson-jesse/simple-backst
骨架插件
- Start by using the built-in creator. From the terminal and root of your project run:
yarn new --select plugin
2. Enter a plugin ID. I usedgithub-playground
3. When the process finishes, let's start the backend:yarn --cwd packages/backend start
4. If you see errors starting, refer to Auth Configuration for more information on environment variables. 5. And now the frontend, from a new terminal window and the root of your project:yarn start
6. As usual, a browser window should popup loading the App. 7. Now manually navigate to our plugin page from your browser:http://localhost:3000/github-playground
8. You should see successful verbiage for this endpoint,Welcome to github-playground!
捷径
让我们添加一个快捷方式。
打开并用以下内容修改 root: packages > app > src > components > Root.tsx
:
import GitHubIcon from '@material-ui/icons/GitHub';
...
<SidebarItem icon={GitHubIcon} to="github-playground" text="GitHub Repository" />
很简单!应用程序会自动重新加载您的更改。 现在您应该能在侧边栏看到一个 GitHub 图标。 点击它就能链接到我们的新插件。 现在,API 的乐趣就开始了。
身份
我们的第一项修改将是从身份信息应用程序接口(Identity API)中提取信息。
1.首先打开 root: plugins > github-playground > src > components > ExampleComponent > ExampleComponent.tsx
2.添加两个新导入项
// Add identityApiRef to the list of imported from core
import { identityApiRef, useApi } from '@backstage/core-plugin-api';
将 ExampleComponent 从 inline 调整为 block
from inline:
const ExampleComponent = () => ( ... )
以阻止:_
const ExampleComponent = () => {
return (
...
)
}
- 现在,在返回语 句之前添加我们的钩子和 const 数据
// our API hook
const identityApi = useApi(identityApiRef);
// data to use
const userId = identityApi.getUserId();
const profile = identityApi.getProfile();
- 最后,更新 InfoCard 的 jsx,以使用我们的新数据
<InfoCard title={userId}>
<Typography variant="body1">
{`${profile.displayName} | ${profile.email}`}
</Typography>
</InfoCard>
如果一切都已保存,你应该能在 github-playground 页面上看到你的姓名、ID 和电子邮件。 我们的数据访问是同步的,所以我们只需抓取并发送即可。
https://github.com/backstage/backstage/tree/master/contrib
- 以下是整个文件,供参考 ExampleComponent.tsx
擦拭
我们最后要处理的文件是 ExampleFetchComponent。 由于改动较多,我们先将该组件清理干净。
1.首先打开 root: plugins > github-playground > src > components > ExampleFetchComponent > ExampleFetchComponent.tsx
2.将文件中的所有内容替换为以下内容:
import React from 'react';
import useAsync from 'react-use/lib/useAsync';
import Alert from '@material-ui/lab/Alert';
import { Table, TableColumn, Progress } from '@backstage/core-components';
import { githubAuthApiRef, useApi } from '@backstage/core-plugin-api';
import { graphql } from '@octokit/graphql';
export const ExampleFetchComponent = () => {
return <div>Nothing to see yet</div>;
};
3.保存并确保没有错误。 如果您的导入程序碍事,请注释掉未使用的导入程序。
为了方便起见,我们将在此文件中添加很多内容。 请不要在产品代码中这样做!
图表模型
GitHub 有一个用于交互的 GraphQL API。 让我们先添加基本的版本库查询
在 ExampleFetchComponent 外部添加查询 const 语句
const query = `{
viewer {
repositories(first: 100) {
totalCount
nodes {
name
createdAt
description
diskUsage
isFork
}
pageInfo {
endCursor
hasNextPage
}
}
}
}`;
2.以这种结构 为指导,我们将把查询分成类型部分 3.在 ExampleFetchComponent 外部添加以下内容
type Node = {
name: string;
createdAt: string;
description: string;
diskUsage: number;
isFork: boolean;
};
type Viewer = {
repositories: {
totalCount: number;
nodes: Node[];
pageInfo: {
endCursor: string;
hasNextPage: boolean;
};
};
};
餐桌模型
使用 Backstage 自带的组件库,让我们定义一个自定义表格。 如果我们有数据要显示,就会用到这个组件。
在 ExampleFetchComponent 外部添加以下内容
type DenseTableProps = {
viewer: Viewer;
};
export const DenseTable = ({ viewer }: DenseTableProps) => {
const columns: TableColumn[] = [
{ title: 'Name', field: 'name' },
{ title: 'Created', field: 'createdAt' },
{ title: 'Description', field: 'description' },
{ title: 'Disk Usage', field: 'diskUsage' },
{ title: 'Fork', field: 'isFork' },
];
return (
<Table
title="List Of User's Repositories"
options={{ search: false, paging: false }}
columns={columns}
data={viewer.repositories.nodes}
/>
);
};
The Fetch
我们准备好刷新获取组件了
- 在 ExampleFetchComponent 中添加应用程序钩子
const auth = useApi(githubAuthApiRef);
- 我们需要访问令牌才能向 GitHub 发出请求,而请求本身是以异步方式获取的。 3. 在 ExampleFetchComponent 中添加 useAsync 块
const { value, loading, error } = useAsync(async (): Promise<any> => {
const token = await auth.getAccessToken();
const gqlEndpoint = graphql.defaults({
// Uncomment baseUrl if using enterprise
// baseUrl: 'https://github.MY-BIZ.com/api',
headers: {
authorization: `token ${token}`,
},
});
const { viewer } = await gqlEndpoint(query);
return viewer;
}, []);
4.解析后的数据被方便地重组为包含 Viewer 类型的 value
和不言自明的布尔值 loading
以及仅在必要时才会出现的 error
。 因此,让我们使用这些作为 4 个多重返回语句中的前 3 个。 5.在我们的异步代码块下方添加 if return 代码块
if (loading) return <Progress />;
if (error) return <Alert severity="error">{error.message}</Alert>;
if (value && value.repositories) return <DenseTable viewer={value} />;
6.这里的第三行利用我们的自定义表接受我们的 Viewer 类型。 7.最后,我们添加 else return 块来捕捉任何其他情况。
return (
<Table
title="List Of User's Repositories"
options={{ search: false, paging: false }}
columns={[]}
data={[]}
/>
);
- 保存后,如果我们没有 任何错误,你应该会看到一个包含你的仓库基本信息的表格。 9. 下面是整个文件,供参考 ExampleFetchComponent.tsx 10. 我们完成了!你应该会看到你自己的 GitHub 仓库的信息显示在一个基本表格中。 如果你遇到问题,你可以比较支持本文档的仓库,simple-backstage-app-plugin
何去何从
将 ExampleFetchComponent 分解成更小的逻辑部分,包含在 > 它们自己的文件中。 将组件重命名为 ExampleXxx 以外的名称。 > > 你可能会为自己开发的插件感到非常自豪。 请按照下一个教程 > 深入了解如何发布并将其包含在整个 Backstage > 社区中。