如何搭建一个 cli 脚手架

175 阅读2分钟

前言

react cra 脚手架 vue 的 cli 脚手架

create-react-app init 简单的一行命令就可以生成一个项目 非常高效快捷

背景

没此的初始化项目都要从头开始 很繁琐

每个人搭建的项目基础环境 有所不一样

需要升级版本了 不能统一收口升级

如何搭建

  1. 需要用第三方工具库

    commander 用于处理用户输入的命令 可以自动的解析命令和参数

    download-git-repo 用于下载git项目模板

    inquirer 用于跟用户之间的交互操作

    ora 下载过程中的动画

  2. 有了上面的工具 我们开始进行下一步的代码操作

    2.1 简易流程

    2.2 初始化

    • 新建一个项目 创建package.json文件
      {
        "name": "xxx",
        "version": "1.0.0",
        "description": "脚手架搭建",
        "main": "index.js",
        "bin": {
          "cli": "./index.js"  // 入口
        }
      }
    
    • index.js
      #!/usr/bin/env node
      console.log('cli')
    

    (#!/usr/bin/env node 让系统动态来查找node执行的脚本)

    • 需要 npm link 到全局node_modules 可以执行cli命令
      npm link
      cli
    

    2.3 下面开始编写我们index.js 命令交互

    • commander 来获取参数
     const program = require("commander")
     const pkg = require("../package.json")
     program
      .version(pkg.version)
      .usage(`cli`)
      .option("-i, --init", "初始化项目")
      .option("-v, --version", "查看版本号信息")
      .option("-l, --list", "查看可用模版列表")
    
    • 执行 用户输入不同命令的脚本
      if(program.opts().init)){
        programInit()
      }
      if(program.opts().list)){
        programList()
      }
    
    • programList()
      const programList =()=> {
        Object.values(obj).forEach(item => {
          console.log(`xxxxx`);
        })
      }
    
    • programInit()
      const inquirer = require("inquirer");
      let choices = Object.values(xx).map(item => {
        return {
         xx
          xxx
        };
      });
      inquirer
      .prompt([
        {
          type: "input",
          name: "projectName",
          message: "请输入项目名称",
        },
        {
          type: "list",
          name: "select",
          message: "选择其中一个作为项目模版",
          choices: [new inquirer.Separator(), ...choices]
        },
      ])
      .then((data) => {
        initTemplate(data);  // 开始初始化
      });
    
    • initTemplate
      const { projectName, git } = data;
      // 检测项目
      await checkName(projectName);
    
      const spinner = ora("download template......").start();
      // 下载地址
      await downloadTel(git, projectName, spinner);
    
      // 处理项目
      await detailFile(resObj,spinner)
    
      // afterBuild
      buildSuccess(projectName)
    
    • checkName() 检测项目名是否存在
      const checkName =(projectName)=> {
        return new Promise((resolve, reject) => {
          fs.readdir(process.cwd(), (err, data) => {
            if (err) {
              return reject(err);
            }
            resolve();
          });
        });
      }
    
    • downloadTe() 开始下载
     const download = require('download-git-repo')
     const downloadTel =(git, projectName) => {
      return new Promise((resolve, reject) => {
        download(`direct:${git}`, projectName, { clone: true }, (err) => {
          if (err) {
            console.error(err)
            reject(err)
          } else {
            resolve()
          }
        })
      })
    }
    
    • detailFile() 方法 处理下载后代码 处理package.json文件入口 作者等等

    • buildSuccess() 成功

      const buildSuccess = (name) => {
        console.log(chalk.green(`\n    cd ${name}`))
        console.log(chalk.green('    npm install'))
        console.log(chalk.green('    npm start\n'))
      }
    

结语

搭建出一个简单的脚手架工具 但是里面知识点还有很多 比如 download-git-repo 如何实现下载的 要是sso登录咋办等等 还需要继续学习