概述
脚手架本质上是一个工具,使用脚手架的目的就是摆脱构建工程时重复性的工作,尤其是当一个工程具有一定通用性时,工程脚手架的意义就更为突出。它可以让我们只需要一行命令,就可以初始化好一项工程。
思路
创建一个公开的仓库,引导用户输入命令初始化工程,从远程拉取代码。流程如下:
实现
1. 初始化工程
代码语言:javascript复制npm init -y
2. 添加依赖
需要用到的依赖有:
- chalk
- commander
- download-git-repo
- inquirer
- ora
- spinner
npm i chalk commander download-git-repo inquirer ora spinner -S
3. 实现脚手架
在根目录下创建文件index.js
,并修改package.json
文件内容:
{
...,
"bin": {
"lzugis-cli": "index.js"
}
}
文件index.js
的完整内容如下:
#! /usr/bin/env node
let fs = require('fs')
const program = require('commander'); // 命令行工具
const download = require('download-git-repo'); // 远程下载
const ora = require('ora'); // loading
const inquirer = require('inquirer'); // 命令行交互
const chalk = require('chalk'); // 输出样式化
const pk = require('./package.json');
// 版本信息
program.version(pk.version, '-v, --version') // 版本信息
.usage('<command> [options]'); // 使用信息
/**
* 删除文件夹下所有问价及将文件夹下所有文件清空
* @param {*} path
*/
function emptyDir(path) {
const files = fs.readdirSync(path);
files.forEach(file => {
const filePath = `${path}/${file}`;
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
emptyDir(filePath);
} else {
fs.unlinkSync(filePath);
}
});
}
/**
* 删除指定路径下的所有空文件夹
* @param {*} path
*/
function rmEmptyDir(path, level=0) {
const files = fs.readdirSync(path);
if (files.length > 0) {
let tempFile = 0;
files.forEach(file => {
tempFile ;
rmEmptyDir(`${path}/${file}`, 1);
});
if (tempFile === files.length && level !== 0) {
fs.rmdirSync(path);
}
}
else {
level !==0 && fs.rmdirSync(path);
}
}
/**
* 清空指定路径下的所有文件及文件夹
* @param {*} path
*/
function clearDir(path) {
const isExist = fs.existsSync(path)
if(isExist) {
console.log('')
const spinner = ora('删除目录');
spinner.start()
spinner.text = `目录${path}已存在,删除中`;
spinner.spinner = {
interval: 120, // Optional
frames: ['. ', '.. ', '...', '.. ']
}
emptyDir(path);
rmEmptyDir(path);
spinner.succeed()
spinner.color = 'green'
console.log(' ')
}
}
/**
* 下载模板
*/
function downloadTemplate(projectName) {
const branch = pk.template.branch
const gitUrl = `direct:${pk.template.url}#feature/${branch}`
const spinner = ora('初始化项目');
spinner.start()
spinner.text = `项目${projectName}初始化中`;
spinner.spinner = {
interval: 120, // Optional
frames: ['. ', '.. ', '...', '.. ']
}
download(gitUrl, projectName, { clone: true }, async function (err) {
if(err) {
console.log(' ')
spinner.fail('项目初始化失败,请联系【01416068】添加权限。')
// downloadTemplate(projectName)
} else {
spinner.succeed('项目初始化成功!请参考如下命令安装依赖后再运行:')
const scripts = `cd ./${projectName} && npm install`
console.log(' ' chalk.blue(`${scripts}`))
console.log(' ' chalk.blue('npm run dev'))
}
})
}
program.command('create')
.description('初始化项目')
.action(() => {
inquirer.prompt([
{
type: 'input',
message: '请输入项目名称:',
name: 'projectName',
default: pk.template.name // 默认值
}
]).then(res => {
console.log(' ')
console.log('即将创建工程' chalk.blue(res.projectName))
console.log(' ')
// 判断路径是否存在,存在则先删除
clearDir(`./${res.projectName}`)
// 下载模板代码
downloadTemplate(res.projectName)
})
});
program.parse(process.argv);
上述代码中将模板工程仓库的配置在package.json
中,添加的内容为:
{
...,
"template": {
"name": "lzugis-project-template",
"url": "https://gitee.com/lzugis15/lzugis-project-template.git",
"branch": "template"
}
}
4. 调试
通过命令npm link
连接脚本,调试脚手架,如下图所示:
5. 发布
- 先通过命令
npm unlink lzugis-cli
取消连接脚本;
2.修改package.json
文件
{
...,
"publishConfig": {
"registry": "https://www.npmjs.com/"
}
}
- 通过命令
npm login --registry https://www.npmjs.com
,根据提示输入用户名和密码,登录npm - 通过命令
npm publish
发布。
6. 测试
先全局安装脚手架npm i sfmap-cli -g
,再通过命令sfmap-cli create
创建工程。