命令的解析与分发,是「全局命令包」的核心功能,其过程比较简单。大家也可以直接看仓库cli-tpl (全部功能压缩到大约300行代码)
cli 版本更新判断:
先获取本 package.json 中的 version
再通过 npm view cli-tpl version 命令查询当前 npm 库最新版本
两者比较得出结论,提醒用户更新
解析用户命令
通过 process.argv[2] 获取到用户执行的实际命令,比如 dcli install 可拿到 install (正式版推荐使用 minimist 解析参数)
处理命令
比如 install 命令,则通过 require 动态映射 install.js 文件来处理该逻辑
注:require 支持动态名称,如 require('./scripts/' + command) 这样,如果 command 是 install 则映射执行 script/install.js 文件
接下来我们看下 4 个核心命令,主要是:
命令
效果
install
帮用户安装/升级一个「模板插件包」
init
帮用户初始化一个工程,并拷贝模板
build
调用工程中的「构建插件包」,帮用户webpack构建
dev
帮用户启动 devServer 进行调试
下面逐一阐述每个命令的实现过程以及效果:
5.3 install命令:安装一个「模板插件包」
install 意思就是把这个模板插件包下载到硬盘;此处我做了一个最小功能的 demo 包gen-tpl (后文详细分解) 来辅助讲解
dcli install gen-tpl
核心处理流程如下:
先判断是否硬盘缓存目录 ~/.maoda 下是否已经有安装过 gen-tpl 包
如果没有,则接下来进行安装 (相当于在 ~/.maoda 目录下执行 npm install)
如果有,且版本低,则提示升级
如果有,且版本最新,则不作为
安装过程即 execSync('npm i gen-tpl@latest -S', { cwd: '~/.maoda' })
我们可以为「模板插件包」的名称做一个约定,即具备固定的前缀,诸如 gen-xxx
5.4 init命令: 选一个「模板插件包」来初始化一个新工程
这是一个脚手架高频而核心的功能
dcli init
此时会分发去执行 script/init.js 文件,我们看看其逻辑
查询硬盘缓存目录 ~/.maoda 下的 package.json 文件,读取其中 dependacies 字段,拿到已安装的「模板插件包」
如果一个都没安装,则提示用户要先 install
让用户选择一套模板
利用 inquery 库发起对话,罗列出已装模板,让用户选择,比如上图的 gen-pc gen-h5 gen-tpl
触发模板初始化流程
比如用户选择了 gen-tpl 这个模板,则用 yeoman-environment 这个库去执行缓存目录里的这个包 ~/.maoda/gen-tpl/index.js
注:这里相当于跨目录的两个 js 文件引用执行,用到了之前说的 import-from 这个库
「模板插件包」被执行,则启动了常规的模板拷贝过程 (后面展开细说)
这里直接用包名称做选项,为了演示更直观,实际通常用包的 description 做选项,更友好一些,比如 gen-pc 包可能描述为 生成PC模板
5.5 build命令:在工程里执行构建
dcli build
确定工程目录
工程目录即执行目录,通过 process.cwd() 获取
读取该工程所用的构建插件
读取工程中约定的配置文件,本demo中为 maoda.js (采用约定式的配置,类似 webpack.config.js .babelrc .prettierrc)
读取 maoda.js 中 builder 配置项 (即指定的构建插件包),比如本 demo 中指定为 build-tpl
如果有的话,读取自定义 webpack 配置 (约定为 webpackCustom 字段,后续会被合并/覆盖到默认 webpack 配置上)
使用制定的构建插件包来进行 webpack 打包
判断工程中是否已经安装 build-tpl
未安装,则在工程中路径中执行 npm install (或 yarn add,此处有个小技巧,可根据用户工程中 lock 文件的类型,判断用户使用的 npm 还是 yarn)
已安装,则直接执行 build-tpl