前言
[MixedCli](https://zhangfisher.github.io/mixed-cli/)
为monorepo
应用开发命令行程序提供了一套解决方案,提供了更加友好的命令行开发体验。
第1步:创建工程
以一个典型的monorepo
为例开始:
shell
flexapp
packages
cli
core
vue
react
示例工程名为flexapp
,工程中的包名分别是@flexapp/core
、@flexapp/cli
、@flexapp/vue
、@flexapp/react
。
第2步:创建命令行应用
@flexapp/cli
是命令行应用,对外提供flexapp
的命令行工具。
1. 安装依赖
::: code-group
bash
npm install mixed-cli
bash
pnpm add mixed-cli
bash
yarn add mixed-cli
:::
2. 创建cli.js
在@flexapp/cli
包中创建cli.js
文件,内容如下:
flexapp
pacakges
cli
cli.js
init.js
package.json
主要内容如下:
::: code-group
ts
const { outputStr,MixedCli } = require("mixed-cli")
const initCommand = require("./init")
const cli = new MixedCli({
name: "flexapp",
version: "1.0.0",
include: /^\@flexapp\//,
// 显示logo
logo: String.raw`
____ ____ __
\ \ / /___ ___________| | _______
\ Y / _ \_/ __ \_ __ \ |/ /\__ \
\ ( <_> ) ___/| | \/ < / __ \_
\___/ \____/ \___ >__| |__|_ \(____ /
\/ \/ \/`,
})
cli.register(initCommand)
cli.run()
json
{
"name": "@flexapp/cli",
"version": "1.0.0",
"bin": {
"flexapp": "cli.js"
}
}
:::
@flexapp/cli
仅仅是一个命令行的入口:
- 重点:
include: /^\@flexapp\//
的意思是告诉mixed-cli
,当执行flexapp
命令时,会在当前工程中搜索以@flexapp/
开头的包,然后包中声明在cli
文件夹下的所有命令被合并到flexapp
命令中。 @flexapp/cli
中使用cli.register(iniCommand)
,注册一个通用的init
命令,该命令的实现在init.js
中。 一般可以在此工程提供一些通用命令,而其他的命令声明逻辑在分别在@flexapp/*/cli/*.js
等包中实现。
第3步: 创建命令
从上面可以看到@flexapp/cli
非常简单,主要是一些通用的命令和命令行的入口。而真正的命令声明在其他的包中,比如@flexapp/vue
、@flexapp/react
等包中。
然后接下来,我们在@flexapp/vue
中创建一个dev
命令,用于启用vue
项目。
bash{11}
flexapp
pacakges
cli
cli.js
dev.js
package.json
vue
src
index.ts
cli
dev.js // dev命令的实现
pacakge.json
接下来我们编写dev.js
文件,内容如下:
::: code-group
js
const { MixedCommand } = require('mixed-cli');
/**
* @param {import('mixed-cli').MixedCli} cli
*/
module.exports = (cli)=>{
const devCommand = new MixedCommand();
devCommand
.name('dev')
.description("以开发模式启动应用") // 未指定默认值,自动使用text类型提供
.option("-p,--port <port>","指定端口号",3000)
.option("-d,--debug" ,"调试模式",{ default:true,prompt:true })
.option("-h,--host <host>","指定主机名",{default:"localhost",prompt:true})
.option("-e,--env [value]","环境变量",{ prompt:false })
.option("-m,--mode <mode>","指定模式",{choices:["development","production","test","debug"]})
.option("-f,--framework [value]","开发框架",{choices:[
{title:"vue",value:1},
{title:"react",value:2,description:"默认"},
{title:"angular",value:3}
]})
.option("-o,--open","自动打开浏览器",{prompt:{ // 自定义提示
type:"toggle",
message:"是否自动打开浏览器?",
}})
.action((options)=>{
console.log("run dev")
})
return devCommand
}
json
{
"name": "@flexapp/vue",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"mixed-cli": "^1.0.0"
}
}
:::
- 在
src/cli
目录下创建dev.js
文件,用于声明dev
命令。cli
目录下的所有js
文件会被自动加载,每个文件均导出一个函数,该函数需要返回一个或多个MixedCommand
实例。cli
目录是一个默认的约定目录,可以通过cli.cliDir
参数修改。 - 创建
MixedCommand
实例,用于声明命令。MixedCommand
继承自commander
的Command
类,因此可以使用commander
的所有特性。 package.json
只需要将mixed-cli
添加为依赖即可。- 同样地,我们可以在
@flexapp/react
,@flexapp/app
等包中创建其他的命令。
第4步: 使用命令
我们在flexapp
应用中开发。
- 安装
@flexapp/cli
包
::: code-group
shell
npm install @flexapp/cli @flexapp/vue
shell
pnpm add @flexapp/cli @flexapp/vue
shell
yarn add @flexapp/cli @flexapp/vue
:::
安装@flexapp/cli
包后,就可以在命令行中使用flexapp
和flexapp init
命令了。
此时执行一下flexapp
命令,会看到如下输出:
shell{15}
____ ____ __
\ \ / /___ ___________| | _______
\ Y / _ \_/ __ \_ __ \ |/ /\__ \
\ ( <_> ) ___/| | \/ < / __ \_
\___/ \____/ \___ >__| |__|_ \(____ /
\/ \/ \/
版本号:1.0.0
Usage: flexapp [options] [command]
Options:
-v, --version 当前版本号
-h, --help 显示帮助
Commands:
init [options] 初始化应用 // 只有这个命令
- 接下来我们安装
@flexapp/vue
::: code-group
shell
npm install @flexapp/vue @flexapp/vue
shell
pnpm add @flexapp/vue @flexapp/vue
shell
yarn add @flexapp/vue @flexapp/vue
:::
此时再执行一下flexapp
命令,会看到如下输出:
bash
____ ____ __
\ \ / /___ ___________| | _______
\ Y / _ \_/ __ \_ __ \ |/ /\__ \
\ ( <_> ) ___/| | \/ < / __ \_
\___/ \____/ \___ >__| |__|_ \(____ /
\/ \/ \/
版本号:1.0.0
Usage: flexapp [options] [command]
Options:
-v, --version 当前版本号
-h, --help 显示帮助
Commands:
init [options] 初始化应用
# dev命令是由@flexapp/vue包提供的
dev [options] 以开发模式启动应用 // [!code ++]
第5步: 自动推断交互提示
在上面dev
命令中,共指定了6
个选项,当执行flexapp dev
命令时, 会根据配置自动交互引导用户输入选项,如下:
- 命令行的交互体验与使用
commander
时完全一样 - 仅当选项未指定默认值或满足一定条件时,才会根据一定的规则自动推断交互提示类型。详见自动推断交互提示
MixedCli
使用prompts
来实现交互提示,因此支持prompts
的所有交互类型特性。详见prompts
小结
MixedCli
是一个基于commander
的命令行工具开发框架,提供了一套命令行开发的最佳实践。MixedCli
能对所有命令行选项自动推断交互提示类型,当用户没有输入选项时,会自动引导用户输入选项,提供友好的用户体验。MixedCli
可以在当前工程自动搜索满足条件的包下声明的命令进行合并,从而实现扩展命令的目的。此特性可以保持@flexapp/cli包的精简和稳定,给用户一致的体验。