仓库地址
toscode.gitee.com/rooney10/co…
背景
工作中开发一个新项目时,如果公司开发流程较为规范的话,会先进行技术选型,用vue还是react,然后选择构建工具、UI框架、状态管理工具、路由、代码规范、提交规范等等,确定好之后开始初始化项目,各种install,各种config配置。实际情况往往是从github clone一个满足使用的项目进行开发,或者copy一个之前的项目,删删改改后在之前的基础上直接进行业务开发了。如果能够拥有我们自己的脚手架,那么开发一个新项目时,直接通过简单的初始化命令,即可完成项目的搭建,让我们把更多的精力放在业务开发上。
目标
- 运行创建命令
- 询问用户问题
- 支持选择模板创建
- 支持自定义创建
- 根据用户的选择生成项目
相关工具库
-
commander用来构建node的命令行工具,使得能够使用自定义指令运行node脚本
-
inquirer通过询问问题,让用户与命令行进行交互
-
fs-extra系统fs模块的扩展
-
chalk控制台输出内容添加样式
-
figlet控制台打印logo
-
ora控制台loading样式
-
download-git-repo下载远程模板,不支持promise,使用util模块中的promisify方法对其进行promise化
实现
创建项目
1.新建项目目录kunkun-cli
mkdir kunkun-cli
cd kunkun-cli
npm init # 生成package.json文件
2.新建程序入口文件cli.js
touch cli.js
在package.json文件中指定入口文件为cli.js
{
"name": "trump-cli",
"version": "1.0.0",
"description": "",
"main": "cli.js",
"bin": { // 指定入口文件
"ikun": "cli.js"
},
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC"
}
编辑cli.js,首行添加#! /usr/bin/env node指定node运行环境
#! /usr/bin/env node
console.log('kunkun-cli start');
3.npm link链接到全局
库包在开发或迭代后,不适合发布到线上进行调试,npm link可以帮助我们模拟包安装后的状态,它会在系统中做一个快捷方式映射,让本地的包就好像install过一样,可以直接使用
在命令行输入ikun执行一下,就可以看到打印的kunkun-cli start了
创建脚手架启动命令
实现思路:
- 参照vue-cli常用的命令有create、config等
- 如果创建目录已存在,提示是否需要覆盖
- 借助commander库实现
安装依赖
npm i commander --save
创建命令
- 打开cli.js进行编辑
#! /usr/bin/env node
const program = require('commander')
program
.command('create <app-name>')
.description('create a new project')
.option('-f, --force', 'overwrite target directory if it exist')
.action((name, options) => {
console.log('name:', name, 'options:', options);
})
program
// 配置版本号信息
.version(`v${require('./package.json').version}`)
.usage('<command> [option]')
// 解析用户执行命令传入参数
program.parse(process.argv);
- 命令行输入ikun,检查命令是否创建成功
- 可以看到Commands下面已经有create [options] ,然后执行这个命令
- 成功拿到命令行输入信息
执行命令
- 创建lib文件夹并在文件夹下创建create.js
module.exports = async function (name, options) {
// 验证是否正常取到值
console.log('>>> create.js', name, options)
}
- 在cli.js中使用create.js
// 配置create命令
program
.command('create <app-name>')
.description('创建新项目')
.option('-f, --force', '强制创建,如果目录已存在则覆盖')
.action((name, options) => {
// 在create.js中执行创建任务
require('./lib/create.js')(name, options)
})
- 执行ikun create my-project,此时在create.js正常打印了信息
- 在创建目录时,需要思考一个问题:目录是否已经存在
- 如果存在
- 当{force: true}时,直接移除原来的目录,直接创建
- 当{force: false}时,询问用户是否需要覆盖
- 如果不存在,直接创建
- 使用fs的扩展工具fs-extra,它是对fs模块的扩展,支持promise
npm install fs-extra --save
- 完善create.js内部实现逻辑
const path = require('path')
const fs = require('fs-extra')
module.exports = async function (name, options) {
// 执行创建命令
// 当前命令行选择的目录
const cwd = process.cwd();
// 需要创建的目录地址
const targetAir = path.join(cwd, name)
// 目录是否已经存在?
if (fs.existsSync(targetAir)) {
// 是否为强制创建?
if (options.force) {
await fs.remove(targetAir)
} else {
// 询问用户是否确定要覆盖
}
}
}
询问用户问题获取创建所需信息
询问是否覆盖已存在的目录
使用inquirer询问用户,如果覆盖的话就将已存在目录移除
// 询问用户是否确定要覆盖
let { action } = await inquirer.prompt([
{
name: 'action',
type: 'list',
message: '目标目录已经存在,请选择操作:',
choices: [
{
name: '覆盖',
value: 'overwrite'
},
{
name: '返回',
value: false
}
]
}
])
if(!action) {
return
} else if(action === 'overwrite') {
// 移除已存在的目录
console.log('移除中...');
await fs.remove(targetAir)
}
如何获取模板信息
我将模板上传到了远程仓库,github提供了接口去获取用户的项目信息:api.github.com/repos/用户名/仓…,通过axios发送请求获取信息
用户选择模板
通过问题交互获取到用户想要创建的模板name为下载模板做准备
下载远程模板
安装依赖与promise化
下载远程模板需要使用download-git-repo工具包,它是不支持 promise的,所以我们这里需要使用 使用 util 模块中的promisify 方法对其进行 promise 化
const util = require('util')
const downloadGitRepo = require('download-git-repo') // 不支持 Promise
class Generator {
constructor (name, targetDir){
...
// 对 download-git-repo 进行 promise 化改造
this.downloadGitRepo = util.promisify(downloadGitRepo);
}
...
}
核心下载功能
const util = require('util')
const downloadGitRepo = require('download-git-repo') // 不支持 Promise
class Generator {
constructor (name, targetDir){
...
// 对 download-git-repo 进行 promise 化改造
this.downloadGitRepo = util.promisify(downloadGitRepo);
}
...
// 下载远程模板
async download() {
// 拼接下载地址
const requestUrl = `kunkun-cli-template/${用户选择模板name}`
// 调用下载方法
this.downloadGitRepo(requestUrl, path.resolve(process.cwd(), this.targetDir)),
}
...
}
发布项目
- 注册npm账号
- 执行npm adduser进行登录,报错需切换至npm镜像源registry.npmjs.com
- 执行npm publish进行发布,报错403可能是包名重复导致
发布成功后在npm官网就能看到已发布的npm包了,全局安装进行验证
自定义创建思路
思路
- 获取到用户选择的配置
- 开始创建
- 根据用户选项生成生成package.json文件
- 初始化git
- 安装依赖
- 生成代码