思维导图:
屏幕快照 2020-07-11 下午6.56.27.png

1、初始化项目

mkdir auto-cli
cd auto-cli
npm init -y
npm i commander download-git-repo ora handlebars figlet clear chalk open watch -s

2、新建CLI命令文件: 新建auto-cli/bin/kkb.js命令文件

#!/us/bin/env node   // 指定解析环境为node
console.log('auto-cli....')

const program = require('commander') //命令行工具
program.version(require('../package.json').version) // 或直接写 '1.0.1'

program
    .command('init <name>') // 定义init命令
    .description('init project')
    .action(name => { // 指定命令要做什么事,回调函数中实现命令功能
      console.log('init ' + name);
    })

    program.parse(process.argv)

3、添加bin命令,修改package.json:

{
  "bin": {
    "kkb": "./bin/kkb.js",
  },
}

4、链接命令:执行npm link,把命令链接到全局,相当于全局安装项目。
最后在命令行运行kkb,就会执行auto-cli/bin/kkb.js命令文件。简单的cli命令工具就完成了。

进阶1:在控制台打印个性化欢迎界面

(1)新建/lib/init.js文件
const {promisify} = require('util') // util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足
const figlet = promisify(require('figlet')) //  util.promisify() 这个方法,方便快捷的把原来的异步回调方法改成返回 Promise 实例的方法

const clear = require('clear')
const chalk = require('chalk')
const log = content => console.log(chalk.green(content));

module.exports = async name => {
  // 打印欢迎界面
  clear()
  const data = await figlet('KKB Welcom') // figlet是把文字变成大字
  log(data);
}

(2)修改init命令回调函数
program
    .command('init <name>') // 定义init命令
    .description('init project')
    .action(require('./init.js'))

    program.parse(process.argv)

此时执行kkb init xx,就会在控制台输出大字界面。

进阶2:通过init命令初始化项目

初始化项目的本质就是从gitlab上下载一个项目模板到本地。
(1)新建/lib/download.js文件,实现下载模板
const {promisify} = require('util')

module.exports.clone = async function(repo, desc) {
  const download = promisify(require('download-git-repo')) // download-git-repo: Download and extract a git repository (GitHub, GitLab, Bitbucket)
  const ora = require('ora')
  const process = ora(`下载......${repo}`)
  process.start() // 进度条开始
  await download(repo, desc)
  //  download-git-repo导出的download方法,第一个参数repo是仓库地址,格式有三种:
  // GitHub - github:owner/name or simply owner/name
  // GitLab - gitlab:owner/name
  // Bitbucket - bitbucket:owner/name
  process.succeed()
}

(2)在/lib/init.js中引入download.js,完成项目初始化
const {promisify} = require('util') // util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足
const figlet = promisify(require('figlet')) //  util.promisify() 这个方法,方便快捷的把原来的异步回调方法改成返回 Promise 实例的方法

const clear = require('clear')
const chalk = require('chalk')
const log = content => console.log(chalk.green(content));
const {clone} = require('./download')

module.exports = async name => {
  // 打印欢迎界面
  clear()
  const data = await figlet('KKB Welcom') // figlet是把文字变成大字
  log(data);

  // clone
  log(`创建项目: ${name}`);
  await clone('github:su37josephxia/vue-sample', name)
}

进阶3:自动安装依赖,自动启动和打开浏览器,在node中执行shell命令

(1)在/lib/init.js中创建子进程执行shell命令
const {promisify} = require('util') // util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足
const figlet = promisify(require('figlet')) //  util.promisify() 这个方法,方便快捷的把原来的异步回调方法改成返回 Promise 实例的方法

const clear = require('clear')
const chalk = require('chalk')
const log = content => console.log(chalk.green(content));
const {clone} = require('./download')
const open = require('open')

const spawn = async (...args) => {
  const {spawn} = require('child_process')
  return new Promise(resolve => {
    const proc = spawn(...args) // 在node.js中执行shell一般用spawn,实现从主进程的输出流连通到子进程的输出流
    proc.stdout.pipe(process.stdout) // 子进程正常流搭到主进程的正常流
    proc.stderr.pipe(process.stderr) // 子进程错误流插到主进程的错误流
    proc.on('close', () => {
      resolve()
    })
  })
}

module.exports = async name => {
  // 打印欢迎界面
  clear()
  const data = await figlet('KKB Welcom') // figlet是把文字变成大字
  log(data);

  // clone
  log(`创建项目: ${name}`);
  // await clone('github:su37josephxia/vue-sample', name)

  // 自动安装依赖
  log('安装依赖')
  console.log(spawn);
  await spawn('npm',['install'],{cwd: `./${name}`})
  log(`安装完成:To get Start: cd ${name} \n npm run server`)
  
  // 自动打开浏览器
  open(`http://localhost:8080`)
  // 自动启动项目
  await spawn('npm',['run', 'dev'],{cwd: `./${name}`})
}

进阶4:通过命令自动生成路由及菜单

(1)新建/lib/refresh.js文件
const fs = require('fs')
const hbs = require('handlebars')
const chalk = require('chalk')

module.exports = async () => {
  // 获取列表
  const list = fs.readdirSync('./src/views')
    .filter(v => v !== 'Home.vue')
    .map(v => ({
      name: v.replace('.vue', '').toLowerCase(),
      file: v
    }))

  // 生成路由文件
  compile({list}, './src/router.js', './template/router.js.hbs')

  // 生成菜单
  compile({list}, './src/App.vue', './template/App.vue.hbs')

  //meta:数据定义  filePath:目标文件 templatePath:模板文件
  function compile(meta, filePath, templatePath) {
    if (fs.existsSync(templatePath)) {
      const content = fs.readFileSync(templatePath).toString()
      const result = hbs.compile(content)(meta)
      fs.writeFileSync(filePath, result)
      console.log('创建成功');
    }
  }
}

(2)在auto-cli/bin/kkb.js命令文件中增加命令    
program
    .command('refresh') // 定义init命令
    .description('refresh routers')
    .action(require('../lib/refresh'))

项目(auto-cli/lib)最终文件代码:

(1)/bin/kkb.js
#!/usr/bin/env node
console.log('auto-router-cli....')

const program = require('commander') //命令行工具
program.version(require('../package.json').version) // 或直接写 '1.0.1'

program
    .command('init <name>') // 定义init命令
    .description('init project')
    // .action(name => { // 指定命令要做什么事,回调函数中实现命令功能
    //   console.log('init ' + name);
    // })
    .action(require('./init.js'))

program
    .command('refresh') // 定义init命令
    .description('refresh routers')
    .action(require('./refresh'))

    program.parse(process.argv)

(2)/lib/init.js
const {promisify} = require('util') // util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足
const figlet = promisify(require('figlet')) //  util.promisify() 这个方法,方便快捷的把原来的异步回调方法改成返回 Promise 实例的方法

const clear = require('clear')
const chalk = require('chalk')
const log = content => console.log(chalk.green(content));
const {clone} = require('./download')
const open = require('open')

const spawn = async (...args) => {
  const {spawn} = require('child_process')
  return new Promise(resolve => {
    const proc = spawn(...args)
    proc.stdout.pipe(process.stdout) // 子进程正常流搭到主进程的正常流
    proc.stderr.pipe(process.stderr) // 子进程错误流插到主进程的错误流
    proc.on('close', () => {
      resolve()
    })
  })
}

module.exports = async name => {
  // 打印欢迎界面
  clear()
  const data = await figlet('KKB Welcom') // figlet是把文字变成大字
  log(data);

  // clone
  log(`创建项目: ${name}`);
  await clone('github:su37josephxia/vue-sample', name)

  // 自动安装依赖
  log('安装依赖')
  console.log(spawn);
  await spawn('npm',['install'],{cwd: `./${name}`})
  log(`安装完成:To get Start: cd ${name} \n npm run server`)

  // 自动打开浏览器
  open(`http://localhost:8080`)
  // 自动启动项目
  await spawn('npm',['run', 'dev'],{cwd: `./${name}`})
}

(3)/lib/download.js
const {promisify} = require('util')

module.exports.clone = async function(repo, desc) {
  const download = promisify(require('download-git-repo')) // download-git-repo: Download and extract a git repository (GitHub, GitLab, Bitbucket)
  const ora = require('ora')
  const process = ora(`下载......${repo}`)
  process.start() // 进度条开始
  await download(repo, desc)
  //  download-git-repo导出的APIdownload方法,第一个参数仓库地址:repo的格式
  // GitHub - github:owner/name or simply owner/name
  // GitLab - gitlab:owner/name
  // Bitbucket - bitbucket:owner/name
  process.succeed()
}

(4)/lib/refresh.js
const fs = require('fs')
const hbs = require('handlebars')
const chalk = require('chalk')

module.exports = async () => {
  // 获取列表
  const list = fs.readdirSync('./src/views')
    .filter(v => v !== 'Home.vue')
    .map(v => ({
      name: v.replace('.vue', '').toLowerCase(),
      file: v
    }))

  // 生成路由文件
  compile({list}, './src/router.js', './template/router.js.hbs')

  // 生成菜单
  compile({list}, './src/App.vue', './template/App.vue.hbs')

  //meta:数据定义  filePath:目标文件 templatePath:模板文件
  function compile(meta, filePath, templatePath) {
    if (fs.existsSync(templatePath)) {
      const content = fs.readFileSync(templatePath).toString()
      const result = hbs.compile(content)(meta)
      fs.writeFileSync(filePath, result)
      console.log('创建成功');
    }
  }
}

JohnsonGH
32 声望1 粉丝

下一篇 »
Gitlab CI/CD