Open chenqiushi opened 5 years ago
整体思路差不多,但是 utils 感觉没必要拆成包吧,直接跟着 CLI 一起升级感觉就可以了
我觉得 CLI 可以分成 core 和 功能插件两部分,core 负责命令行的解析和插件调度,并且提供:
# 安装插件
mip2 install xxx
# 卸载插件
mip2 remove xxx
# 升级插件
mip2 update xxx/all
# 打印当前已安装的插件列表,可打印插件名和当前插件版本号、是否存在最新版等信息
mip2 list
# 查看当前 MIP2 版本
mip2 version
其他可能还缺少的部分可以补充。
默认采用 npm 包的方式进行 MIP2 插件管理,比如 mip2-plugin-dev
则对应 mip2 dev -xxx -xxx
,mip2-plugin-dev-sf
则对应 mip2 dev sf --xxx ---xxx
。
为了插件开发时本地调试方便,应该要提供一种加载本地插件的方法。这个我们讨论一下。
功能插件在安装好之后,可以通过 mip2 xxx xxxxx
的方式调用,比如 mip2-plugin-dev 的插件的命令为:
mip2 dev xxxxx
这样 CLI 会自动解析好相关参数并传递给对应的插件进行执行
在实践过程当中,发现一种情况比较常见,就是插件的复用机制。比如目前现有的 mip-cli-plugin-sf 在功能上依赖了 mip2-dev 的编译和路由功能。关于这一块我的想法是增加一个插件的复用机制,通过 webpack/tapable
的方式进行组织,由 dev 模块通过 tapable 机制主动暴露钩子、方法等等,然后由其插件主动进行控制。
所有的插件都挂载到一个 global.MIP2 的大对象上,通过 MIP2.require('xxx')
的方法去加载其他插件,CLI 会自动去查找插件并返回插件对象,如果不存在则提示用户下载或者自动下载。
这里主要问题在于,插件是需要继承自一个由 CLI 核心提供的共同基类呢,还是统一一个对象格式,由插件开发者自行按照格式实现即可。如果统一使用 CLI 提供的基类,那么插件是无法独立于 CLI 直接使用的,比如 mip2-build,在编译上线的项目当中其实可以直接使用这个包进行上线即可,并不需要先通过 CLI 加载执行 mip2-build 去进行组件上线编译。
所以这里估计也得讨论一下。
目前 mip2 dev 只提供了全量编译的功能,目前开发的组件越来越多,在初始启动的时候会变得有些慢了,所以需要支持组件在 dev 模式下的增量编译。即通过 server 访问到对应组件的时候再将其添加到 webpack 的 entry 中进行编译;
目前 dev 的 proxy 只是基于源码替换 URL 的 proxy,应该升级成真正的 proxy,从目前的反馈来看,通过 proxy 来解决开发时跨域问题的需求还是很多的;
VALIDATE 功能升级
mip2-plugin-dev 则对应 mip2 dev -xxx -xxx,mip2-plugin-dev-sf 则对应 mip2 dev sf --xxx ---xxx
这一块 mip2 dev sf 应该是属于 mip2 dev 的子命令,可以同属一个插件 mip2-plugin-dev 来管理。不然如果有 mip2 dev sf2 , mip2 dev sf3 不是得发布 3 个插件。
所有的插件都是 mip2-plugin-<name>
的形式
dev 可以集成自己的 a b c 命令,也可以外部插件扩展 sf,我的意思是这样子的,就跟 CLI 允许内置插件和扩展插件一样,可以增加插件灵活性
经讨论,明确了几个问题:
每个插件模块对外暴露的是一个对象,对象的接口格式由 CLI 或者一个公用的 utils 包来进行统一;插件以依赖的形式去调用其他插件,而不是以 MIP2.require('xxx') 的方式去管理,CLI 只负责命令解析和插件调度、插件升级卸载等等;
插件统一对外暴露的对象里面必须提供的 run 方法用于接收参数,并且插件的功能是完整的,不依赖 CLI 提供任何功能,因此可以直接通过 const plugin = require('xxx') ;
plugin.run({xxx})
的方式进行具体功能的直接使用
目录组织形式初定如下(具体随时修改):
mip2/packages
|-- mip-cli
| |-- cli
| | |-- bin
| | `-- mip2
| | |-- lib
| | |-- utils
| | |-- ...
| | |-- README.md
| | `-- package.json
| |-- cli-plugin-dev
| | |-- src
| | |-- README.md
| | `-- package.json
| |-- cli-plugin-build
| | |-- src
| | |-- README.md
| | `-- package.json
| |-- cli-plugin-validate
| | |-- src
| | |-- README.md
| | `-- package.json
| |-- cli-plugin-utils
| | |-- src
| | |-- README.md
| | `-- package.json
| |-- ...
| `-- ...
|
`-- mip
其中 ,mip-cli/cli
模块是命令行工具本身,主要完成:
cli-plugin-<name>
是官方插件,相互之间可以进行调度,具体方式 @clark-t 可以补充
Plugins 之间存在一些需要公用的方法和模块,如 logger
env
exit
等,抽离出来在 cli-plugins-utils
里进行管理,开发插件时可以引入避免冗余。
Plugins 可以独自管理发布,单个 plugin 能够以 nodejs 模块的形式引入,以编程的方式使用,如:
const build = require('mip-cli-plugin-build');
build(foo, bar);
也可以安装 mip2
CLI,通过命令行工具进行调度:
npm install mip2
mip2 build
为避免命名上的冲突,我觉得 cli-plugins-utils 应该命名为 cli-utils 会比较好点,npm 包名为 mip-cli-utils; utils 除了提供公用方法之外,还提供 TS 的类型定义之类,统一约束 CLI 插件对外暴露的格式;
插件我认为应该对外暴露的是一个对象而不是方法:
{
command,
run({/* 参数 */}),
/* api */
/* hooks */
}
其中 plugins.run({/ ... /}) 就等价于秋实君上面提到的 build(foo, bar)
的调用方式
目前有个问题,比如在开发模式下除了最基础的 webpack 和 server 之外,可能还需要 proxy、autoreload、autoopen 等功能,但这些不是必须的,比如 autoopen 功能目前在 1.0 里面几乎是默认不开启的,所以这些功能是否也可以插件化?也就是插件的插件,然后给开发者提供配置方法比如通过 mip.config.js 去决定是否使用某些插件
要解决什么问题
描述一下你理想中的解决方案
CLI 应提供一种方式(如一个 plugin 包 cli-shared-utils),暴露命令行常用接口(logger、spinner、server、env 等)给插件使用。
描述你的备选方案 清晰准确的描述你考虑的备选方案
补充信息 补充其他信息,如截图等