在日常开发中,我们会根据公司项目和实际经验沉淀出一些项目模板,来很好的在不同项目中重复使用和快速开发,如果每次都通过拷贝代码的形式到新项目的话,会变得比较麻烦,并且容易增大出错的概率。这时我们就可以搭建一套集成常用模板的前端脚手架,方便我们快速的进行初始化创建。
初始化项目
首先创建一个名为 any-starter-cli 的项目,当然名字可以随意更改,之后在该目录下执行 pnpm init 来初始化 package.json 文件。
pnpm init
安装依赖
初始化完项目之后,继续安装以下依赖,注意:请锁定ora、log-symbols、chalk的版本,因为最新版本只支持ESM
pnpm i chalk commander download-git-repo inquirer ora log-symbols
| 依赖 | 版本 | 作用 |
|---|---|---|
| chalk | 4.1.2 | 控制台输出内容样式 |
| commander | 9.3.0 | 命令行工具 |
| ownload-git-repo | 3.0.2 | 下载远程模板 |
| inquirer | 8.2.4 | 交互式命令行工具 |
| ora | 3.2.0 | 显示加载动画 |
| log-symbols | 4.0.0 | 显示出 √ 或 × 等的图标 |
| cli-table | 0.3.11 | 允许从 node.js 脚本在命令行上呈现 unicode 辅助表 |
编写代码
在开始编写代码之前,我们需要了解 commander 的用法
- usage(): 设置 usage 值
- command(): 定义一个命令名字
- description(): 描述
- option(): 定义参数,需要设置“关键字”和“描述”,关键字包括“简写”和“全写”两部分,以
,|空格做分隔。 - parse(): 解析命令行参数 argv
- action(): 注册一个 callback 函数
- version(): 终端输出版本号
接着根目录下创建 bin/starter 文件,并写入以下内容
#!/usr/bin/env node
const program = require('commander')
program.usage('<command>')
program.version(require('../package').version)
program
.command('list')
.description('List the templateList')
.action(() => {
require('../commands/list')
})
program
.command('init')
.description('Init a project')
.action(() => {
require('../commands/init')
})
program.parse(process.argv)
接着,在 package.json 中添加以下命令
"bin": {
"starter": "bin/starter"
},
此时我们执行 npm link将命令挂载到全局,然后再输入 starter 就可以看到的效果了。
创建模板
为了能让脚手架后续可以下载到对应的模板,我们需在跟根目录下创建 tempalte.json, 并写入以下代码,当然,这些模板可以根据实际情况替换,这里只是为了演示。
{
"vue-element-plus-admin": "https://github.com:kailong321200875/vue-element-plus-admin#master",
"webpack-multi-page-cli": "https://github.com:kailong321200875/webpack-multi-page-cli#master"
}
编写指令
编写指令之前,我们需要了解 inquirer 的基本用法
- type:表示提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor
- name: 存储当前问题回答的变量
- message:问题的描述
- default:默认值
- choices:列表选项,在某些 type 下可用,并且包含一个分隔符(separator)
- validate:对用户的回答进行校验
- filter:对用户的回答进行过滤处理,返回处理后的值
- when:根据前面问题的回答,判断当前问题是否需要被回答
- prefix:修改 message 默认前缀
- suffix:修改 message 默认后缀
List the templateList
接下来我们编写列举所有项目模板的命令
在根目录下创建 commands/list.js 文件,并写入以下代码
const { showTable } = require(`${__dirname}/../utils/index`)
const templateList = require(`${__dirname}/../template`)
showTable(templateList)
在根目录下创建 utils/index.js 文件,并写入以下代码
const Table = require('cli-table')
const table = new Table({
head: ['name', 'url'],
style: {
head: ['green']
}
})
function showTable (tempList) {
const list = Object.keys(tempList)
if (list.length > 0) {
list.forEach((key) => {
table.push([key, tempList[key]])
if (table.length === list.length) {
console.log(table.toString())
process.exit()
}
})
} else {
console.log(table.toString())
process.exit()
}
}
exports.showTable = showTable
配置完之后重新运行 npm link, 然后执行 starter list 命令即可查看效果
Init a project
接着需要配置 init 指令,用于选择初始化的模板
在 commands 下创建 init.js 文件,并写入以下代码
const ora = require('ora')
const download = require('download-git-repo')
const templateList = require('../template.json')
const symbols = require('log-symbols')
const chalk = require('chalk')
const inquirer = require('inquirer')
inquirer
.prompt([
{
type: 'rawlist',
message:'请选择初始化项目模板',
name:'template',
choices: Object.keys(templateList)
}
])
.then(answers => {
const templateName = answers.template
const url = templateList[templateName]
console.log(chalk.green('\n Start generating... \n'))
// 出现加载图标
const spinner = ora("Downloading...")
spinner.start()
download(
`${url}`,
`./${templateName}`,
err => {
if (err) {
spinner.fail()
console.log(chalk.red(symbols.error), chalk.red(`Generation failed. ${err}`))
return
}
// 结束加载图标
spinner.succeed()
console.log(chalk.green(symbols.success), chalk.green('Generation completed!'))
console.log('\n To get started')
console.log(`\n cd ${templateName} \n`)
}
)
})
.catch(error => {
console.log(error)
process.exit()
})
到这里,我们就完成了一个快速启动不同模板的前端脚手架,后续就可以直接 npm publish 上传到 npm 上。
上传成功之后,全局安装 pnpm add any-starter-cli -g
之后执行 starter -h,出现以下提示就代表发布成功
最后,就可以使用 starter init 初始化想要的模板了
结语
当我们项目启动模板越来越多时,提供一个快速初始化的脚手架,更方便也更不容易出错。
文章中的源码地址:any-starter-cli