起因

  • 最近突然了解到脚手架的概念,然后就了解了一下,发现其实脚手架就是一个工具,用于快速搭建项目,而其中的工具就是一些脚本,
    这些脚本可以用来初始化项目,安装依赖,运行测试等。
  • 因为平常搞项目老是得自己建一堆文件夹然后又一堆初始化的工程,每次写都觉得心累。然后我就想,既然脚手架是一个工具,那么我
    也可以自己定制一个脚手架,这样就可以根据自己的需求来搭建项目了。

定制脚手架

  1. 了解一些底层逻辑,安装一些需要使用的依赖
  • Commander 是一个用于构建命令行工具的 npm 库
  • Inquirer 是一个强大的命令行交互工具,用于与用户进行交互和收集信息
  • Ora 是一个用于在命令行界面显示加载动画的 npm 库
  • Download-git-repo 是一个用于下载 Git 仓库的 npm 库
  1. 文件配置
  • #!/usr/bin/env node 告诉系统用 node 来解析这个文件(隐式执行)
  • package.json 中的 bin 字段告诉系统入口文件
  • npm link 把当前文件夹链接到全局(软连接)
  1. 配置 github 仓库模板,然后就可以通过不同的参数拉取不同的分支模板。
  2. 书写逻辑

index.js

#!/usr/bin/env node
import { program } from "commander";
import inquirer from "inquirer";
import { checkNodeVersion, checkFilePath, config } from "./utils.js";
import { downloadTemplate } from "./download.js";
/**
*
* @param {string} defaultName 默认项目名
* @returns {object} 返回命令行交互的结果
*/
async function createPromptList(defaultName) {
return inquirer.prompt([
{
type: "input",
name: "name",
message: "请输入项目名称",
default: defaultName,
validate: function (value) {
if (!value) {
return "项目名称不能为空";
}
return true;
},
},
{
type: "list",
name: "version",
message: "请选择构建框架",
default: "vue3",
choices: [
{ name: "vue3", value: "vue3" },
{ name: "react18", value: "react18" },
],
},
{
type: "confirm",
name: "isTypescript",
message: "是否使用typescript",
default: true,
},
]);
}

function main() {
const version = config.version;
program.version(version);
// Node版本校验
checkNodeVersion();
// 定义命令
program
.command("create <name>")
.description("拉取项目模板")
.action(async name => {
//拿到交互结果
const options = await createPromptList(name);
if (checkFilePath(options.name)) {
console.error("项目已存在");
return;
}
//根据交互结果从git拉取模板
await downloadTemplate(options);
});

// 解析命令行参数
program.parse(process.argv);
}

main();

utils.js

import fs from "node:fs";
import semver from "semver";
import path from "node:path";

const configPath = path.join(process.cwd(), "package.json");
const configJson = fs.readFileSync(configPath, "utf-8");

export const config = JSON.parse(configJson);

/**
* 校验是否存在文件夹
* @param {string} path 校验文件路径
* @returns {boolean}
*/
export const checkFilePath = path => fs.existsSync(path);

/**
* 校验node版本
*/
export const checkNodeVersion = () => {
const check = semver.lt(process.version, "16.0.0");
if (check) {
throw new Error("node版本过低,推荐升级node至v16.0.0+");
}
};

download.js

import ora from "ora";
import download from "download-git-repo";

const spinner = ora("正在下载模板...");
/**
* 根据交互结果从git拉取模板
* @param {object} options 命令行交互结果
* @param {string} options.version 项目版本
* @param {boolean} options.isTypescript 是否使用typescript
* @param {boolean} options.isScss 是否使用scss
*/
export const downloadTemplate = options => {
const { name, version, isTypescript } = options;
// 拉取模板
return new Promise((resolve, reject) => {
spinner.start();
const isTs = isTypescript ? "-ts" : "-js";
download(`direct:https://github.com/hshijing/nodeCreateCli.git#${version}${isTs}`, name, { clone: true }, err => {
if (err) {
console.error(err);
spinner.stop();
reject(err);
}
resolve();
spinner.succeed("下载模板成功");
spinner.stop();
});
});
};
  1. 使用 npm link 把本地脚手架链接到全局
  2. 本地测试
  3. 使用 verdaccio 搭建私服 npm 并发布
  4. 使用 npm 安装本地脚手架再次测试

结语

  • 总体来说满足自己的开发需求的话不难,如果要做公共库的话需要思考的就很多了!!!