一、需求
开发新需求,一般都要创建好多新文件
唔想鼠标点点点而系通过命令生成新文件
效果预览
二、用户画像、文档、原型
略
三、设计
1. 输入命令
如输入 mycli c src/app然后开始
2. 读取命令
逻辑有诸如以下情况按需处理:
- 名称喺未合法
- 文件喺未已经存在
- 如果喺多层路由点处理;
- 如果喺组件类喺未要大/小驼峰命名
- 喺未有文件后缀
- 喺未需要插入模板
- 如果只喺一个简单咖字符串,喺未想喺某个路径下面直接创建--然后重复
1-6咖问题; - ...
3. 生成文件
如生成src/app.vue文件
四、准备
交互处理
- commander:命令行交互
- inquirer:选择式指令
- path:路径处理
- url:路径处理
- fs-extra:文件处理
- ...
优化体验
- ora:loading
- chalk:输入文字美化
- ...
五、开发
1. mycli
首先喺实现命令mycli咖有效触发。
- 打开
cmd敲命令
mkdir mycli && cd mycli && npm init -y && code .
- 修改配置,用
import语法
"name": "mycli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
- 创建主要文件
mkdir bin && touch bin/index.js
bin/index.js
#! /usr/bin/env node
console.log("Hello world !");
然后执行node bin/index.js,就可以睇到控制台输出Hello world !
package.json
"bin": {
"mycli": "./bin/index.js"
},
- 生成命令
npm link
- 测试命令
mycli
如果提示命令唔存在,重启cmd再次执行mcli,可以睇到控制台成功咁输出Hello world !
2. mycli c
然后喺识别命令参数mycli c,需要
- 安装依赖
yarn add commander fs-extra inquirer path url
- 令
--help生效
#! /usr/bin/env node
import { program } from "commander";
program.option("-d,--debug", "whether to enable debug mode?", false);
program.on("option:debug", () => {
console.log("开启了debug模式");
});
program.on("command:*", (obj) => {
console.error(`未知命令:${obj[0]}`);
});
// 监听 --help 指令
program.on("--help", function () {
// 前后两个空行调整格式,更舒适
console.log("\n", `输入 "cli <command> --help" 查看命令详情.`, "\n");
});
// 必须,让命令生效
program.parse(process.argv);
输入mycli -h就可以睇到提示内容
c咖创建
a. 首先喺新增内容
program
// 命令: mycli create
.command("create ")
// 别名 mycli c 相当于 mycli create
.alias("c")
// 描述信息
.description("创建文件")
.action((createName) => {
console.log("创建命令触发:", createName);
});
b. 然后敲mycli -h可以睇到多咗提示信息
c. mycli c可以见到创建命令触发:{}噶输出
3. mycli c src/app
而家输入mycli c src/app仲唔可以识别到后面咖字符串,继续走
1. argument识别
- 先更新
program代码
program
// 命令: mycli create
.command("create ")
// 别名 mycli c 相当于 mycli create
.alias("c")
// 描述信息
.description("创建文件")
// .usage("[name]")
// <>表示是必输字符,[]表示可选输入字符
.argument("[name]", "文件名称")
.action((createName) => {
console.log("字符串识别:", createName);
});
- 然后敲
mycli c src/app就可以睇到字符串识别: src/app咖输出
2. 直接创建文件
- 需要引入
fs-extra文件模块处理器编写创建文件咖代码,例如:
import fs from "fs-extra";
// ...代码省略
console.log("字符串识别:", createName);
fs.writeFileSync(createName, "哈哈哈");
- 然后执行
mycli c src/app
有/ 符号喺会自动识别为文件夹路径,所以毫无疑问会报错
3. 问题或者喺流程处理
行到呢度已经完成咗一个cli工具最基本亦都喺最主要咖步骤。
下面进入上面1~7个问题噶处理,然后重点喺:
- 路径名称喺未合法
/识别问题- 路径重复问题
- 询问式交互都喺进阶操作,情况比较多,谂太多最后就喺写出来自己都唔想用
下面喺关键节点:
1. 路径名称喺未已经存在
呢个比较好处理,都喺用得最多咖地方,大部分节点都要呢个判断
// root是否已存在文件/夹
export const existsPathSync = (path = "") => {
const root = process.cwd();
let src = path.startsWith("/") ? path : `/${path}`;
if (src.indexOf(root) === -1) {
src += root;
}
const exist = fs.existsSync(src);
if (exist) {
chalk.error(`${src} 已存在`);
}
return exist;
};
2. 路径名称喺未合法
情况诸如喺未中文、首字母喺未英文等等
// name校验
export function patternName(str = "") {
if (!str || !str.trim()) {
chalk.error("不能为空");
return false;
}
// 中文检测
const isChinese =
/[\u4e00-\u9fa5|\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5]/.test(
str
);
// console.log('是否包含中文:' + isChinese);
if (isChinese) {
chalk.error("名称不应该包含中文");
return false;
}
// 首字母 英文开头
const firstWord = str.substring(0, 1);
const isEn = /^[a-zA-Z]+$/.test(firstWord);
// console.log('是否英文开头:' + isEn);
if (!isEn) {
chalk.error("首写字母必须是英文");
return false;
}
return true;
}
3. 文件夹符 / 识别
主要就喺识别字符串中咖/然后处理
// 创建对应文件夹
export function createDirSync(prevDir = "", fileName = "") {
// 如果有文件夹路径,遍历生成文件夹
if (fileName.split("/").length > 1) {
const names = fileName.split("/").filter((src) => src && src !== "/");
// console.log(names);
// 生成的文件名
const __filename = names[names.length - 1];
let str = prevDir;
for (const src of names) {
if (src === __filename) {
break;
}
str = str + "/" + src;
// 不存在,创建文件夹
if (!fs.existsSync(str) && src !== __filename) {
// 创建文件夹
fs.mkdirSync(str);
}
}
}
}
4. app.vue
如果上面咖问题你都已经处理好
输入mycli c src/app喺没有文件后缀咖,想要生成对应类型噶文件,系创建文件咖步骤直接拼接.vue就可以了。
但喺呢种限制比较大,万一我想创建一个js文件,或者我想直接生成模板代码呢,又或者...我想自动识别手机壳颜色变换主题上天呢?所以接下来进入自由发挥模式
1. inquirer
- 询问式交互,引入
inquirer然后新增代码
.action(async (createName) => {
console.log("字符串识别:", createName);
const input = await inquirer.prompt([
{
type: "list",
name: "value",
message: "选择创建的文件后缀",
choices: [".vue", ".js"],
},
]);
console.log(input);
});
- 再次执行命令
mycli c src/app会需要你选择文件后缀,按回车键确认选择
2. 模板
既然喺生成组件,系唔系应该有模板一起生成会比较好,所以要准备模板
首先创建templates目录,然后新增模板文件
// templates/vue.js
const template_vue2 = `
<template>
<div class="">
</div>
</template>
<script>
export default {
name: '',
components: {
},
props: {
},
data() {
return {};
}
};
</script>
<style lang='less' scoped>
</style>
`;
export default template_vue2
3. 生成组件
得到文件后缀,亦都摞到模板代码,接落黎可以生成带模板代码噶vue文件
- 先更新代码
import template from "../templates/vue.js";
.action(async (createName) => {
console.log("字符串识别:", createName);
const input = await inquirer.prompt([
{
type: "list",
name: "value",
message: "选择创建的文件后缀",
choices: [".vue", ".js"],
},
]);
console.log(input.value);
// 方便演示把src/去掉
fs.writeFileSync(`app${input.value}`, template);
console.log("app.vue 组件生成成功!");
});
- 继续执行命令
mycli c src/app - 生成组件,Bingo~!
至此一个通过命令生成包含模板代码的组件文件咖脚本就基本完成。
六、发布、提测、迭代
最后系项目研发咖常规流程,项目周期取决于你想呢个工具为你做D咩
搞掂,收工~