当前位置: 首页 > news >正文

[Backstage] 前端扩展 | 应用扩展树 | 工厂函数 | attachTo附着点

第9章:扩展(前端)

在上一章实用API(前端)中,我们学习了Backstage前端的不同部分如何共享通知显示或错误处理等通用功能

这些API为插件提供了一致的通信方式。但这些插件本身,连同它们的页面、导航项甚至它们提供的API

是如何组织和连接起来形成一个完整、连贯的Backstage应用的呢?

Backstage如何知道在哪里放置新页面,或者如何在另一个插件的视图中显示自定义卡片?

这就是**扩展(前端)**的用武之地

扩展是构建整个Backstage前端应用视觉和功能框架的基本构建块。

前端扩展解决了什么问题?

想象Backstage应用是一个复杂的乐高模型。每个扩展就像一块单独的乐高积木。前端插件则像是特定积木的集合,组合在一起可以构建特定功能(如乐高汽车或房子)

从许多独立插件构建大型可定制应用的挑战在于确保所有部分能无缝衔接。如果没有标准化的方式来定义和连接这些部分,最终会导致混乱、不一致以及定制或替换部分功能的巨大困难。

扩展通过提供通用结构解决了这个问题。每个扩展定义了它是哪种积木、连接到哪里(输入)、提供什么(输出)以及如何行为(工厂函数)。这种模块化方法支持灵活的组装和覆盖,实现应用UI和功能的深度定制。

前端扩展的核心概念

扩展是Backstage前端的基石。以下是其核心思想:

  1. 乐高积木(扩展)

    • 扩展是一个自包含的UI或功能单元。它可以是一个完整页面、页面的一部分、按钮,甚至是像实用API实现这样的非可视化部分。
    • 使用createExtension或称为"蓝图"的辅助函数定义扩展。
  2. 应用扩展树(乐高模型)

    • 所有扩展按层次排列,形成树状结构。每个扩展通常是另一个"父"扩展的"子"扩展。
    • 这棵树决定了整个应用的构建和渲染方式,确保一切各归其位。
  3. 输入和输出(乐高凸点和凹槽)

    • 输出:扩展向父级提供的数据或React元素。可以将其视为乐高积木顶部的"凸点"。每个输出必须与特殊共享引用(如coreExtensionData.reactElement)关联以定义其类型。
    • 输入:扩展从子级接收的数据或React元素。这就像乐高积木底部的"凹槽"。扩展明确声明它期望从子级获得哪种数据。
    • 这是扩展通信和沿树传递信息的主要方式
  4. 工厂函数(积木内部机制)

    • 这是扩展创建时运行的实际代码。它接收输入和配置(如果有),然后生成扩展定义的输出。它是乐高积木内部的"逻辑"。
  5. 附着点(attachTo

    • 此属性定义扩展在应用扩展树中的连接位置。它指定父扩展的唯一id和应连接到的该父级的输入name。这就是将一块乐高积木连接到另一块的方式。
  6. 配置(config

    • 扩展可以接受配置参数,允许在不更改底层代码的情况下定制其行为。就像选择乐高积木的颜色或特定细节。
  7. 扩展蓝图(预设计的乐高件)

    • 虽然可以直接使用createExtension(最基本的方式),但Backstage也提供了"蓝图"如PageBlueprintNavItemBlueprintApiBlueprint。这些是常见扩展类型的模板,使创建具有预配置通用属性的扩展更容易,就像使用预设计的乐高车轮件。

解决用例:添加自定义主页部分

假设Backstage主页有一个特殊区域(在名为app/homepage的扩展上暴露为名为main-content的输入),可以在此添加自定义React元素。我们希望在此添加一个CustomGreetingCard来欢迎用户。

首先,创建简单的React组件:

// plugins/my-custom-plugin/src/components/CustomGreetingCard.tsx
import React from 'react';export const CustomGreetingCard = () => {return (<div style={{padding: '20px',border: '1px solid #ccc',borderRadius: '8px',background: '#e0f7fa',textAlign: 'center'}}><h2>👋 欢迎来到Backstage,团队!</h2><p>这是你的个性化门户。快速探索目录并创建新服务!</p></div>);
};

现在,将其定义为扩展并指定如何连接到应用扩展树。我们将此放入名为my-custom-plugin的新插件中。

// plugins/my-custom-plugin/src/plugin.ts
import {createFrontendPlugin,createExtension, // 使用基础扩展创建器coreExtensionData, // 用于常见数据类型如React元素
} from '@backstage/frontend-plugin-api';
import { CustomGreetingCard } from './components/CustomGreetingCard';
import React from 'react'; // 别忘了导入React// 1. 定义我们的自定义扩展
const customGreetingExtension = createExtension({id: 'my-custom-plugin/greeting-card', // 扩展的唯一ID// 2. 我们希望将其连接到假设的'homepage'扩展的'main-content'输入。// 在实际应用中,你会从文档/代码中找到正确的父ID和输入名称。attachTo: { id: 'app/homepage', input: 'main-content' },// 3. 此扩展输出一个React元素。output: [coreExtensionData.reactElement],// 4. 工厂函数生成输出。factory() {return [coreExtensionData.reactElement(<CustomGreetingCard />)];},
});// 5. 创建一个插件来托管我们的扩展
export const myCustomPlugin = createFrontendPlugin({pluginId: 'my-custom-plugin',extensions: [customGreetingExtension],
});

代码说明:

  • createExtension:这是定义扩展的基本函数。
  • id:这是Backstage用来管理扩展的唯一标识符(如my-custom-plugin/greeting-card)。
  • attachTo此属性至关重要!它告诉Backstage我们的customGreetingExtension应连接到应用扩展树中的哪里。我们指定父级的ID(app/homepage)和应插入的特定输入名称(main-content)。
  • output:我们声明扩展将提供一个React.JSX.ElementcoreExtensionData.reactElement是Backstage提供的特殊引用,表示此类输出。
  • factory():此函数是我们扩展的核心。当Backstage构建应用时,此函数运行。它接收输入和配置(如果有)并返回输出数组。这里,它简单地返回我们的<CustomGreetingCard />组件,用其coreExtensionData.reactElement引用包装。
  • createFrontendPlugin我们的my-custom-plugin简单地打包customGreetingExtension,以便可以将其安装到Backstage应用中

要使此生效,需将myCustomPlugin添加到packages/app/src/App.tsx文件(类似于第2章中添加cloudCostsPlugin的方式):

// packages/app/src/App.tsx(简化)
import { createApp } from '@backstage/frontend-defaults';
import { myCustomPlugin } from './plugins/my-custom-plugin'; // 我们的自定义插件
// ... 其他插件的导入const app = createApp({features: [myCustomPlugin,// ... 其他插件和功能],
});export default app.createRoot();

说明: createApp中的features数组是你告诉Backstage加载哪些插件(以及它们提供的扩展)到应用中的地方。

底层原理:应用扩展树在运行中

当Backstage应用启动时,它不会随机显示内容。它通过像乐高积木一样连接所有扩展,系统地构建和渲染应用扩展树

让我们追踪加载myCustomPlugin及其customGreetingExtension时发生的情况:

在这里插入图片描述

说明:

  1. 用户打开Backstage门户:你在浏览器中打开Backstage应用。
  2. Backstage应用加载插件和扩展createApp函数初始化并加载所有配置的前端插件,包括myCustomPlugin。然后发现这些插件提供的所有扩展(如customGreetingExtension)。
  3. 应用识别附着点Backstage检查每个扩展的attachTo属性。对于customGreetingExtension,它注意到它希望连接到app/homepage扩展的main-content输入。
  4. 构建应用扩展树:Backstage构建所有活动扩展的完整层次树。此树从核心内置扩展(如App/RootApp/LayoutApp/Routes和我们假设的App/Homepage)开始,并在指定附着点集成插件提供的扩展(如customGreetingExtension)。
  5. 工厂函数执行(自底向上:Backstage应用通过调用其factory函数实例化扩展,从叶节点(没有子级的扩展)开始,沿树向上工作。
    • 我们的customGreetingExtensionfactory()函数运行,生成<CustomGreetingCard />组件。然后此组件作为"输入"提供给其父级App/Homepage
    • App/Homepage接收此输入,将其与自己的逻辑集成(如将其放入特定的div中),并生成自己的输出,然后成为其父级(App/Layout)的输入。
    • 此过程沿树向上继续,直到App/Root扩展生成整个应用的最终完整React元素
  6. 应用渲染UI:最终的React元素随后在屏幕上渲染,将你的自定义问候卡片无缝集成到Backstage主页中。

这种树结构和自底向上的实例化确保组件在构建时所有依赖(输入)已解析,从而产生灵活且可组合的UI。

代码

前端扩展的基础主要在@backstage/frontend-plugin-api包中。

  • createExtension:这是定义任何扩展的基本底层函数,如我们的示例所示。

    • 文档:官方前端扩展文档深入探讨了其结构和用法。
  • coreExtensionData:用于定义输入和输出的常见ExtensionDataRef集合。

    • 文档:内置数据引用文档列出了各种引用,如reactElement(用于React组件)、routeRef(用于路由)和title(用于显示文本)。
  • 扩展蓝图:用于创建特定类型扩展的高级辅助函数,使开发更容易。

    • 示例
      • PageBlueprint.make:用于创建完整页面,如前端插件中所示。(文档:常见扩展蓝图)
      • NavItemBlueprint.make:用于向导航侧边栏添加项。
      • ApiBlueprint.make:用于提供实用API(前端)。
  • 扩展配置(app-config.yaml:可以直接在app-config.yaml文件中配置、启用或禁用扩展。

    • 文档:在应用中配置扩展文档解释了如何使用app.extensions键。
    # app-config.yaml
    app:extensions:# 示例:如果需要,禁用我们的自定义问候卡片- my-custom-plugin/greeting-card: false# 示例:配置内置的警报显示扩展- app-root-element:app/alert-display:config:transientTimeoutMs: 10000 # 让警报停留更久(默认为5000ms)
    

    (可以在应用内置扩展文档中找到app-root-element:app/alert-display。)

  • 扩展覆盖:为了更深度定制,可以使用.override()方法替换或修改现有扩展。

    • 文档:前端扩展覆盖文档提供了如何实现这一点的详细示例。

结论

在本章中,我们探讨了扩展(前端),这些核心构建块构建了整个Backstage前端应用

我们了解到扩展就像单独的乐高积木,在分层的"应用扩展树"中连接,通过明确定义的输入和输出进行通信

通过理解如何创建、配置和连接这些扩展,现在具备了深度定制、扩展和集成Backstage门户功能的基础知识,可以构建一致且量身定制的开发者体验。

END★,°:.☆( ̄▽ ̄)/.°★

http://www.dtcms.com/a/487319.html

相关文章:

  • 凡科网站案例网站备案好麻烦
  • ps做全屏网站画布要多大网络推广与传统推广的区别
  • 动易网站 首页模板修改智能科技网站模板
  • JVM 内存结构与 GC 机制详解( 实战优化版)
  • JVM垃圾收集器详解(jdk21+25实战版)
  • 花店网站建设规划书如何用易语言做网站辅助
  • 怎样做交互式网站网站建设的标语
  • 【iOS】KVC
  • 自己注册公司网站教育网站建设网站
  • 九度企业网站推广软件合肥网站建设工作
  • Beyond Vision (BV) -具有人工智能功能的全自动多旋翼无人机和混合垂直起降无人机
  • 做网站网络公司无收入阿里巴巴建站多少钱
  • 旅游网站对比模板下载08wordpress主题
  • HTTP之POST请求和GET请求
  • 聚类算法详解:k-means、层次聚类和DBSCAN
  • 廊坊中小企业网站制作做汽配找哪个网站好
  • 网站建设视频教程集工厂管理软件
  • Linux 学习笔记之 VI 编辑器与文件查找技巧
  • 贵阳网站建设多钱钱清远专业网站制作公司
  • 网站设计对网站搜索引擎友好性的影响南宁市两学一做网站
  • 什么是部署php网站邢台城乡建设局网站
  • 搜狐三季度营收多少新开网站seo
  • 基于 clangd 搭建 Redis 6.2 源码阅读与调试环境
  • 备案主体负责人 网站负责人哪个网站做ppt好
  • C文件中在编译时候怎么把几个同名函数链接进来
  • 影视 IP 全链开发:App 如何成为核心
  • 机房网络组建方案搜索引擎优化的核心是
  • CentOS7虚拟机扩容操作指南(CentOS7虚拟机磁盘大小不够)
  • Replication(下):事务,一致性与共识
  • PIL与OpenCV图像读取的颜色格式陷阱:RGB vs BGR