尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Backstage CLI 自定义模块开发指南:用 createCliModule 扩展 backstage-cli 命令体系

发布时间:2026/9/13 17:54:07

资讯中心
01
ARTICLE

Backstage CLI 自定义模块开发指南:用 createCliModule 扩展 backstage-cli 命令体系

Backstage CLI 自定义模块开发指南:用 createCliModule 扩展 backstage-cli 命令体系
Backstage CLI 自定义模块开发指南用 createCliModule 扩展 backstage-cli 命令体系【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstageBackstage 的 CLIbackstage-cli本身由一组相互独立的 CLI 模块构成每个模块提供一组相关命令。本文基于backstage/cli-node的createCliModuleAPI完整讲解如何从零创建一个自定义 CLI 模块从yarn new脚手架生成、package.json角色声明、命令注册与参数解析到模块的自动发现机制、独立运行方式与命令冲突解决规则。读完本文你将能够为团队封装自己的backstage-cli子命令并将其无缝集成到现有的 CLI 帮助树与命令体系中。什么是 Backstage CLI 模块CLI 模块CLI module是一个以包package为单位、通过createCliModuleAPI 注册一个或多个命令的独立模块。只要它被作为依赖安装到项目中Backstage CLI 就会在启动时自动发现并加载它其命令会与内置命令一起出现在--help输出中。官方默认将 13 个内置模块聚合在backstage/cli-defaults中例如backstage/cli-module-authauth login、auth logout、auth show等backstage/cli-module-buildpackage build、repo build、build-workspace等backstage/cli-module-configconfig:print、config:check等backstage/cli-module-test-jestrepo test、package test完整的模块清单与命令索引可参考 CLI 模块总览。自定义 CLI 模块正是沿着这套同一机制扩展 CLI 的官方途径。用脚手架快速生成模块Backstage CLI 提供了内置模板通过new命令交互式生成模块yarn new在交互菜单中选择cli-module模板。该模板源码位于 packages/cli-module-new/templates/cli-module会创建一个结构正确的包包含示例命令、独立的 bin 脚本以及全部必需的配置。模块的标准目录结构一个 CLI 模块包通常包含以下文件packages/cli-module-example/ bin/ backstage-cli-module-example # 独立的 bin 脚本 src/ commands/ example.ts # 命令实现 index.ts # 模块定义createCliModule package.json其中src/index.ts是模块入口导出由createCliModule创建的模块对象src/commands/存放各命令的实现bin/下的脚本负责模块的独立执行。package.json用 role 声明模块身份package.json必须将backstage.role设置为cli-module这是 CLI 在依赖扫描时识别模块的关键标志。一个完整的模块package.json如下{ name: mycompany/cli-module-example, version: 0.1.0, main: src/index.ts, types: src/index.ts, publishConfig: { access: public, main: dist/index.cjs.js, types: dist/index.d.ts }, backstage: { role: cli-module }, bin: bin/backstage-cli-module-example, files: [dist, bin], dependencies: { backstage/cli-common: ..., backstage/cli-node: ..., cleye: ... }, devDependencies: { backstage/cli: ... } }各字段的职责如下backstage.role必须为cli-module。发现机制见下文正是通过检查该字段来判断一个依赖包是否是 CLI 模块。main/types开发期指向src/index.ts便于源码直接运行。publishConfig.main/publishConfig.types发布时指向dist/index.cjs.js与dist/index.d.ts让消费方加载编译产物。bin指向bin/backstage-cli-module-example独立脚本使模块可以脱离完整 CLI 单独执行。files发布时仅包含dist与bin。dependenciesbackstage/cli-common路径与子进程等公共工具、backstage/cli-node提供createCliModule、runCli与类型、cleye参数解析库所有内置 CLI 模块也使用它。devDependenciesbackstage/cli用于开发期的package build、package test等脚本。模板实际生成的脚本package.json.hbs还包含完整的构建、测试、发布脚本scripts: { build: backstage-cli package build, lint: backstage-cli package lint, test: backstage-cli package test, clean: backstage-cli package clean, prepack: backstage-cli package prepack, postpack: backstage-cli package postpack }模块定义createCliModule 入口模块入口使用createCliModule注册命令src/index.tsimport { createCliModule } from backstage/cli-node; import packageJson from ../package.json; export default createCliModule({ packageJson, init: async reg { reg.addCommand({ path: [example], description: An example command, execute: { loader: () import(./commands/example) }, }); }, });createCliModule接受一个包含两个字段的 options 对象packageJson至少包含name字段的对象通常是直接导入的package.json。name在发生命令冲突时用于错误提示与归属标识。init异步回调接收一个 registry 对象通过其addCommand方法注册命令。从源码实现看createCliModule.tscreateCliModule会先校验packageJson.name是否存在若缺失则抛出The packageJson provided to createCliModule must have a name随后立即调用init把所有addCommand注册的命令收集为数组并以OpaqueCliModule的不透明实例形式返回模块。因此init在模块加载时执行而不是在命令执行时执行init应当保持轻量避免任何重量级导入或副作用对于依赖较重的命令应使用延迟加载loader模式将命令实现延后到真正调用时才import。定义命令CliCommand 对象每条命令由传入reg.addCommand的一个CliCommand对象定义类型定义见 types.tsreg.addCommand({ path: [my-tool, run], description: Run the tool, execute: async ({ args, info }) { // Command implementation }, });命令路径 pathpath数组定义命令的调用方式每个元素构成命令层级的一级[info]注册为backstage-cli info[repo, test]注册为backstage-cli repo test[actions, sources, add]注册为backstage-cli actions sources add路径中的中间节点会自动创建并在帮助输出中表现为命令分组。例如注册[repo, test]后backstage-cli repo会自动成为一个包含test子命令的分组。描述 description一段短字符串显示在帮助输出中命令名旁边。弃用与实验性标记命令可以标记deprecated: true或experimental: true。被标记的命令会从--help输出中隐藏但仍然可以正常调用。execute 两种模式execute字段支持两种形式直接执行——内联异步函数reg.addCommand({ path: [greet], description: Print a greeting, execute: async ({ args, info }) { console.log(Hello!); }, });延迟加载——通过 loader 动态导入命令实现。这是推荐模式可以避免在命令真正被调用前加载重依赖reg.addCommand({ path: [greet], description: Print a greeting, execute: { loader: () import(./commands/greet) }, });使用延迟加载模式时命令文件必须以默认导出方式导出执行函数// src/commands/greet.ts import type { CliCommandContext } from backstage/cli-node; export default async ({ args, info }: CliCommandContext) { console.log(Hello!); };从 runCli.ts 的执行逻辑可以印证这一点当execute是函数时直接调用否则调用execute.loader()取出模块并兼容解析其default导出后调用。命令上下文 CliCommandContext执行函数接收一个CliCommandContext包含两个字段类型定义见 types.tsargs命令路径解析后剩余的全部命令行参数含位置参数与 flag。例如用户执行backstage-cli greet --name World时args为[--name, World]。info命令元信息对象包含usage帮助中显示的完整调用串例如backstage-cli greetname命令名例如greet。在runCli内部info.usage由[programName, ...commandToExecute.path].join( )拼出info.name则由commandToExecute.path.join( )得出。用 cleye 解析 flags命令通常使用cleye从args数组中解析 flags——这也是所有内置 CLI 模块使用的同一个库// src/commands/greet.ts import { cli } from cleye; import type { CliCommandContext } from backstage/cli-node; export default async ({ args, info }: CliCommandContext) { const { flags } cli( { name: info.usage, flags: { name: { type: String, description: Name to greet, default: World, }, loud: { type: Boolean, description: Shout the greeting, }, }, }, undefined, args, ); const greeting Hello, ${flags.name}!; console.log(flags.loud ? greeting.toUpperCase() : greeting); };注意几个要点name传入info.usage让 cleye 生成的错误信息与帮助文本与backstage-cli greet的完整调用串保持一致字符串 flag 用type: String声明布尔开关用type: Boolean声明模板生成的示例命令example.ts还启用了booleanFlagNegation: true支持诸如--no-name形式的否定 flag并用flags.name ?? World提供默认值cleye 只负责解析args切片CLI 自身的命令分发路径匹配、帮助渲染、退出码由backstage/cli-node的runCli完成。独立执行bin 脚本每个 CLI 模块都可以脱离完整的backstage/cli作为独立程序运行便于单独分发模块。脚手架生成的 bin 脚本如下bin/backstage-cli-module-example#!/usr/bin/env node const path require(node:path); /* eslint-disable-next-line no-restricted-syntax */ const isLocal require(node:fs).existsSync( path.resolve(__dirname, ../src), ); if (isLocal) { require(backstage/cli-node/config/nodeTransform.cjs); } const { runCli } require(backstage/cli-node); const cliModule require(isLocal ? ../src/index : ..).default; const pkg require(../package.json); runCli({ modules: [cliModule], name: pkg.name, version: pkg.version });脚本中的isLocal检查用于判断 bin 脚本旁是否存在src/目录开发期从源码运行src/存在注册backstage/cli-node/config/nodeTransform.cjs的 Node.js 转换直接加载 TypeScript 源文件../src/index从发布包运行src/不存在加载编译产物..即包入口dist/index.cjs.js。随后调用runCli并传入模块数组、程序名与版本号。runClirunCli.ts会校验每个模块均是由createCliModule创建的对象将各模块注册的命令汇总进一个命令图CommandGraph;支持--version/-V输出版本递归解析命令路径、渲染帮助输出并按错误类型映射退出码如InputError对应 74、未找到命令对应 127 等。这也说明runCli同样适用于从一组固定的直接导入模块构建自定义 CLI 程序——例如把backstage/cli-module-build与你自己的模块组合成一个独立的工具。安装模块与自动发现模块发布或作为 workspace 包可用后在项目根目录的package.json中加入依赖即可{ devDependencies: { backstage/cli: ..., mycompany/cli-module-example: ... } }CLI 会在下次运行时自动发现它自定义命令随即出现在--help输出中与默认命令并列。发现机制的核心实现在 packages/cli/src/wiring/discoverCliModules.tsCLI 启动时读取项目根目录的package.json合并dependencies与devDependencies中的全部依赖逐一解析每个依赖包的package.json检查其backstage.role是否为cli-module——若是则将该包解析为入口模块加载。任何无法解析或读取的包会被静默跳过。回退行为与迁移说明如果项目依赖中找不到任何 CLI 模块CLI 会回退到导入backstage/cli-defaults并打印一条弃用警告。该回退将在未来版本移除。要消除警告可以在根package.json中加入backstage/cli-defaults作为开发依赖或按需安装独立的backstage/cli-module-*包。只安装部分模块如果只需要部分命令可以只安装对应模块而不依赖backstage/cli-defaults{ devDependencies: { backstage/cli: ..., backstage/cli-module-build: ..., backstage/cli-module-lint: ..., backstage/cli-module-test-jest: ... } }此时 CLI 仅提供 build、lint、test 相关命令。命令冲突与覆盖规则如果你的模块注册的命令路径与backstage/cli-defaults中的默认模块冲突你的模块优先冲突的默认模块会被静默跳过。例如发布一个注册了与backstage/cli-module-build相同命令路径的内部mycompany/cli-module-build加入根package.json后就会取代默认 build 模块。这一规则同样适用于自定义模块之间当多个模块注册相同路径时通过命令图CommandGraph的归并过程后加载者或具有优先级的模块胜出被覆盖的模块不参与帮助渲染与命令分发。更完整的模块发现与覆盖机制说明见 CLI 模块总览。源码中的模块体系全景CLI 模块体系分布在以下几个包中理解它们有助于排查与扩展backstage/cliCLI 主入口包含负责发现模块的CliInitializer与扫描项目依赖的discoverCliModulesdiscoverCliModules.ts。backstage/cli-node构建 CLI 模块的公共 API——createCliModule、runCli以及CliModule、CliCommand、CliCommandContext类型cli-module 目录。backstage/cli-common路径解析与子进程管理等最小公共工具供 CLI、backend 与create-app共用。backstage/cli-defaults聚合包将全部 13 个默认模块重新导出为数组。backstage/cli-module-new提供cli-module脚手架模板是快速起步的参考实现templates/cli-module。小结自定义 CLI 模块是扩展 Backstage CLI 的官方且轻量的方式用yarn new生成脚手架 → 在package.json声明backstage.role: cli-module→ 在src/index.ts用createCliModule注册命令 → 命令内用 cleye 解析参数 → 通过 bin 脚本支持独立运行 → 安装为项目依赖后由 CLI 自动发现。整个过程与内置模块共用同一套加载、分发与冲突解决机制你可以放心地将团队专属命令如内部脚手架、代码生成、发布辅助工具以模块形式交付给所有使用backstage-cli的开发者。【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。