来源:Node.js

脚手架

脚手架是一个工具,用于快速生成项目的基础结构和代码文件,以及提供一些常用的命令和功能

一个脚手架可以做到这些:

  • 项目结构:定义项目的目录结构,包括源代码、配置文件、静态资源等
  • 文件模板:提供一些预定义的文件模板,如HTML模板、样式表、配置文件等,以加快开发者创建新文件的速度
  • 命令行接口:通常提供一个命令行接口,通过输入命令和参数,开发者可以执行各种任务,如创建新项目、生成代码文件、运行测试等
  • 依赖管理:帮助开发者管理项目的依赖项,自动安装和配置所需的库和工具
  • 代码生成:生成常见的代码结构,如组件、模块、路由等,以提高开发效率
  • 配置管理:提供一些默认的配置选项,并允许开发者根据需要进行自定义配置

编写脚手架

工具

编写一个脚手架需要一些库:

Commander

Commander是一个用于构建命令行工具的npm库,它提供了一种简单而直观的方式来创建命令行接口,并处理命令行参数和选项

Commander可以轻松定义命令、子命令、选项和帮助信息,还可以处理命令行的交互,使用户能够与命令行工具进行交互

Inquirer

Inquirer是一个强大的命令行交互工具,用于与用户进行交互和收集信息

它提供了各种丰富的交互式提示(如输入框、选择列表、确认框等),可以构建灵活的命令行界面

使用Inquirer,可以向用户提出问题,获取用户的输入,并根据用户的回答采取相应的操作

Ora

Ora是一个用于在命令行界面显示加载动画的npm库,它可以在执行耗时的任务时提供一个友好的加载状态提示

Ora提供了一系列自定义的加载动画,如旋转器、进度条等,可以根据需要选择合适的加载动画效果,并在任务执行期间显示对应的加载状态

download-git-repo

Download-git-repo是一个用于下载Git仓库的npm库,它提供了一个简单的接口,可以方便地从远程Git仓库中下载项目代码

可以指定要下载的仓库和目标目录,并可选择指定分支或标签,支持从各种Git托管平台(如GitHub、GitLab、Bitbucket等)下载代码

准备

  1. 在package.json中添加入口文件

    1
    2
    3
    "bin": {
    "test-cli": "src/index.js"
    },
  2. 在命令行运行npm link,创建挂载到全局的软连接,这样就能全局执行test-cli命令

  3. 测试效果,当在命令行输入test-cli后,确实能输出

    1
    2
    3
    4
    #! /usr/bin/env node
    // 特殊注释,告诉操作系统,执行自定义命令时,用node去执行这个文件

    console.log('test')

编写

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#! /usr/bin/env node
// 特殊注释,告诉操作系统,执行自定义命令时,用node去执行这个文件

// 可以解析命令的参数
import { program } from 'commander'
import fs from 'node:fs'
import inquirer from 'inquirer'
import { downloadTemp, pathExists } from './util.js'

const pkg = fs.readFileSync('./package.json')
const json = JSON.parse(pkg)

// 创建版本号 版本参数 -V
program.version(json.version)

// 创建命令 create
program
.command('create <projectName>') // 命令名 <参数名>
.alias('c') // 命令别名为c
.description('创建项目') // 命令描述
.action((projectName) => { // 输入命令后执行的操作
inquirer.prompt([{
type: 'input', // 输入方式 input输入 confirm确认 list选择 等等
name: 'projectName', // 返回值的key
message: '请输入项目名称', // 描述
default: projectName // 默认值
}, {
type: 'confirm',
name: 'isTs',
message: '是否使用TypeScript模板',
}]).then((answers) => {
// console.log(answers) // -> { projectName: 'yajue', isTs: true }
if(pathExists(answers.projectName)) {
console.log('项目已存在')
return
}
if(answers.isTs) {
downloadTemp('ts', answers.projectName)
} else {
downloadTemp('js', answers.projectName)
}
})
})

// 获取参数
program.parse(process.argv)

util.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import fs from 'node:fs'
import download from 'download-git-repo'
import ora from 'ora'
import { resolve } from 'node:path'

const spinner = ora('正在下载...')

// 检查路径是否存在
export const pathExists = (path) => {
if (fs.existsSync(path)) {
return true
}
return false
}

// 根据不同的分支拉取不同的代码
export const downloadTemp = (branch, name) => {
return new Promise((resolve, reject) => {
// 执行下载动画
spinner.start()
// 下载模板
download(`direct:https://gitee.com/chinafaker/vue-template.git#${branch}`, name, { clone: true }, (err) => {
if (err) reject(err)
resolve()
spinner.stop('下载完成!')
})
})
}