likes
comments
collection
share

如何创建自己的cli脚手架

作者站长头像
站长
· 阅读数 20

现代前端开发中已经离不开各种脚手架的使用了,例如vue-cli和create-react-app等脚手架,而我们在日常开发中都会在这些脚手架的基础上做一些升级改造,例如集成一些常用的工具、网络请求封装、状态管理、特定布局等等,然后在后续的新项目中复用这些基础架构。为了方便管理和使用,我们可以将其抽离出来形成一个项目模版,通过类似vue-cli脚手架的方式来创建一个新项目,接下来本文就介绍一下如何动手创建一个自己的脚手架工具。

一、创建项目

新建一个项目文件夹,这里我将其命名为easy-cli,然后在该目录下执行:npm init -y生成package.json文件。

为了能够使用全局命令,我们需要在package.json里增加bin字段。

{
  "name": "easy-cli",
  "version": "1.0.0",
  // ...
  "bin": {
    "easy-cli": "./src/index.js"
  }
}

增加bin字段后我们就可以像下面这样全局使用命令:

easy-cli xxx

现在我们还无法执行命令,因为我们还没创建bin字段所指向的文件,接下来我们创建src/index.js

#! /usr/bin/env node

console.log('hello')

第一行代码#! /usr/bin/env node是必须的,它用来告诉系统使用node环境来执行该文件。

然后执行命令:npm link将其链接到全局变量,接下来我们就可以使用easy-cli命令了。

如何创建自己的cli脚手架

可以看到js文件被执行成功了。

二、定义版本

首先需要安装commander库,commander可以帮助我们处理命令行。

npm i commander --save

commander内部做了封装,使用命令--version查看版本时会输出我们在version方法里定义的值。

#! /usr/bin/env node

const program = require('commander')
const pkg = require('../package.json')

program.version(`v${pkg.version}`) // 定义当前版本

program.parse(process.argv) // 解析用户执行命令传入参数

如何创建自己的cli脚手架

三、命令行交互

我们希望在使用脚手架时通过如下步骤来创建一个新项目项目:

  • 首先执行easy-cli create命令。
  • 用户输入项目名称。
  • 用户选择模板。
  • 将用户选择的模板copy到本地。

在最后一步这里,一种选择是将项目模板放在脚手架里,然后将其对应的目录复制到本地。另一种选择是将项目模板放在git仓库里,然后在用户选择后将其下载到本地。这里我们选择第二种方案,这样当项目模板有改动时不需要频繁的去脚手架里改动。

1、获取项目名称

这里我们需要先安装inquirer,由于inquirer9.0以上版本无法使用require,所以安装时我们选择安装8版本的inquirer

npm i inquirer@8 --save
#! /usr/bin/env node

const program = require('commander')
const inquirer = require('inquirer')
const pkg = require('../package.json')

program.version(`v${pkg.version}`) // 定义当前版本

program
  .command('create')
  .description('创建模版')
  .action(async () => {
    const { projectName } = await inquirer.prompt({
      type: 'input',
      name: 'projectName',
      message: '请输入项目名称:'
    })
    console.log(projectName)
  })
 
program.parse(process.argv) // 解析用户执行命令传入参数

项目名称我们需要用户手动输入,所以prompt里的type的值设置为input,除此之外type值还有list(列表选择)confirm(单选确认)等,name是设置结果返回值对应的key名称,设置为projectName则返回结果里通过projectName获取。

如何创建自己的cli脚手架

2、选择模板

const program = require('commander')
const inquirer = require('inquirer')
const pkg = require('../package.json')

program
  .command('create')
  .description('创建模版')
  .action(async () => {
    const { projectName, template } = await inquirer.prompt([
      {
        type: 'input',
        name: 'projectName',
        message: '请输入项目名称:'
      },
      {
        type: 'list',
        name: 'template',
        message: '请选择模版:',
        choices: [
          {
            name: 'vue-admin',
            value: 'https://github.com:PanJiaChen/vue-element-admin'
          },
          {
            name: 'react-admin',
            value: 'https://github.com:marmelab/react-admin'
          }
        ]
      }
    ])
    console.log('projectName===', projectName)
    console.log('template===', template)
  })
 

prompt也支持传入数组的形式,这里我们可以将输入项目和选择模板的操作依次传入,choices接收的数组对象包含一个name和value,name用于显示,选择后会将对应的value值返回。

如何创建自己的cli脚手架

如何创建自己的cli脚手架

3、下载模版到本地

安装download-git-repo:

npm i download-git-repo --save
const program = require('commander')
const inquirer = require('inquirer')
const pkg = require('../package.json')
const downloadGitRepo = require('download-git-repo')
const path = require("path")

program
  .command('create')
  .description('创建模版')
  .action(async () => {
    const { projectName, template } = await inquirer.prompt([
      {
        type: 'input',
        name: 'projectName',
        message: '请输入项目名称:'
      },
      {
        type: 'list',
        name: 'template',
        message: '请选择模板:',
        choices: [
          {
            name: 'vue-admin',
            value: 'https://github.com:PanJiaChen/vue-element-admin'
          },
          {
            name: 'react-admin',
            value: 'https://github.com:marmelab/react-admin'
          }
        ]
      }
    ])
    console.log('projectName===', projectName)
    console.log('template===', template)
    
    // 获取目标文件夹
    const dest = path.join(process.cwd(), projectName)
    downloadGitRepo(template, dest, (err) => {
      if (err) {
        console.log('下载模板失败' + err.message)
        return
      }
      console.log('下载模板成功')
    })
  })

通过process.cwd将项目模板下载到命令行当前目录下。

如何创建自己的cli脚手架

运行命令后可以看到项目模板已经成功下载下来了,一个自制的脚手架已经基本完成了。接下来我们做一些优化。

4、优化:判断项目是否已存在

将项目模版下载到本地前,我们可以做一下优化判断,如果用户输入的项目名称在本地目录中已经存在,则弹出选择让用户确认是否删除覆盖。

接下来我们安装第三方包fs-extra方便进行文件操作:

npm i fs-extra --save
const program = require('commander')
const inquirer = require('inquirer')
const pkg = require('../package.json')
const downloadGitRepo = require('download-git-repo')
const path = require("path")
const fs = require('fs-extra')

program
  .command('create')
  .description('创建模版')
  .action(async () => {
    const { projectName, template } = await inquirer.prompt([
      {
        type: 'input',
        name: 'projectName',
        message: '请输入项目名称:'
      },
      {
        type: 'list',
        name: 'template',
        message: '请选择模板:',
        choices: [
          {
            name: 'vue-admin',
            value: 'https://github.com:PanJiaChen/vue-element-admin'
          },
          {
            name: 'react-admin',
            value: 'https://github.com:marmelab/react-admin'
          }
        ]
      }
    ])
    
    // 获取目标文件夹
    const dest = path.join(process.cwd(), projectName)
    if (fs.existsSync(dest)) {
      const { isExist } = await inquirer.prompt({
        type: 'confirm',
        name: 'isExist',
        message: '您输入的项目名称已存在,是否覆盖?',
      })
      // 如果覆盖就删除文件夹,否则退出
      isExist ? fs.removeSync(dest) : process.exit(1)
    }
    downloadGitRepo(template, dest, (err) => {
      if (err) {
        console.log('下载模板失败' + err.message)
        return
      }
      console.log('下载模板成功')
    })
  })

如何创建自己的cli脚手架

5、优化:增加loading

安装ora

npm i ora@5 --save
const ora = require('ora')

const loading = ora('正在下载中...')
loading.start()
downloadGitRepo(template, dest, (err) => {
  if (err) {
    loading.fail('创建模版失败' + err.message)
    return
  }
  loading.succeed('创建模版成功')
})

如何创建自己的cli脚手架

6、优化:修改package.json

我们下载下来的项目模板里,package.json里的nameversion记录的都是项目模板里的信息。

如何创建自己的cli脚手架

通常我们需要把name改成我们新创建的的项目名称,version从1.0.0开始,所以我们可以简单的借助node的文件操作能力进行修改。

downloadGitRepo(template, dest, (err) => {
  if (err) {
    loading.fail('创建模版失败' + err.message)
    return
  }
  loading.succeed('创建模版成功')
  
  // 修改package.json
  const pkgPath = path.join(process.cwd(), projectName, 'package.json')
  const pkgContent = fs.readFileSync(paths, 'utf-8')
  const pkgJson = JSON.parse(pkgContent)
  
  pkgJson.name = projectName
  pkgJson.version = '1.0.0'
  
  fs.writeFileSync(paths, JSON.stringify(pkgJson, null, 2))
})

如何创建自己的cli脚手架

四、发布npm

上面的工作完成后就可以选择发布到npm了,发布npm的步骤比较简单,这里就不多赘述了。

注册一个npm账号,然后npm loginnpm publish

五、感谢

本次分享到这里就结束了,感谢您的阅读,如果本文对你有什么帮助的话,别忘了动动手指点个赞❤❤❤!

转载自:https://juejin.cn/post/7275977439657476148
评论
请登录