1.自定义命令和入口配置
首先创建一个文件夹,然后npm init -y生成package.json文件
添加bin命令配置入口文件
新建lib/index.js文件
然后在控制台npm link 建立软连接 、然后执行felix-cli 就可以输出代码
2.查看当前版本号命令
安装 commander
npm i commander
lib/index.js
#!/usr/bin/env node
const {program} = require('commander')
// 处理--version的操作
const version = require('../package.json').version
program.version(version,'-v --version')
// 让commander解析process.argv的参数
program.parse(process.argv)
3.增加options选项和封装
新建lib/core/help-options.js文件
help-options.js
const { program } = require('commander')
function helpOptions() {
// 1.处理--version的操作
const version = require('../../package.json').version
program.version(version, '-v --version')
// 2.增强其他的options的操作
program.option('-w --why', "a why cli program~")
program.option('-d --dest <dest>', 'a destination folder, 例如: -d src/components')
program.on('--help', () => {
console.log("")
console.log("others:")
console.log(" xxx")
console.log(" yyy")
})
}
module.exports = helpOptions
lib/index.js
#!/usr/bin/env node
const {program} = require('commander')
const helpOptions = require('./core/help-options')
// 1.配置所有的options
helpOptions()
// 让commander解析process.argv的参数
program.parse(process.argv)
4.create命令创建项目过程
安装download-git-repo,主要用于从远程仓库下载模板
npm i download-git-repo
lib/index.js
const { createProjectAction } = require('./core/actions')
// 2.增加具体的一些功能操作
program
.command("create <project> [...others]")
.description("create vue project into a folder, 比如: felix-cli create vue3-template")
.action(createProjectAction)
lib/core/actions
const { promisify } = require('util')
const download = promisify(require('download-git-repo'))
const { VUE_REPO } = require('../config/repo')
async function createProjectAction(project) {
try {
// 1.从编写的项目模板中clone下来项目
await download(VUE_REPO, project, { clone: true })
} catch (error) {
console.log("github连接失败, 请稍后重试")
}
}
module.exports = {
createProjectAction,
}
lib/config/repo.js
const VUE_REPO = "direct:https://gitee.com/hktklifusheng/vue3-template#master"
module.exports = {
VUE_REPO
}
然后可以新建一个文件夹,在控制台输出以下命令 就可以新建模板
felix create template
5.脚手架执行安装与运行命令
在下载完模板后自动执行安装包和运行项目
lib/core/actions.js
const { promisify } = require('util')
const download = promisify(require('download-git-repo'))
const { VUE_REPO } = require('../config/repo')
const execCommand = require('../utils/exec-command')
async function createProjectAction(project) {
try {
// 1.从编写的项目模板中clone下来项目
await download(VUE_REPO, project, { clone: true })
// 2.很多的脚手架, 都是在这里给予提示
// console.log(`cd ${project}`)
// console.log(`npm install`)
// console.log(`npm run dev`)
// 3.帮助执行npm install
console.log(process.platform)
const commandName = process.platform === 'win32' ? 'npm.cmd' : 'npm'
await execCommand(commandName, ["install"], { cwd: `./${project}` })
// 4.帮助执行npm run dev
await execCommand(commandName, ["run", "dev"], { cwd: `./${project}` })
} catch (error) {
console.log("github连接失败, 请稍后重试")
}
}
module.exports = {
createProjectAction,
}
utils/exec-command
const { spawn } = require('child_process')
function execCommand(...args) {
return new Promise((resolve) => {
// npm install/npm run dev
// 1.开启子进程执行命令
const childProcess = spawn(...args)
// 2.获取子进程的输出和错误信息
childProcess.stdout.pipe(process.stdout)
childProcess.stderr.pipe(process.stderr)
// 3.监听子进程执行结束, 关闭掉
childProcess.on('close', () => {
resolve()
})
})
}
module.exports = execCommand
6.脚手架创建添加组件的过程
要安装ejs js的模板引擎
npm i ejs
lib/index.js
const { addComponentAction} = require('./core/actions')
program
.command("addcpn <cpnname> [...others]")
.description("add vue component into a folder, 比如: whycli addcpn NavBar -d src/components")
.action(addComponentAction)
lib/core/actions.js
const compileEjs = require('../utils/compile-ejs')
const writeFile = require('../utils/write-file')
const { program } = require('commander')
async function addComponentAction(cpnname) {
// 1.创建一个组件: 编写组件的模板, 根据内容给模板中填充数据
const result = await compileEjs("component.vue.ejs", {
name: cpnname,
lowername: cpnname.toLowerCase()
})
// 2.将result写到到对应的文件夹中
const dest = program.opts().dest || "src/components"
await writeFile(`${dest}/${cpnname}.vue`, result)
console.log("创建组件成功:", cpnname + ".vue")
}
module.exports = {
addComponentAction
}
lib/utils/compile-ejs.js
const path = require('path')
const ejs = require('ejs')
function compileEjs(tempName, data) {
return new Promise((resolve, reject) => {
// 1.获取当前模板的路径
const tempPath = `../template/${tempName}`
const absolutePath = path.resolve(__dirname, tempPath)
// 2.使用ejs引擎编译模板
ejs.renderFile(absolutePath, data, (err, result) => {
if (err) {
console.log("编译模板失败:", err)
reject(err)
return
}
resolve(result)
})
})
}
module.exports = compileEjs
lib/utils/write-file.js
const fs = require('fs')
function writeFile(path, content) {
return fs.promises.writeFile(path, content)
}
module.exports = writeFile
然后就可以在模板的控制台中输入felix addcpn navbar,就能新建组件了
或者指定目录elix addcpn navbar --dest src/views/home/c-cpns