场景
随着项目组规模的扩大,前端项目规范约束也被提上了日程。为了做足规范方面的约束,我向我很多大厂的朋友询问了他们前端规范约定。如果大家感兴趣的话我之后可以出一节关于前端项目规范约束的章节,看大家的反响哦,绝对的企业级项目。好了言归正传,在前端规范做好之后我又发现了一个问题,如果每个项目都想要沿用这一规范的话,是比较困难的,即使我们把项目放在了git上面,但是在使用某一模版的时候还是比较耗时的,所以我选择了一个一劳永逸的方式——脚手架!
脚手架搭建
什么是前端脚手架工具
前端脚手架(Front-end framework 或 Front-end scaffold)是一套预定的目录结构、文件和工具的集合,旨在帮助前端开发人员更有效地搭建和组织项目。它通常包含了项目的基本结构、构建工具、依赖管理等,以提供一致的开发环境,并简化开发流程。
脚手架可以通过命令行工具交互式的为提供开发者提供标准化的项目结构,快速启动新项目,省去了耗时的项目初始化过程。
搭建脚手架的相关依赖
一个脚手架一定离不开下面的几个库,下面我将一一介绍:
- chalk
Chalk 是一个用于在终端中输出彩色文本的库。它提供了一种简便的方式来为控制台输出添加颜色,样式和格式。
主要用于美化命令行输出,使得输出的文本更具有可读性和吸引力。 - commander
Commander 是一个用于构建命令行工具的库,它提供了一组强大的功能,包括定义命令、选项、处理参数等。
用于创建复杂的命令行界面,使得开发者能够更轻松地构建和管理命令行工具。 - download-git-repo
download-git-repo 是一个用于从 Git 存储库下载代码的库。它允许你通过提供 Git 存储库的 URL,将存储库的内容下载到本地。
通常用于在项目初始化或命令行工具中,从远程 Git 存储库中下载模板或代码。 - inquirer
Inquirer 是一个交互式命令行工具的库,它提供了一套用户界面交互的工具,可以用于创建命令行提示、选择、输入等交互界面。
用于在命令行中向用户提出问题,接收用户输入,以便更友好地与用户进行交互。 - ora
Ora 是一个用于在终端中显示加载指示器(loading spinner)的库。它提供了一种简单的方式来显示正在进行中的任务的加载状态。
主要用于在命令行工具中显示加载状态,告知用户程序正在执行某个操作,以提高用户体验。
思路
其实一个脚手架初期的思路是十分简单的。我们项目组想要搭建脚手架的初衷很简单,就是想要通过类似于npm create vite
的方式通过交互式的命令行工具来实现模版的下载。
- 在命令行中输入特定的命令;
- 通过交互式的方式,选择要拉取的模版;
- 通过附加的命令行选项直接指定要使用的模板。
脚手架初始化
创建一个空目录,然后执行npm init -y
,初始化package.json。
{
"name": "create-dgn-project-template",
"version": "0.0.1",
"description": "",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+"
},
"author": "smallDragon-z",
"license": "ISC"
}
安装相关依赖
{
"dependencies": {
"chalk": "^2.4.2",
"commander": "^2.19.0",
"download-git-repo": "^1.1.0",
"inquirer": "^6.2.2",
"ora": "^3.2.0"
},
}
在根目录下创建bin/create.js
!!!注意:因为我们的代码是运行的命令行工具(node环境)的,所以入口文件顶部一定要加上
#!/usr/bin/env node
它告诉操作系统执行这个脚本的时候,调用 /usr/bin/env 来执行,env会在PATH目录中查找node并执行它。
入口文件:
#!/usr/bin/env node
/**
* @description: 通过交互式命令行创建项目
* */
const inquirer = require('inquirer');
const questions = require('../data/question');
const path = require('path');
const { createFolder } = require('../IO/createFolder');
const cloneGit = require('../IO/cloneGit');
inquirer.prompt(questions).then((answers) => {
const { projectName } = answers;
const currentDirectory = process.cwd(); // 获取命令行执行的目录
const folderPath = path.join(currentDirectory, projectName); // 构建文件夹路径
const { IsCreated } = createFolder(folderPath); // 创建文件夹
if (IsCreated) {
console.log('folderPath', folderPath);
cloneGit('smallDragon-z/itpsp-tv#main', folderPath);
}
});
功能:
questions 问题
/**
* @description 问题列表自定义交互式命令行的问题及简单的校验
* */
const { red } = require('chalk');
const { checkFilenameRules } = require('../utils/checkFilenameRules');
const questions = [
{
name: 'projectName',
type: 'input',
message: '请输入模板名称',
default: 'react-template',
validate(val) {
// 校验
// 1. 输入不能为中文
if (checkFilenameRules(val)) {
return true;
} else {
console.log(red('项目名不合法'));
return false;
}
},
},
];
module.exports = questions;
createFolder
/**
* @description 创建目录
* @param {String} folderPath 要创建的目录路径
* @returns {Object} { IsCreated: true }
* */
const fs = require('fs');
const { checkDirectoryExists } = require('../utils/checkDirectoryExists');
const chalk = require('chalk');
const createFolder = (folderPath) => {
// 判断文件夹是否存在
// 存在则删除
if (checkDirectoryExists(folderPath)) {
fs.rmSync(folderPath, { recursive: true });
}
// 创建文件夹
try {
// 创建目录,如果目录已存在,则抛出异常
fs.mkdirSync(folderPath);
return {
IsCreated: true,
};
} catch (error) {
console.log(chalk.red(`目录 ${folderPath} 创建失败`));
}
};
module.exports = { createFolder };
cloneGit:
/**
* @description: 克隆git仓库到指定目录
* */
const download = require('download-git-repo');
const ora = require('ora');
const cloneGit = (gitUrl, folderPath) => {
const spinner = ora('Loading...').start();
download(
gitUrl,
folderPath,
{
clone: true, // 是否使用 Git clone,默认为 false
logger: function (message) {
console.log('message', message);
},
},
function (err) {
// 使用ora添加一个loading效果
if (err) {
console.log('err', err);
spinner.fail('git仓库克隆失败');
} else {
spinner.succeed('git仓库克隆成功');
}
},
);
};
module.exports = cloneGit;
因为这是初版,还没有通过commder来配置相关的命令选项来指定模板,之后的版本中会持续更新。
如果想学习的话可以到我的gitee仓库学习。
一些关于download-git-repo的问题
- 提示下载失败的原因:
- 网络问题: 网络连接可能不稳定或者被防火墙阻塞,导致无法连接到 Git 服务器。
- Git 仓库不存在或不可访问: 确保提供的 Git 仓库地址是正确的,并且你有权限访问该仓库。
- 权限问题: 如果仓库是私有的,确保你有权限访问,并且提供了正确的身份验证信息。
- 分支问题:默认拉取master分支中的代码,如果不符合这一规则请指定对应的分支。
- Git 版本问题: 确保你的系统上安装了正确版本的 Git,并且可以在命令行中正常使用 Git。
- 存储空间问题: 确保你的文件系统有足够的空间来存储下载的文件。
- 代理问题: 如果你在一个受代理网络环境中,可能需要配置 Git 使用代理。
- Git 仓库结构问题: 有时候,Git 仓库可能包含一些特殊的结构或文件,可能导致下载失败。
- 路径问题: 检查你下载的目标路径是否正确。有时候指定的路径不存在,导致下载后找不到相应的文件夹。
10.还有一些我没有发现的错误请自行查看官网,或者自行百度 解决方案。
- 提示下载成功但是模板并没有被拉取到本地
如果你使用的是绝对路径,并且确认该路径是存在的,但仍然没有看到相应的文件夹,那么你可以尝试通过检查错误信息、日志或者回调函数的参数来获取更多的信息,以便定位问题。以下是一些可能有助于解决问题的步骤:
检查回调函数的错误参数: 在 download-git-repo 的回调函数中,第一个参数通常是错误信息。你可以输出该错误信息,以便了解下载过程中是否发生了错误。
download(repoUrl, destination, function (err) {
if (err) {
console.error('Error:', err);
} else {
console.log('Download complete');
}
});
查看下载过程的日志: download-git-repo 提供了一些配置选项,可以启用日志记录。你可以尝试设置 options 对象,以便在下载时输出更详细的日志信息。
const download = require('download-git-repo');
const repoUrl = 'username/repo';
const destination = './my-repo';
const options = {
clone: true, // 是否使用 Git clone,默认为 false
logger: function (message) {
console.log(message);
},
};
download(repoUrl, destination, options, function (err) {
if (err) {
console.error('Error:', err);
} else {
console.log('Download complete');
}
});
这样你就能够看到更详细的日志信息,可能能够帮助你找到问题所在。
手动尝试使用 Git Clone: 你可以尝试手动使用 Git 命令来克隆相同的仓库到相同的目标路径,以验证是否存在问题。
git clone <仓库地址> <目标路径>
如果手动克隆也出现问题,可能是网络、权限或仓库地址等方面的问题。确保手动克隆能够正常执行。
通过以上步骤,你应该能够更容易地找到问题所在并解决它。如果问题仍然存在,你可以考虑尝试使用其他下载 Git 仓库的 Node.js 模块,或者直接使用 git 命令行工具执行克隆操作。