背景
脚手架是一个通用开发工具,之前自己写一下原生web工程时总是需要重复搭建开发环境、重复写几乎相同的配置文件。为了避免每次的重复工作,统一开发环境、规范,于是想到自己写一个脚手架用用,顺便记录一下。
目前个人习惯基于当前主流的webpack打包工具开发项目,所以此脚手架是基于webpack5开发的。
概览
本文我们先实现作为脚手架最基本的功能:输入命令 创建统一的模板项目
开发
依赖
开发一个的脚手架,你至少需要如下npm包:
- commander:命令行处理工具
- inquirer:命令行交互工具
- download-git-repo:git仓库下载工具
- ora:终端loading美化工具
- chalk:命令行输入/输出美化工具
初始化项目
mkdir web-cli
cd web-cli
npm init -y
在 package.json
配置文件中定义bin
字段
node.js 内置了对命令行操作的支持 bin
字段可以定义命令名和关联的执行文件。
项目中会使用ES6模块化开发,需要转换成最终执行命令的node.js能识别的common.js模块化,在script
定义Babel编译的命令
"bin": {
"web": "./bin/index.js"
}
在根目录下创建src/index.js
文件作为入口,并在行首加入一行 #!/usr/bin/env node
指定当前脚本由node.js进行解析
Babel配置
项目中会使用ES6模块化开发,需要配置Babel转换成最终执行命令的node.js能识别的common.js模块化,安装相关依赖:
npm install --save-dev @babel/core @babel/cli @babel/preset-env
在 package.json
配置文件中script
字段定义Babel编译的命令
"scripts": {
"build": "babel src -d dist"
}
添加Babel配置文件babel.config.json
{
"presets": ["@babel/preset-env"]
}
测试一下效果
除了将项目发包再global安装外,我们可以在项目根目录下执行npm link
命令把指定的执行文件链接到全局环境。我们在入口代码中写一个输出hello world
#!/usr/bin/env node
console.log('helo world!')
执行npm link
后,我们打开命令行终端输入:web
我们能看到输出hello world
模板项目
我们需要创建一个完成通用配置的模板项目并上传到GitHub的公共仓库,这一步就不多演示了。我创建了一个基于webpack5并完成htmlWebpackPlugin、css资源处理、JavaScript资源处理及基础优化等基础配置的项目模板:https://github.com/LeoJ340/we...
接下来,我们需要通过输入命令拉取仓库代码并动态配置一些个人信息。需要实现的逻辑是:
- 在命令行输入创建项目的命令以及项目名
- 输入项目或作者的基本信息
- 去GitHub拉取模板项目到自定义项目名的目录下
- 根据读取的项目信息修改
package.json
配置
安装相关依赖:
npm install commander download-git-repo [email protected]
commander
commander是一个用来注册命令以及获取命令行参数的第三方库,commander的注册命令基本用法如下:
import { program } from 'commander';
program.command('命令 [参数]', '命令描述', opts).action(回调函数)
// 解析用户执行时输入的参数
// process.argv 是 nodejs 提供的属性
program.parse(process.argv);
download-git-repo
download-git-repo是一个用于下载GitHub、Gitlab上的公共仓库的库。基本用法如下:
import download from 'download-git-repo';
download(repository, destination, options, callback)
- repository:远程仓库的地址
- destination:下载到本地的路径
- options:配置参数(若传入函数,则覆盖回调函数)
- callback:回调函数
inquirer
inquirer是一个提供了命令行的交互操作的库(新版的inquirer只支持ESM,即使用babel编译也会报错,所以这里需要使用老版本),用法也很简单(摘自官网):
import inquirer from 'inquirer';
inquirer
.prompt([
/* Pass your questions in here */
])
.then((answers) => {
// Use user feedback for... whatever!!
})
.catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
} else {
// Something else went wrong
}
});
接下来,我们修改一下入口代码:
#!/usr/bin/env node
import { program } from 'commander';
import inquirer from 'inquirer';
import download from 'download-git-repo';
program.version('1.0.0')
// 注册create命令,name作为参数 指项目名
program.command('create ').action(name => {
// 获取一些项目信息
inquirer.prompt([
{
name: 'author',
message: '你的名字是:'
},
{
name: 'version',
message: '版本号',
default: '1.0.0'
},
{
name: 'description',
message: '项目描述',
default: 'a web project template with Babel & ESLint'
}
]).then(res => {
// 拿到信息参数
const { author, version, description } = res
const beginTime = new Date().getTime()
download(`LeoJ340/webpack-template`, `./${name}`, err => {
const time = (new Date().getTime() - beginTime) / 1000
console.log(err || `create project finish in ${time}s`)
})
})
});
program.parse(process.argv)
到这里,我们完成了脚手架最基本的输入命令、下载仓库的功能。通过inquirer
获取的参数可以使用nodeJS的fs
文件库修改package.json
文件
优化
到目前为止,我们完成的脚手架最基本的功能,但是我们发现...命令行太丑了。于是决定优化一下,这里需要依赖两个库:chalk、ora
chalk
chalk是一个命令行美化工具,能够让你输出五彩斑斓的命令。
npm i [email protected]
import chalk from 'chalk';
console.log(chalk.green(`create project finish in 1s`))
ora
ora是一个实现命令行loading效果的库。使用方法也很简单:
npm i [email protected]
import ora from 'ora';
// 定义一个loading
const loading = ora('template downloading...');
// 启动loading
loading.start()
// loading 成功
loading.success()
// loading 停止
loading.stop()
基于上面上个第三方库再优化一下代码,就完成了最初版的脚手架开发
源码仓库
GitHub:https://github.com/LeoJ340/web-cli,欢迎star⭐⭐⭐
如果你觉得本文对你有帮助,还请帮忙点个赞❤,如果你有不同的见解,欢迎评论区讨论。