
脚手架编写
🛎️脚手架
脚手架框架
bin
src
contant.js
create.js
main.js
package-lock.json
package.json
🛠️插件安装
devDependencies & dependencies
脚本名称 | 脚本作用 |
---|---|
commander | 读取版本,设定选项(option),开发命令行工具 |
consolidate | express中的模板引擎可以覆盖其他模板 |
download-git-repo | 可以通过git的方式下载模板到本地 |
ejs | 模板库,json生成html和consolidate配合使用 |
inquirer | 命令行交互 |
metalsmith | 批量处理模板 |
ora | 优化加载等待的交互 |
chalk | 美化终端 |
ncp | 判断文件是否存在 |
axios | http库发送请求 |
1 | npm i |
编写bin文件
编写www.js
bin文件下创建 www.js 文件
输入
1
2
3
require("../src/main.js")
- 回到 package.json 添加如下启动项
1 | "bin": { |
⭐编写src文件
🚀main.js
版本和命令行生成以及文件路径选择都在这里编写
1 | const {version} = require('../package.json'); |
编写文件创建和帮助指令
1 | const mapActions = { |
完成上一步操作后,我们需要逐步进行命令选择
需要使用 Reflect 中的 ownkeys进行每条命令的遍历
最后使用 forEach进行循环操作
1 | Reflect.ownKeys(mapActions).forEach((action) => { |
command :命令行(对应mapActions中的每一个动作)
alias :别称,也就是mapActions中的alias
description:同样对应mapActions中的description
因为这边是对mapActions进行循环遍历,所以每一个在mapActions中的属性都需要遍历到
- 最后一行的判断
help事件
1 | program.on("--help",() => { |
执行help的时候输出mapActions和命令行自带的option
版本显示
1 | program.version(version).parse(process.argv); |
main代码
1 | console.log("welcome xiu"); |
💡create.js
如果纯复刻,建议先去下面把 constant.js写了再回来
模板的选择,模板的复制,终端的选择和终端的样式都在这里实现
1 | const axios = require('axios') |
获取仓库信息
1 | // 获取仓库信息 |
抓取版本列表
1 | // 抓取版本(tag)列表 |
下载项目
1 | const downLoad = async(repo, tag) => { |
repo 就是仓库下的模板名称
tag 就是每个模板的版本号
编写加载项
再完成上面几步之前会有一个加载的过程,重复的加载我们可以封装来完成
1 | const waitFnLoading = (fn,message) => async(...args) => { |
这里有两个函数体变量
(fn,message) , async(…args)
前者用来接收执行的函数和发出的提示
后者用来对执行函数自带参数进行调用
- 接下来要做的就是导出下载模块
导出下载模块
交互选择
1 | let repos = await waitFnLoading(fetchRepoList,'fetch template...')() |
获取对应的版本号
1 | let tags = await waitFnLoading(fetchTagList,'fetch template tag...')(repo) |
交互选择 和 获取对应的版本号 本质上没有差别
都是通过 inquirer 交互页面查看每个版本进行选择
不同的地方是:
异步调用的 加载项不同:
let repos = await waitFnLoading(fetchRepoList,'fetch template...')<mark>()</mark> let tags = await waitFnLoading(fetchTagList,'fetch template tag...')<mark>(repo)</mark>
下载的项目首先是临时存放到本地,之后再对存放的内容的文件名称和当前路径下的文件匹配有无重复最后实现模板复制到当前路径下。
在一些简单模板下没有ask.js 但是在绝大部分的复杂模板下有 ask.js文件,这就需要我们对ask.js文件进行访问和重编写
这里需要使用到 metalSmith 对模板的内容进行批量处理
1 | // 下载项目 返回临时的存放目录 |
- done() 相当于 node.js的中间件 next()
1 | const result = await waitFnLoading(downLoad,'downloading...')(repo,tag) |
- 这一行代码获取到的result 就是对应模板和版本号之后的结果
1 | if(!fs.existsSync(path.join(result,'ask.js'))) { |
这里的 if..else.. 是对文件中是否存在 ask.js 进行判断
有就是复杂模板 需要重编写
1 | metalSmith(__dirname) |
- 这一处代码就是对模板下的所有文件匹配找到ask.js然后遍历执行里面所有的问题最后删除 delete files[“ask.js”]
1 | .use((files,metal,done)=>{ |
使用 metalSmith下的use 对刚刚遍历执行的问题中找到以‘<%’开头的选项就是要用户选择或是填写的
这里说明一下,前面删除的 ask.js 为什么这里还可以访问?
原因在于同样都是中间件,中间件之间是可以互相访问变量内容的,所以删除的ask.js在use里同样算是变量未删除。
成功退出
没什么好说的,直接复制改改就好了
1 | console.log(` |
create代码
1 | const axios = require('axios') |
💡constant.js
在create中用到的地址下载,你会发现无法复刻到本地原因在于 电脑系统版本不同,临时文件存放路径不同
所以这里可以单独对版本进行判断
1 | const downloadDirectory = `${process.env[process.platform === 'darwin' ? 'Home' : 'USERPROFILE']}/.template` |
- 如果是 ‘darwin’ 那就是 mac 如果不是 其他的都是Windows
🎈完结
祝福你也可以完成自己的脚手架
- 标题: 脚手架编写
- 作者: Charliexiu
- 创建于: 2023-04-08 22:13:27
- 更新于: 2023-04-19 00:08:57
- 链接: https://ccharlie-xiu.github.io/2023/04/08/脚手架编写/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。