什么是脚手架
- 全局的命令行工具
- 有交互能力
- 项目模板代码的下载能力
如何实现一个脚手架?
- 创建一个本地的全局命令行
- 接收命令行传入的参数并处理
- 命令行交互:
问问题,用户答,接收用户输入的答案,处理不同的答案 - 下载远程代码模板
- 项目初始化完成的提示消息
1. 创建一个本地的全局命令行
- 创建
sample-scaffolding
(自定义)目录, 创建 bin 目录,然后创建一个 cli.js 文件 - 在 sample-scaffolding 项目路径,运行 npm init 初始化项目,得到 package.json
- bin 目录:项目的命令行执行的脚本文件,根据文件创建了一个mycli命令行
- 在当期项目路径,执行npm link 命令行,把脚手架连接到全局(link作用:把当前项目挂载到全局npm执行的系统变量里,创建一个全局的本地命令行)
脚手架基础应用搭建
Node CLI 应用入口文件必须要有这样的文件头,指示 node 运行cli.js
#!/usr/bin/env node
如果是 Linux 或 macOS 系统下还需要修改此文件的读写权限为 755 具体就是通过 chmod 755 cli.js 实现修改
通过 yarn link
命令行,把这个模块 link 到全局,这时我们就可以在命令行中,使用sample-scaffolding
命令行执行,看到终端 console.log 正常执行,就意味着这个 cli 的基础应用就已经可以了。
使用cli脚手架创建基本业务
脚手架的工作过程:
- 通过命令行交互询问用户问题
- 根据用户回答的结果动态生成文件
通过命令行交互询问用户问题
在node中,发起命令行交互询问,我们使用 inquirer 这个模块,执行命令行yarn add inquirer
安装。有了这个模块,我们就可以在代码中载入它
inquirer 具体使用如下图所示,配置完成后运行文件,可见,能正常打印我们输入的项目名称“Hello”。
根据用户回答的结果动态生成文件
在项目根目录下,新建一个 templates 的目录存放我们的文件模板,在templates 目录里新建一个index.html作为示例来介绍脚手架工作过程的一个模板文件
在模板中,可以通过<%= name %>
的方式去输出我们cli.js 配置询问环节得到的答案,如name的值
我们还可以根据需要添加其他的模板文件...
有了模板文件之后,回到 cli.js 文件,可以根据用户回答的结果生成文件,生成之前,我们先把模板的目录和生成的文件目录确定下来:
- 通过 path 拿到模板文件目录
const path = require('path')
// 模板目录
const tmplDir = path.join(__dirname, 'templates')
- 而输出的目标目录,一般就是我们命令行在哪个目录下执行,就是哪个目录的路径,也就是我们的cwd目录,在node中,我们可以借助于
process.cwd
方法,得到这样一个目录的路径
// 目标目录
const destDir = process.cwd()
明确了模板目录和目标目录之后,我们就可以通过 fs 模块,去读取模板目录下,有哪些模板文件,将这些文件全部转换到目标目录,fs.readdir 会自动扫描 模板目录下所有文件 整体配置流程如下:
#!/usr/bin/env node
// console.log('Lily\'s cli working');
const fs = require('fs')
const path = require('path')
const inquirer = require('inquirer')
const ejs = require('ejs') // 模板引擎
// prompt 发起询问,接收一个数组的参数
inquirer.prompt([
{
type: 'input', // 指定问题的输入方式
name: 'name', // 指定问题返回值对应的键
message: 'Project name?' // 指定屏幕上给用户的提示
}
]).then(answers => { // then方法里可以拿到这个问题接收到的用户的答案
// console.log(answers);
// 模板目录
const tmplDir = path.join(__dirname, 'templates')
// 目标目录
const destDir = process.cwd()
// 将模板下的文件全部转换到目标目录,在readdir回调函数中,可以通过files拿到所有的文件列表
fs.readdir(tmplDir, (err, files) => {
// 读取过程中发生问题,可以把错误信息抛出
if (err) throw err
// 遍历每个文件
files.forEach(file => {
console.log(file); // 打印出来可以得知模板文件的路径是相对templates下的相对路径
// 通过 ejs 模板引擎中 renderFile 方法渲染这个路径对应的文件 yarn add ejs 安装后需要引入
// 参数一:文件的绝对路径, 参数二: 模板引擎工作中的数据上下文, 参数三:是一个渲染后的回调函数(成功或失败)
ejs.renderFile(path.join(tmplDir, file), answers, (err, result) => {
if (err) throw err
console.log(result);
// 通过文件写入的方式把结果写入到目标目录
// 参数一:是目标目录的拼接, 参数二:输出的结果
fs.writeFileSync(path.join(destDir, file), result)
})
})
})
})
配置完成后,我们可以到一个新的目录,运行cmd ,执行命令行sample-scaffolding
尝试使用这个脚手架是否搭建成功,如下图可见,已经把我们的模板文件和输入的信息,输出到对应的目标目录,脚手架生效了!
处理命令参数
(以下内容脚手架名称修改为mycli)
安装 commander:commander 专门用来接收并处理命令参数的工具
npm install commander
#!/usr/bin/env node
const { program } = require('commader')
program.parse(process.argv)
设置脚手架帮助信息 program.option()
获取当前脚手架帮助信息 mycli --help
自定义脚手架指令 program.command('自定义指令名称')
<project>
: 必填参数
[others...]
: 选填
alias
: 别名
description
: 描述信息
action
: 回调函数,要操作的事
然后就可以使用自定义的 create
指令
你们的点赞,是对我的鼓励!欢迎评论区给我留言