工作场景:
1、假设你的公司会使用Vue、react技术栈(或者还有其他的)
2、你和你的前端同事们需要经常使用 create-vue、create-react-app来创建项目,然后配置ESlint、Prettier…
或者还有一些其他的你们公司自己的东西,比如说自己封装的axios库、自己的UI库等等
那么这个时候如果能用命令行来快速完成这些重复的工作,是不是能节省不少时间?毕竟工程化的目标之一就是提效啊。
所以,应该怎么做呢?
大致可通过以下几个步骤实现:
- 命令行输入一个命令(比如:my_cli)
- 选择要使用的框架
- 输入项目名称
- 下载对应的模块库代码
接下来我们看下具体的每一个步骤怎么实现。
前置准备
要准备好对应的模板项目。这里我准备了Vue和react的。
● Vue
就是基于create-vue创建了一个空项目。引入了element-plus作为UI组件库。
● react
用create-react-app创建的一个空项目。
当前模块项目里面可以有一些你公司特性的内容在里面。作为demo,你可以使用我创建的这两个示例模板。
vue-template
react-template
实现步骤
1、创建一个脚手架的项目
mkdir my_cli
cd my_cli
npm init
在my_cli下创建src/bin/index.js文件。
#!/usr/bin/env node
console.log('我的脚手架')
在 package.json 中添加一个 bin 属性
"type": "module",
"bin": {
"my_cli": "./src/bin/index.js"
},
然后执行下:sudo npm link
命令。
这个时候就可以在命令行执行命令my_cli了。
这一步会在控制台输出文字:我的脚手架
2、在控制台输出脚手架的名称
需要使用 clear、chalk-animation 、 figlet 三个包
● clear 清空控制台
● figlet 提供一些文字效果
● chalk-animation 命令行动画与渐变颜色。
安装:npm i clear figlet chalk-animation
index.js文件
clear(); // 清屏
const cliName = figlet.textSync('my_cli')
const neon = chalkAnimation.neon(cliName)
setTimeout(() => {
neon.stop(); // Animation stops
}, 1000);
这一步的效果:
figlet还提供了其它一些炫酷的样式。
3、添加一些选择项
使用户可以选择要使用的框架。需要安装inquirer。
这里提供3个选项:react、vue、退出。
setTimeout(() => {
neon.stop(); // Animation stops
query();
}, 1000);
const opttions = {
"Vue": "vue",
"React": "react",
退出: "quit"
};
const question = [
{
type: "rawlist" /* 选择框 */,
message: "请选择要使用的框架?",
name: "frame",
choices: Object.keys(opttions),
},
];
async function query() {
const answer = await inquirer.prompt(question);
console.log(`你的现在是:${answer.frame}`);
return;
}
这一步的效果是:
4、根据用户选择的框架下载对应的模板
在用户选择模板后,请用户输入项目名称,如果没有输入,默认给一个。
index.js文件添加
async function query() {
const answer = await inquirer.prompt(question);
// console.log(`你的选择是:${answer.frame}`);
if (answer.frame === "退出") return;
await next(answer.frame);
}
async function next(frame) {
let { name } = await inquirer.prompt([
{
type: "input" /* 选择框 */,
message: "请输入项目的名称?",
name: "name",
},
]);
if (!name) name = `${frame.toLowerCase()}_projects`;
log("开始创建项目:" + name);
// 从github克隆项目到指定文件夹
await clone(`github:demong89/${frame.toLowerCase()}-template`, name);
}
src/utils/clone.js
import { promisify } from "util";
import download from "download-git-repo";
import ora from "ora";
export default async (repo, desc) => {
const process = ora(`开始下载.....${repo}`);
process.start();
await promisify(download)(repo, desc);
process.succeed();
};
这一步完成后,就可以下载项目到本地了。
5、把下载的项目package.json中name改成项目名
index.js添加
// 修改package.json项目名称
compile(`${frameName}-template`, name, `./${name}/package.json`);
log(
`
👌 安装完成:
To get Start:
===========================
cd ${name}
${gen(frameName)}
===========================
`
);
src/utils/compile.js
import fs from "fs";
import handlebars from "handlebars";
import { log } from "./index.js";
export function compile(templateName, name, filePath) {
if (fs.existsSync(filePath)) {
const content = fs.readFileSync(filePath).toString();
// console.log("名称:", templateName, name);
const result = content.replaceAll(templateName, name);
// console.log(result);
fs.writeFileSync(filePath, result);
log(`📚 ${filePath} 修改成功`);
} else {
log(`❌ ${filePath} 修改失败`);
}
}
这一步完成,就可以正确创建对应的模块项目了。
当然这只是走了一下流程。中间可以根据自己的需求添加不同的流程,来创造属于你自己的脚手架。
完整代码
最后
当然事情还没完。在第一个步骤的时候我们用npm link 将项目链接到本地执行的。那脚手架项目写好后要给公司同事使用的啊。
将脚手架项目发布到npm。然后全局安装一下,就可以正常使用了。
你可以使用我这个demo来尝试一下。
npm i my_cli_demong -g
my_cli
说一下这里为啥是my_cli_demong和my_cli。 上传npm包的时候,my_cli已经存在了,需要改个名称,所以加了一个demong后缀。而my_cli是我们配置的可执行的命令名称,在package.json的bin字段里。
好了,动手实践一下吧。