为什么要实现自己的脚手架?
痛点:重复性的开发项目的时候,要不断的复制粘贴,或者新建一个项目时,要复制另外一个项目,然后删除里面的代码。
常见的脚手架:vue-cli
node 会执行bin目录下面的文件
1.先创建可执行的脚本 #! /usr/bin/env node
#! /usr/bin/env node
告诉shell用当前系统的node环境来执行这段代码。
2.配置package.json中的bin字段
{
"name": "mycli", // 这个name是脚手架的名字
"version": "1.0.0",
"description": "",
"main": "index.js",
"bin": "./bin/mycli",
// 不加bin,npm link 不会把文件链接到/usr/local/bin 目录下,
// 只会生成这样的链接 /usr/local/lib/node_modules/my-cli -> /Users/yujunjiao/Desktop/my-cli
"bin":{
"cli":"./bin/mycli", // cli是脚手架的名字
"mycli":"./bin/mycli", // mycli是脚手架的名字
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
此时这个命令并不能执行,能执行的原因是:会找到全局的bin这个目录,我们要把这个包放到全局下才能被找到,然后执行 3.把包临时连接到本地全局环境中 npm link
执行 npm link
/usr/local/bin/my-cli -> /usr/local/lib/node_modules/my-cli/bin/mycli
/usr/local/lib/node_modules/my-cli -> /Users/yujunjiao/Desktop/my-cli
链接映射:把my-cli文件夹放到了本地全局的bin目录下(这样执行命令的时候就能找到这个文件),
然后去找本地lib目录下的node_modules下找my-cli这个文件夹,根据这个文件夹的package.json配置的bin字段,
找到这个脚本真正要执行的文件,
然后/usr/local/lib/node_modules/my-cli 找的是/Users/yujunjiao/Desktop/my-cli这文件,
最后找到的就是/Users/yujunjiao/Desktop/my-cli/bin/mycli
所以全局使用的/usr/local/bin/my-cli这个文件最终指向了/Users/yujunjiao/Desktop/my-cli/bin/mycli
link 相当于将当前本地模块连接到npm目录下,这个npm目录可以直接访问,所以当前包就可以直接访问了,把包链接到全局下,
当我们执行命令的时候,就会执行这个包对应的文件。
直接执行 mycli
#! /usr/bin/env node
// 脚本的文件夹不能是 my-cli 不识别
// console.log('my-cli');
//1.配置可执行的命令 commander
const program = require('commander')
const fs = require("fs")
const chalk = require('chalk')
// 核心功能 1.创建项目 2.修改配置文件 3.ui界面(@vue/ui)
program
.command('create <app-name>') // command 后面接受的参数从 create 后面第一个参数开始,后面会被自动添加 args, cmd
.description('create a new project')
.option('-f,--force', 'overwrite tartget directory if it exists')
.action((name, args, cmd)=>{
console.log(name, args, cmd);
require('../lib/create')(name, args)
})
program
.command('config <value> <value>') // command 后面接受的参数从 option 的第二个参数开始,后面会被自动添加 args, cmd
.description('inspect an modify the config')
.option('-g,--get <name1>', 'check then config')
.option('-s,--set <name1> <value1>', 'modify then config')
.action((value1,value2, args, cmd)=>{
console.log(value1, value2, args['set']);
// console.log(name, value, args, cmd);
})
program.on('--help',()=>{
console.log('');
console.log(`Run ${chalk.cyan('mycli <command> --help')} show detail`)
console.log('');
})
program.version(`mycli ${require('../package.json').version}`)
.usage(`<command> [option]`)
//解析用户执行命令传入的参数
program.parse(process.argv) // 这个配置之后有 --help,这个不配置解析不了命令行参数
//2.要实现一个脚手架,要做一个命令行交互的功能 inquirer
//3.模板下载下来 download-git-repo
//4.根据用户的选择动态生成内容 metalsmith