脚手架工具开发
项目创建
初步创建
创建index.js
- 编写一些简单代码
创建package.json
- npm init -y
创建hype 命令
入口文件中,添加如下指令(shebang也称为hashbang)
- #!/usr/bin/env node
- 根据配置环境执行当前文件
- #!/usr/bin/env node
修改package.json
1
2
3"bin":{
"hype":"index.js"
}npm link
Commander的使用
npm install commander
1
2
3
4
5
6
7const program = require('commander')
//查看版本号
program.version(require('./package.json').version)
//解析终端指令
program.parse(process.argv)1
2
3
4
5
6
7
8
9
10
11
12
13
14//添加自己的option
const program = require('commander')
const helpOptions = () => {
//增加自己的options
program.option('-h --hype', 'a hype cli')
program.option('-d --dest<dest>', 'a destination folder,例如:-d /src/components')
program.option('-f --framework<framework>', 'your framework')
program.on('--help', function () {
console.log("");
console.log("other");
console.log(" ohter options");
})
}创建项目指令实现思路
创建解析create指令
1
2
3
4
5
6
7
8
9
10
11const program = require('commander')
const {createProjectAction}=require('./action')
const createCommands =()=>{
program
.command('create <project> [others...]')
.description('clone a repository into a folder')
/*会在action中执行相关函数*/
.action(createProjectAction)
}
module.exports= {createCommands}通过download-git-repo从代码仓库中下载模板
1
2
3download('flippidippi/download-git-repo-fixture', 'test/tmp', function (err) {
console.log(err ? 'Error' : 'Success')
})1
2利用内部的一个方法 可以将代码转成promise形式
const {promisify} = require('util')1
await download(vueRepo,project,{clone: true});
进入目录,并且执行
npm install
命令执行终端命令
const { spawn } = require(‘child_process’) // 子进程
child_process.spawn(command[, args][, options])
which/where yarn/npm...
查看所在路径需要加上一个判断是否是windows系统
1
2const command = process.platform === 'win32' ? 'npm.cmd' : 'npm'
await commandSpawn(command,['install'],{ cwd: `./${project}` })
执行
npm run serve
命令1
await commandSpawn(command, ['run','serve'],{cwd: `./${project}`})
打开浏览器
- open()
- 但是在vue cli 自己打开浏览器是通过webpack 做的 因为它知道启用的哪个端口
实现其他的指令
addcpn
首先要有一个组件的模板 .ejs
- ejs的一个语法:
<%= %>
- ejs的一个语法:
编译ejs模板 result字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const compile = (tempName,data)=>{
const templatePosition = `../templates/${tempName}`
const templatePath = path.resolve(__dirname,templatePosition)
console.log(templatePath);
return new Promise((resolve,reject)=>{
ejs.renderFile(templatePath,{data},{},(err,result)=>{
if(err){
console.log(err);
reject(err);
return
}
resolve(result)
})
})
}1
const result = await compile('vue-component.ejs',{name,lowerName:name.toLowerCase()})
将result写入到.vue 文件
1
2
3
4
5
6
7
8
9program
.command('addcpn <name>')
.description('add vue component , 例如:hype addcpn HelloHype -d src/components')
.action((name)=>{ 敲完指令执行的action
addCpnAction(name,program.dest || 'src/components') ->dest出处
})
const targetPath = path.resolve(dest,`${name}.vue`)
writeTofile( targetPath,result)放到对应的文件夹
addcpn的逻辑
addpage
1
2
3
4
5
6program
.command('addpage <page>')
.description('add vue page and router config, 例如: hype addpage Home [-d src/pages]')
.action((page) => {
addPageAndRouteAction(page, program.dest || 'src/pages')
})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//添加组件 路由
const addPageAndRouteAction = async (name, dest) => {
// 1.编译ejs模板
const data = {name, lowerName: name.toLowerCase()};
const pageResult = await compile('vue-component.ejs', data);
const routeResult = await compile('vue-router.ejs', data);
// 3.写入文件
const targetDest = path.resolve(dest, name.toLowerCase());
if (createDirSync(targetDest)) {
const targetPagePath = path.resolve(targetDest, `${name}.vue`);
const targetRoutePath = path.resolve(targetDest, 'router.js')
writeToFile(targetPagePath, pageResult);
writeToFile(targetRoutePath, routeResult);
}
}生成路径方法
createDirSync
1
2
3
4
5
6
7
8
9
10const createDirSync = (pathName) => {
if (fs.existsSync(pathName)) {
return true;
} else {
if (createDirSync(path.dirname(pathName))) {
fs.mkdirSync(pathName);
return true;
}
}
}写入文件方法
writeToFile
1
2
3
4const writeToFile = (path, content) => {
// 判断path是否存在, 如果不存在, 创建对应的文件夹
return fs.promises.writeFile(path, content);
}
- addstore与addpage类似
项目发布
- 在npm网站创建账号
- npm login 登陆
- npm publish 发布
- 更新的话更新package.json中的版本号
然后npm install -g coderhyp
就可以使用啦