手写一个自己的脚手架

406 阅读3分钟

为什么要实现自己的脚手架?

痛点:重复性的开发项目的时候,要不断的复制粘贴,或者新建一个项目时,要复制另外一个项目,然后删除里面的代码。

常见的脚手架: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

image.png

image.png

image.png

image.png

#! /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






image.png