这是我参与更文挑战的第9天,活动详情查看: 更文挑战
现在的代码还是基于上一篇脚手架文章的代码
一、commander脚手架初始化
使用lerna创建commander
lerna create @zl-cli-dev/command
复制代码
然后把文件夹移动到models下,修改好index文件夹后,我们需要把commder被init继承。
在commands/init中导入依赖,
package.json
"dependencies": {
"@zl-cli-dev/command": "./../../models/command"
}
npm link
复制代码
文件夹中使用如下
const Command = require('@zl-cli-dev/command')
class InitCommand extends Command {
}
function init(argv) {
return new InitCommand(argv)
}
module.exports = init
module.exports.InitCommand = InitCommand;
复制代码
现在我们可以修改command中的代码了
class Command {
constructor(argv) {
console.log('Command constructor', argv)
}
init() {
throw new Error('init必须实现')
}
exec() {
throw new Error('exec必须实现')
}
}
module.exports = Command;
复制代码
修改exec中index.js
if(rootFile) {
// 在当前进程中使用
require(rootFile).call(null, Array.from(arguments))
// 在node子进程中调用
}
复制代码
运行下代码,看我们的输出知否正常
zl-cli-dev init --targetPath F:\2021\web-jg\week2\zl-cli-dev\commands\init --debug test-project --force
复制代码
看到一下结果大概就是好了
与此同时,要将检查node的版本号的方法移动过来
在core/cli/lib/index.js
function checkNodeVersion() {
const currentVersion = process.version
const lowestVersion = constant.LOWEST_NODE_VERSION
if(!semver.gte(currentVersion, lowestVersion)) {
throw new Error(colors.red(`zl-cli 需要安装 v${lowestVersion}以上版本的Node.js`))
}
}
复制代码
移动这个方法,还需要在command中加载semver和colors依赖
npm install -S semver
npm install -S colors
复制代码
改造之后代码如下
const semver = require('semver')
const colors = require('colors/safe')
const LOWEST_NODE_VERSION = '12.10.0'
class Command {
constructor(argv) {
// console.log('Command constructor', argv)
this._argv = argv
let runner = new Promise((resolve, reject) => {
let chain = Promise.resolve()
chain = chain.then(() => this.checkNodeVersion())
})
}
checkNodeVersion() {
const currentVersion = process.version
const lowestVersion = LOWEST_NODE_VERSION
if(!semver.gte(currentVersion, lowestVersion)) {
throw new Error(colors.red(`zl-cli 需要安装 v${lowestVersion}以上版本的Node.js`))
}
}
init() {
throw new Error('init必须实现')
}
exec() {
throw new Error('exec必须实现')
}
}
module.exports = Command;
复制代码
二、初始化
参数初始化操作
// 参数初始化操作
chain = chain.then(() => this.initArgs())
复制代码
初始化方法
initArgs() {
this._cmd = this._argv[this._argv.length - 1]
this._argv = this._argv.slice(0, this._argv.length - 1)
}
复制代码
可以通过
zl-cli-dev init --targetPath F:\2021\web-jg\week2\zl-cli-dev\commands\init --debug test-project --force
复制代码
输出下this._cmd和this._argv.
同时要对参数argv做判断,判断参数不能为空,必须为数组且不能为空
if (!argv) {
throw new Error('参数不能为空!')
}
if(!Array.isArray(argv)) {
throw new Error('参数必须为数组!')
}
if(argv.length < 1) {
throw new Error('参数列表为空!')
}
复制代码
在这里我们修改下exec/lib/index.js
try {
// 在当前进程中使用
require(rootFile).call(null, Array.from(arguments))
// 在node子进程中调用
} catch (e) {
log.error(e.message)
}
复制代码
使用try catch优化下输出
然后新加init和exec两个方法的调用,以及catch的监听
chain = chain.then(() => this.init())
chain = chain.then(() => this.exec())
chain.catch(err => {
log.error(err.message)
})
复制代码
现在初始化commands/init中的方法
init() {
this.projectName = this._argv[0] || ''
this.force = !!this._cmd.force
log.verbose('projectName: ' + this.projectName)
log.verbose('force: ' + this.force)
}
复制代码
通过this._argv我们拿到了项目名称,通过this._cmd我们拿到了force的状态
导入log,我们就可以使用log.verbose了。同时创建我们的init的业务逻辑
exec() {
console.log('init的业务逻辑')
}
复制代码
三、动态执行代码
在执行完上边的代码后,修改下之前的一块代码,exec/lib/index.js
if(rootFile) {
try {
// 在当前进程中使用
// require(rootFile).call(null, Array.from(arguments))
// 在node子进程中调用
const code = 'console.log(1)'
const child = cp.spawn('node', ['-e', code], {
cwd: process.cwd(),
stdio: 'inherit'
})
child.on('error', e => {
log.error(e.message)
process.exit(1)
})
child.on('exit', (e) =>{
log.verbose('命令执行成功:'+ e)
process.exit(e)
})
} catch (e) {
log.error(e.message)
}
}
复制代码
现在我们要拼接code,动态的拼接
const args = Array.from(arguments)
const cmd = args[args.length - 1]
const o = Object.create(null)
Object.keys(cmd).forEach(key => {
if (cmd.hasOwnProperty(key) && !key.startsWith('_') && key !== 'parent') {
o[key] = cmd[key]
}
})
args[args.length - 1] = o
const code = `require('${rootFile}').call(null, ${JSON.stringify(args)})`
复制代码
输入命令
zl-cli-dev init --targetPath F:\2021\web-jg\week2\zl-cli-dev\commands\init --debug --force test-project
复制代码
有一下输出就说明我们代码正常运行了!
四、windows操作系统spawn执行
方法如下
function spawn(command, args, options) {
const win32 = process.platform === 'win'
const cmd = win32 ? 'cmd': command
const cmdArgs = win32 ? ['/c'].concat(command, args) : args
return cp.spawn(cmd, cmdArgs, options || {})
}
复制代码
对windows系统做判断。替换到执行cp.spawn
const child = spawn('node', ['-e', code], {
cwd: process.cwd(),
stdio: 'inherit'
})
复制代码
再次命令,得到一下结果
成功了!!!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END