开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情
前言
上一篇文章完成了初始化命令和帮助信息等选项的创建,初始化命令的实现我们也写了好多,今天这一篇文章,我们讲继续完善init
函数
当前痛点
github
在国内访问非常不稳定,github api
请求每次都是超时- 请求模板和创建目录的时候都比较耗时,这时就需要在命令行显示
loading
效果,告诉用户再进行操作 - spwan命令在mac很好使用,但是在windows上有兼容性问题存在
痛点解决方案
- 使用
gitee
仓库代替github
仓库, 使请求稳定 ora
命令行loading
效果- 使用
cross-spawn
解决spwan的操作系统兼容性问题
新建请求工具模块
请求gitee
中的所有模板仓库,供用户选择想要的模板
创建请求库
lerna create @wson-koa2-cli/request utils
utils/request/lib/index.js
'use strict';
const axios = require('axios');
const giteeRepo = 'https://gitee.com/api/v5/users/Yjust4U/repos';
axios.interceptions.response.use(res => {
return res.data;
})
async function getTemplateList() {
// 获取所有模板
const repos = axios.get(giteeRepo);
// 筛选name属性中包含template的仓库
const templates = repos.filter((repo) => repo.name.includes('template'));
return templates;
}
module.exports = {
getTemplateList
};
新建generator类来处理创建逻辑
commands/init/lib/generator.js
const { getTemplateList } = require("@wson-koa2-cli/request");
const inquirer = require("inquirer");
class Generator{
constructor(projectName, targetDir) {
// 项目名称
this.projectName = projectName;
// 项目目录
this.targetDir = targetDir;
}
// 获取用户选择的模板
// 3)return 用户选择的名称
async getRepo() {
// 1)从远程拉取模板数据
const templateList = await getTemplateList();
if (!templateList.length) return;
// 2)用户选择自己要下载的模板名称
const { template } = await inquirer.prompt([
{
type: 'list',
name: 'template',
message: "请选择模板来初始化项目",
choices: templateList
}
])
return template;
}
// 核心创建逻辑
async create() {
// 1)获取模板名称
const repo = await this.getRepo()
console.log('用户选择了,repo=' + repo)
}
}
module.exports = Generator;
其他代码不变
下载远程模板
创建utils
库,用来存放工具函数
lerna create @wson-koa2-cli/utils utils
utils/utils/lib/index.js
封装spawn异步请求
'use strict';
const spawn = require('cross-spawn'); // 用来解决操作系统兼容性问题
// 异步执行子进程命令
function execAsync(commands, args, options = {}) {
return new Promise((resolve, reject) => {
const p = spawn(commands, args, options);
p.on('error', e => {
reject(e)
})
p.on('exit', c => {
resolve(c)
})
})
}
module.exports = {
execAsync
}
继续完善generator类
commands/init/lib/generator.js
const { getTemplateList } = require("@wson-koa2-cli/request");
const { execAsync } = require("@wson-koa2-cli/utils");
const inquirer = require("inquirer");
const path = require('path');
const fs = require('fs-extra');
class Generator{
constructor(projectName, targetDir) {
// 项目名称
this.projectName = projectName;
// 项目目录
this.targetDir = targetDir;
}
// return 用户选择的模板名称
async getRepo() {
// 1)从远程拉取模板数据
const templateList = await getTemplateList();
if (!templateList.length) return;
// 2)用户选择自己要下载的模板名称
const { template } = await inquirer.prompt([
{
type: 'list',
name: 'template',
message: "请选择模板来初始化项目",
choices: templateList
}
])
return template;
}
// clone远程模板
async download(repo){
// 1)拼接下载地址
const repoUrl = `https://gitee.com/Yjust4U/${repo}.git`;
// 把安装后的模板放到targetDir中
await execAsync('git', ['clone', repoUrl], {
stdio: 'inherit',
cwd: this.targetDir,
})
}
async toTargetDir(repo) {
// 获取模板目录
const templatePath = path.join(this.targetDir, repo);
// .git文件所在位置
const gitFile = path.join(this.targetDir, '/.git');
// 赋值到targetDir中
await fs.copy(templatePath, this.targetDir);
// 删除模板文件
await fs.remove(templatePath);
// 删除.git文件
await fs.remove(gitFile);
}
// 核心创建逻辑
async create() {
// 1)获取模板名称
const repo = await this.getRepo();
// 2)下载模板到模板目录
await this.download(repo);
// 3) 把模板拷贝到项目目录
await this.toTargetDir(repo);
console.log('下载完成');
}
}
module.exports = Generator;
ora 命令行loading动效
首先我们得使用ora
库封装一下loading
动效
utils/utils/lib/index.js
// 添加加载动画
async function wrapLoading(fn, message, failMessage, ...args) {
// 使用 ora 初始化,传入提示信息 message
const spinner = ora(message);
// 开始加载动画
spinner.start();
try {
// 执行传入方法 fn
const result = await fn.apply(null, ...args);
// 状态为修改为成功
spinner.succeed();
return result;
} catch (error) {
// 状态为修改为失败
spinner.fail(failMessage)
}
}
封装好以后了,两个地方需要使用,第一个是
commands/init/lib/generator.js
中的获取仓库模板
// return 用户选择的模板名称
async getRepo() {
// 1)从远程拉取模板数据
const templateList = await wrapLoading(getTemplateList, '获取仓库模板中....', '获取仓库模板失败');
if (!templateList.length) return;
// 2)用户选择自己要下载的模板名称
const { template } = await inquirer.prompt([
{
type: 'list',
name: 'template',
message: "请选择模板来初始化项目",
choices: templateList
}
])
return template;
}
还有一处是下载模板
// clone远程模板
async download(repo){
// 1)拼接下载地址
const repoUrl = `https://gitee.com/Yjust4U/${repo}.git`;
// 把安装后的模板放到targetDir中
const result = await wrapLoading(execAsync, '下载模板中....', '下载模板失败', ['git', ['clone', repoUrl], {
cwd: this.targetDir,
}]);
return result;
}
两处都搞定以后我们的项目就完美了
测试
接下来测试一下
good
呀
最后
我的项目已经上传到npm
上了, 大家也可以全局npm
安装来把玩,package
名称为@wson-koa2-cli/core