将收获什么
- 掌握命令行交互方法
- 服务端框架
egg.js 的应用和 api 开发方法
egg.js 集成云 mongodb 实现数据存储
主要内容
- 脚手架项目创建功能架构设计
- 通过命令行交互获取项目基本信息
egg.js + 云 mongodb 的集成
- 开发前端项目模板
egg.js 获取项目模板 API 开发
- 项目模板下载功能开发
inquirer 源码解析,彻底搞懂命令行交互
创建功能架构设计
- 可拓展:能够快速复用到不同团队,适应不同团队之间的差异
- 低成本:在不改动脚手架源码的情况下新增模板,且新增模板的成本很低
- 高性能:控制存储空间,安装时充分利用
node 多进程提升安装性能
创建功能架构设计图
准备阶段

下载模板阶段

安装模板阶段

准备阶段开发
'use strict';
const fs = require('fs');
const Command = require('@hzw-cli-dev/command');
const log = require('@hzw-cli-dev/log');
const inquirer = require('inquirer');
const fse = require('fs-extra');
const semver = require('semver');
const TYPE_PROJECT = 'project';
const TYPE_COMPONENT = 'component';
class InitCommand extends Command {
init() {
this.projectName = this._argv[0] || 'project';
this.force = !!this._argv[1].force;
log.verbose('🚀🚀 ~ 是否强制安装', this.force);
log.verbose('🚀🚀 ~ 项目名称', this.projectName);
}
async exec() {
try {
const ret = await this.prepare();
if (ret) {
}
} catch (error) {
log.error(error.message);
}
}
async prepare() {
const localPath = process.cwd();
const isEmpty = this.isDirEmpty(localPath);
let isContinue = false;
if (!isEmpty) {
if (!this.force) {
const res = await inquirer.prompt([
{
type: 'confirm',
name: 'isContinue',
message: '当前文件夹内容不为空,是否在此继续创建项目?',
default: false,
},
]);
isContinue = res.isContinue;
if (!isContinue) {
return false;
}
}
if (isContinue || this.force) {
const { isDelete } = await inquirer.prompt([
{
type: 'confirm',
name: 'isDelete',
message: '是否清空当前目录下的文件?',
default: false,
},
]);
if (isDelete) {
fse.emptyDirSync(localPath);
}
}
}
return this.getInfo();
}
async getInfo() {
const info = {};
const { type } = await inquirer.prompt({
type: 'list',
message: '请选择初始化类型',
name: 'type',
default: TYPE_PROJECT,
choices: [
{
name: '项目',
value: TYPE_PROJECT,
},
{
name: '组件',
value: TYPE_COMPONENT,
},
],
});
log.verbose('type', type);
if (type === TYPE_COMPONENT) {
}
if (type === TYPE_PROJECT) {
const o = await inquirer.prompt([
{
type: 'input',
message: '请输入项目名称',
name: 'project',
validate: (a) => {
const reg =
/^[a-zA-Z]+([-][a-zA-Z0-9]|[_][a-zA-Z0-9]|[a-zA-Z0-9])*$/;
if (reg.test(a)) {
return true;
}
return '要求英文字母开头,数字或字母结尾,字符只允许使用 - 以及 _ ';
},
},
{
type: 'input',
message: '请输入项目版本号',
name: 'version',
default: '1.0.0',
validate: (a) => {
return !!semver.valid(a) || '请输入合法的版本号';
},
filter: (a) => {
if (!!semver.valid(a)) {
return semver.valid(a);
}
return a;
},
},
]);
console.log('🚀🚀 ~ InitCommand ~ o', o);
}
return info;
}
isDirEmpty(localPath) {
let fileList = fs.readdirSync(localPath);
fileList = fileList.filter(
(file) => !file.startsWith('.') && ['node_modules'].indexOf(file) < 0,
);
return !fileList || fileList.length === 0;
}
}
function init(argv) {
return new InitCommand(argv);
}
module.exports = init;
module.exports.InitCommand = InitCommand;