Backstage @backstage/app-defaults:用一份默认装配让标准前端 App 摆脱样板代码

发布时间:2026/9/13 11:36:18
Backstage @backstage/app-defaults:用一份默认装配让标准前端 App 摆脱样板代码 Backstage backstage/app-defaults用一份默认装配让标准前端 App 摆脱样板代码【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage本文以 Backstage 仓库中的backstage/app-defaults包为核心完整讲解它的定位与安装方式、createApp的公开 API 面以及默认组件、图标、主题、API 工厂四类默认装配的源码实现与覆盖override语义并给出仓库内真实应用的调用示例。读完后你将能够在自己的 Backstage 应用中正确安装并调用该包理解每一项默认值何时被使用、如何被替换并基于源码定制登录页、错误页与全局图标。包的定位backstage/app-defaults提供了一套 Backstage App 的默认装配default wiring当你创建一个新的 Backstage 前端应用时无需手工准备全局路由、进度指示、404 页、启动错误页、错误边界兜底页、明暗主题、全局图标集与十余个基础 API 工厂这个包会把它们一次性注入到应用根节点。官方包描述package.json为Provides the default wiring of a Backstage App包的关键元数据以 package.json 为准包名/版本backstage/app-defaults1.7.12-next.1backstage.role为web-library即纯前端库不参与后端运行核心依赖backstage/core-app-api、backstage/core-components、backstage/core-plugin-api、backstage/frontend-plugin-api、backstage/plugin-permission-react、backstage/theme以及 Material-UI v4material-ui/core、material-ui/iconsPeer 依赖React 17/18、react-router-dom^6.30.2入口文件为src/index.ts发布产物在dist/main: dist/index.esm.js、types: dist/index.d.ts并声明了sideEffects: false以便打包器做树摇。包的公开入口非常克制见 src/index.tsexport { createApp } from ./createApp; export type { OptionalAppOptions } from ./createApp;也就是说整个包对外的 API 面只有一个函数createApp和一个类型OptionalAppOptions。这一点也可以从 API Extractor 生成的 report.api.md 中得到确认export function createApp( options?: OmitAppOptions, keyof OptionalAppOptions OptionalAppOptions, ): BackstageApp; export type OptionalAppOptions { icons?: PartialAppIcons { [key in string]: IconComponent }; themes?: (PartialAppTheme OmitAppTheme, theme)[]; components?: PartialAppComponents; };安装按包内 README 给出的方式从 Backstage 仓库根目录执行# From your Backstage root directory yarn --cwd packages/app add backstage/app-defaults该命令以 Yarn workspace 的方式把包安装到你自己的应用包约定俗成为packages/app中。安装完成后即可在应用的入口模块中import { createApp } from backstage/app-defaults。README 还指向了 Backstage 的主 README即本仓库根目录的 README.md与官方文档站点在本仓库中文档内容可直接查阅 docs/ 下的对应章节前端应用构建专题位于 docs/frontend-system/building-apps/。createApp 的装配逻辑三类覆盖语义createApp的实现在 src/createApp.tsx它本质上是backstage/core-app-api中createSpecializedApp的一个带默认值的封装export function createApp( options?: OmitAppOptions, keyof OptionalAppOptions OptionalAppOptions, ) { return createSpecializedApp({ ...options, apis: options?.apis ?? [], bindRoutes: options?.bindRoutes, components: { ...components, ...options?.components, }, configLoader: options?.configLoader, defaultApis: apis, icons: { ...icons, ...options?.icons, }, plugins: (options?.plugins as BackstagePlugin[]) ?? [], featureFlags: options?.featureFlags ?? [], themes: options?.themes ?? themes, }); }对照这段代码各选项的覆盖语义可以分成三档这也是使用该包时最容易踩坑的地方选项默认来源覆盖语义源码依据componentsdefaults/components按键浅合并只替换你显式传入的那几个组件其余保留默认...components, ...options?.componentsiconsdefaults/icons按键浅合并逐个图标覆盖且允许任意字符串键自定义 kind 图标...icons, ...options?.iconsthemesdefaults/themes整体替换一旦传入themes默认主题将完全不再生效options?.themes ?? themesapis无defaultApis承担默认传入的apis会附加在默认工厂defaultApis之后不传则为[]apis: options?.apis ?? []defaultApis: apisplugins/featureFlags/bindRoutes/configLoader[]或透传直接透传缺省为空数组同上注意themes与components/icons的不对称性createApp.tsx 的类型注释明确写道——If this option is provided none of the default themes will be used若提供该选项则任何默认主题都不会被使用。如果你只想加一个自定义主题需要自己把默认的 light/dark 主题一并传入数组。默认组件路由、进度与三层错误体验默认组件集在 src/defaults/components.tsxexport const components: AppComponents { Progress, // backstage/core-components 的进度条 Router: BrowserRouter, // 全局路由 NotFoundErrorPage: DefaultNotFoundPage, // 404 页 BootErrorPage: DefaultBootErrorPage, // 启动期错误页 ErrorBoundaryFallback: DefaultErrorBoundaryFallback, // 插件错误边界兜底 };几个值得注意的实现细节404 页DefaultNotFoundPage直接渲染ErrorPage status404 statusMessagePAGE NOT FOUND启动错误页DefaultBootErrorPage按启动阶段输出不同提示load-config失败时提示The configuration failed to load…load-chunk失败时提示Lazy loaded chunk failed to load, try to reload the page…并展示error.stack错误边界兜底DefaultErrorBoundaryFallback使用ErrorPanel显示Error in ${plugin?.getId()}并提供Retry按钮点击即调用resetError重置边界——单个插件抛错不会拖垮整个应用辅助组件OptionallyWrapInRouter会检测当前是否已处于 Router 上下文中useInRouterContext()没有才用MemoryRouter包裹避免错误页在测试或无路由环境中因缺少路由上下文而崩溃。默认主题light 与 dark默认主题定义在 src/defaults/themes.tsx共两个id: light标题 Light Theme变体light图标为 Material-UI 的WbSunnyid: dark标题 Dark Theme变体dark图标为Brightness2。两者的Provider都通过backstage/theme导出的UnifiedThemeProvider注入builtinThemes.light/builtinThemes.dark。Unified 的含义是该 Provider 对 Material-UI v4 与 v5 组件都能生效这正是 Backstage 正处于 UI 组件库迁移MUI v4 → 新版 BUI 组件过程中的兼容层。结合上文themes的整体替换语义若你想自定义主题应复制这份结构并自行决定保留几个默认主题。默认图标集src/defaults/icons.tsx 提供了一组以 Material-UI v4 图标实现的AppIcons覆盖应用外壳shell、导航与实体entity两类场景图标键对应图标典型用途brokenImageBrokenImage图片加载失败占位catalogMenuBook目录Catalog入口scaffolderCreateNewFolder软件模板Scaffolder入口techdocsSubject文档TechDocs入口search/chat/dashboard/docs/email/github/group/help同名图标顶部导航与功能入口kind:api/kind:component/kind:domain/kind:group/kind:location/kind:system/kind:user/kind:resource/kind:templateExtension/Memory/Apartment/People/LocationOn/Category/Person/Storage/FeaturedPlayList目录中各类实体 kind 的默认标识user/warning/star/unstarred/externalLinkPerson/Warning/Star/StarBorder/OpenInNew用户头像、告警、收藏、外链源码中保留了历史注记catalog使用MenuBook图标旁有一条 To be confirmed: see https://github.com/backstage/backstage/issues/4970 的注释说明该图标选择与社区讨论相关联。由于icons的覆盖是按键合并且允许任意字符串键PartialAppIcons { [key in string]: IconComponent }你既可以替换内置键也可以为自定义 kind 或功能直接新增图标键。默认 API 工厂应用启动即获得的能力createApp把 src/defaults/apis.ts 中的apis数组作为defaultApis传给createSpecializedApp。这是该包体量最大的部分——一组通过createApiFactory声明的默认 API 工厂及其依赖图基础能力discoveryApiRef依赖configApi用FrontendHostDiscovery.fromConfig(configApi)从配置解析后端地址alertApiRefAlertApiForwarder全局告警转发器analyticsApiRefNoOpAnalyticsApi默认空实现不采集errorApiRef依赖alertApi组合ErrorAlerterErrorApiForwarder并通过UnhandledErrorForwarder.forward(errorApi, { hidden: false })把未捕获的 JS 错误也纳入上报storageApiRef依赖errorApiWebStorage.create({ errorApi })提供基于浏览器存储的KeyValueStoragefetchApiRef依赖configApi、identityApi、discoveryApicreateFetchApi挂了三层中间件——resolvePluginProtocol把插件协议的相对路径解析为完整后端地址、injectIdentityAuth按配置为请求注入身份凭证、clarifyFailures把网络/后端错误转为更易诊断的异常oauthRequestApiRefOAuthRequestManager承载 OAuth 弹窗流程permissionApiRef依赖discovery/identity/config创建IdentityPermissionApi基于backstage/plugin-permission-reacttoastApiRef依赖alertApi把 toast 消息标题会被reactNodeToString拍平为字符串桥接到alertApi展示模式为transient严重级别映射为warning→warning、danger→error、其余→info。认证 API每个 provider 一个工厂所有认证工厂共享同样的依赖三元组{ discoveryApi, oauthRequestApi, configApi }并从配置读取auth.environment用于区分多个后端环境API Ref实现类额外参数googleAuthApiRefGoogleAuth.create—microsoftAuthApiRefMicrosoftAuth.create—githubAuthApiRefGithubAuth.createdefaultScopes: [read:user]oktaAuthApiRefOktaAuth.create—gitlabAuthApiRefGitlabAuth.create—oneloginAuthApiRefOneLoginAuth.create—bitbucketAuthApiRefBitbucketAuth.createdefaultScopes: [account]bitbucketServerAuthApiRefBitbucketServerAuth.createdefaultScopes: [REPO_READ]atlassianAuthApiRefAtlassianAuth.create—vmwareCloudAuthApiRefVMwareCloudAuth.create—openshiftAuthApiRefOpenShiftAuth.create—这套默认装配意味着一个装了该包的应用开箱即拥有从配置发现后端 → 发起请求时自动带身份 → 各主流 IdP 的单点登录的完整前端地基。插件侧通过useApi(githubAuthApiRef)等方式消费这些能力而无需各自重复初始化。仓库内的真实用法该包在仓库中的消费者包括 packages/app-legacy/src/App.tsx、packages/app-legacy/src/index-public-experimental.tsx、脚手架模板 packages/create-app/templates/legacy-app/packages/app/src/App.tsx 以及开发工具入口 packages/dev-utils/src/devApp/render.tsx。以 legacy 参考应用为例它演示了前述三类覆盖语义的实际写法import { createApp } from backstage/app-defaults; const app createApp({ apis, // 追加在默认工厂之后的自定义 API icons: { // Custom icon example按键覆盖单个图标 alert: AlarmIcon, }, featureFlags: [ { name: scaffolder-next-preview, description: Preview the new Scaffolder Next, pluginId: , }, ], components: { // 按键覆盖单个组件自定义登录页 SignInPage: props ( SignInPage {...props} providers{[guest, custom, ...providers]} titleSelect a sign-in method aligncenter / ), }, });这个示例恰好展示了继承默认 点状定制的典型模式SignInPage用包装组件替换默认登录页注入自定义 provider 列表与标题alert图标被换成AlarmIcon而路由、进度条、错误页、主题、图标集与全部默认 API 工厂继续由该包提供。测试如何验证默认装配包内自带针对默认组件与createApp的组件测试src/createApp.test.tsx通过createApp({ components }).getProvider()渲染应用验证用户以components.ThemeProvider提供的自定义 Provider 被真实生效断言rolemain节点存在——证明components的按键覆盖会直达应用外壳src/defaults/components.test.tsx针对默认组件错误页、兜底页等的独立渲染测试。配合package.json中的脚本backstage-cli package test/build/lint可以在本包目录内直接运行这些验证。小结什么时候需要它、什么时候不必需要它你新建一个标准 Backstage 前端应用web-library之上的app包希望零样板地获得默认主题、错误体验、图标集与全套基础 API 工厂需要定制时记住覆盖语义的差异——components与icons是按键替换而themes是整体替换apis则是默认工厂 追加的模型不必用它完全自定义应用外壳的场景下可以直接使用底层的createSpecializedAppbackstage/core-app-api自行装配——backstage/app-defaults的价值正在于把这层装配收敛为一份可预测的默认实现。参考入口packages/app-defaults/README.md、packages/app-defaults/package.json、packages/app-defaults/report.api.md、packages/app-defaults/src/createApp.tsx、packages/app-defaults/src/defaults/apis.ts。【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询