前端脚手架搭建分享
最近团队需要统一脚手架,花了点时间了解了一下如何去进行搭建
其实原理并不复杂,
第一步,首先我们要知道需要哪些东西,然后我们要创建什么东西
-
我们首先需要一个可被 node 执行入口文件
-
需要生成文件的模板
-
使用 node fs 模块把模板写入我们指定的目录
这是最简单的思路,那么我们就可以动手了
-
首先创建一个文件夹,然后在文件夹执行 npm init 初始化一个 package.json 文件
-
然后创建一个入口文件 index.js,然后写入
#!/usr/bin/env node console.log('hello,cli!'); 复制代码
这时候执行 node index.js 就能够在控制台打印 hello,cil!
-
再创建一个模板文件 template.js, 添加字符串
hello,template! 复制代码
-
然后我们在 index.js 进行修改,通过 process.cwd()获取 node 当前执行路径,我们可以读取一个文件,并写入到一个目录下
#!/usr/bin/env node console.log('hello,cli!'); const fs = require("fs"); const path = require("path"); const folderName = path.join(process.cwd(), "/cli"); // 判断文件夹是否存在 const mkdirFile = (name) => { try { if (!fs.existsSync(name)) { fs.mkdirSync(name); } } catch (err) { console.error(err); } }; fs.readFile("./template.js", "utf-8", (err, data) => { if (err) { console.log(err); return; } else { console.log(data); mkdirFile(folderName); fs.writeFileSync(`${folderName}/template.js`, data); } }); 复制代码
-
第一步基础就完成了。下面我们进行思考
如何在创建脚手架时,需要在控制台进行交互,这时候需要引入安装第三方库
- commander 可以自动的解析命令和参数,用于处理用户输入的命令
- inquirer 用户输入/选择交互
- ora 控制台进度动画提示
好了,这时候我们修改 index.js,执行 node index.js 就会提示,使用 create 参数,执行 node index.js create 项目名,然后进入项目类型选择,选择完成,就会创建对应名称的项目文件夹,并在里面创建 template.js
#!/usr/bin/env node
// console.log("hello,cli!");
const fs = require("fs");
const path = require("path");
const ora = require("ora");
const inquirer = require("inquirer");
const program = require("commander");
// 判断文件夹是否存在
const mkdirFile = (name) => {
try {
if (!fs.existsSync(name)) {
fs.mkdirSync(name);
}
} catch (err) {
console.error(err);
}
};
const doFs = (name) => {
fs.readFile("./template.js", "utf-8", (err, data) => {
if (err) {
console.log(err);
return;
} else {
mkdirFile(name);
fs.writeFileSync(`${name}/template.js`, data);
}
});
};
program
// .version('1.0.0')
.command("create <app-name>")
.description("create a new project")
.action(async (name) => {
const cwd = process.cwd();
const questions = [
{
type: "list",
message: "请选择项目类型: ",
name: "type",
choices: [{ name: "web项目", value: "web" }],
},
];
const { type } = await inquirer.prompt(questions);
const proce = ora("Start creating...");
proce.start();
const folderName = path.join(cwd, name);
doFs(folderName);
proce.succeed("succeed done!");
});
program.parse(process.argv);
复制代码
那么到此,我们的基本思路已经完成,我们需要重新整理一下。
-
首先,我们创建一个 bin 文件夹,添加 tara.js 文件,作为我们的入口,在其中引入 index.js
-
创建一个 src 文件夹,里面存放我们所有的源码,添加 src/core 文件夹
-
因为后续的模板定义,类定义会用到,我们需要可直接执行 ts 文件,所以需要添加一个第三方组件,npm i -S ts-node @types/node,具体使用可以参照官方文档,然后将 tara.js 改造
#!/usr/bin/env node
const tsNode = require("ts-node/dist/bin");
const path = require("path");
(async () => {
const argv = process.argv.slice(2);
const dir = path.join(__dirname, "../src");
tsNode.main(["index.ts", ...argv], { "--dir": dir });
})();
复制代码
-
修改 index.js 为 index.ts,并给所有方法参数添加类型定义,然后直接执行 node bin/tara,这时候会抛 Cannot find module ‘typescript’错误,需要安装 ts 库 npm i -S typescript
-
这时候我们也可以使用远程模板 download-git-repo 支持从 Github 下载仓库,详细了解可以参考官方文档。
npm install --save download-git-repo
复制代码
download() 第一个参数就是仓库地址,详细了解可以看官方文档
-
使用本地模板,那我们的思路是,可以生成一个统一的模板配置对象,然后根据配置,一个一个的生成文件,从而生成完整的项目目录
-
那第一步就是先创建一个模板类 Project.ts,定义生成 package.json 文件的属性
_init_方法是一个抽象方法,用于子类进行自定义一些操作
import Package from "./Package"; abstract class Project { name: string; private package: Package; constructor(parameters) {} init() {} protected abstract _init_: void; } export default Project; 复制代码
- 创建一个 Package 类
class Package { constructor(parameters) {} } export default Package; 复制代码
-
// TODO