动态生成代码模板——编写基于 nodejs 的 cli 工具
目标
项目结构
.
├── README.md
├── bin
│ ├── config.js // 处理用户的输入
│ ├── createIndexTemplate.js
│ ├── createPackageTemplate.js
│ ├── index.js // 主文件
│ ├── questions // 用户输入
│ │ ├── index.js
│ │ ├── middleware.js
│ │ ├── packageName.js
│ │ └── port.js
│ └── template // 待生成的模板
│ ├── index.ejs
│ └── package.ejs
├── koaTemplate // 生成的模板
│ ├── index.js
│ └── package.json
├── package-lock.json
└── package.json
思路

大致思路:
用户终端输入 koa-cli,根据用户输入的内容生成配置,将配置作用于脚本,生成符合理想的内容
Script 关键步骤分为 4 步:
创建项目文件夹
文件名称——用户输入(input)
创建 index.js
index.js 的内容——已有的模板 ➕ 用户选择安装的中间件等服务(input)
创建 package.json
package 的内容——已有的模板 ➕ 用户选择安装的第三方包(input)
进入生成的项目,安装依赖(output)
过程
创建基本项目
- 新建项目文件夹 koa-cli
- 初始化项目:
npm init -y- 修改
"type": "module"方便使用 esm 语法
- 修改
- 新建入口文件:
bin/index.js
import fs from 'fs'
const indexTemplateString = '...'
const packageTemplateString = '...'
// 1. 创建项目文件夹
fs.mkdirSync('koaTemplate')
// 2. 创建 index.js
fs.writeFileSync('koaTemplate/index.js', indexTemplateString)
// 3. 创建 package.json
fs.writeFileSync('koaTemplate/package.json', packageTemplateString)
node index.js测试- 添加 npm test 命令方便测试
"scripts": {
"test": "rm -rf ./koaTemplate && node ./bin/index.js"
}
- koa 项目已经创建完成。进入到文件夹,安装依赖,需要用到 npm 包
execa
import fs from 'fs'
import execa from 'execa'
const indexTemplateString = '...'
const packageTemplateString = '...'
// 1. 创建项目文件夹
fs.mkdirSync('koaTemplate')
// 2. 创建 index.js
fs.writeFileSync('koaTemplate/index.js', indexTemplateString)
// 3. 创建 package.json
fs.writeFileSync('koaTemplate/package.json', packageTemplateString)
// 4. 安装依赖
execa('yarn', {
cwd: koaTemplate,
stdio: [2, 2, 2],
})
完善项目
至此,CLI 的基本内容已经完成。可以直接运行脚本生成项目。
但是有几个重要问题:
- 生成的项目名称是固定的
- 脚手架没有可选的安装选项
- 模板内容和用户输入的可选项有关联
- 首先不用考虑用户输入的部分,可以直接抽离成为
InputConfig, 大概长这样
const inputConfig = {
packageName: '',
port: 8000,
middleware: {
static: false,
views: false,
router: false,
body: false,
},
}
然后将 InputConfig,依次传给需要的部分
通过 InputConfig 中的内容对模板内容进行控制,模板需要用
ejstip: 通过将安装的可选项后面逗号前置,保证 package 的 json 格式无误
和用户交互获取用户输入内容,需要用
inquirer格式化最后的模板代码,需要用
prettier
运行测试
通过npm link 将此目录下的 bin 链接到全局
通过 npm root -g, 获取全局安装的命令,查看上一步是否成功
工具
exaca: 执行脚本命令
ejs: 模板工具
inquire: 获取用户输入内容
prettier: 格式化代码
chalk: 美化输出
F2: 更换全局变量名
Quick and Simple Text Selection: 更换边界符号
terminalizer: 命令行录制
Travis CI: 自动发布
gren: 自动生成发布日志 github-release-notes