【Vue】3.0利用远程仓库自定义项目脚手架
目录
- 介绍
- 正文
- 目标
- 依赖
- 实现
- 运行
介绍
项目脚手架(Project Scaffolding)是一种用于快速生成项目基础结构的工具或模板,类似于建筑中的“脚手架”——为项目搭建一个标准化的初始框架,帮助开发者省去重复性配置工作,专注于核心功能的开发。
虽然Vue提供了标准项目脚手架,但是生成的项目模板过于简洁,应用到实际开发中还需要做很多配置和开发。同时为了在团队间统一项目框架,自定义项目脚手架就显得无比重要。
正文
目标
实现通过命令行创建项目,创建过程中可以选择不同的项目模板(如下图),最终通过拉取远程仓库的形式,完成项目初始化的过程。
依赖
脚手架项目用到的依赖如下:
- chalk@4.1.2:用于终端输出着色
- commander@13.1.0:解析命令行参数
- download-git-repo@3.0.2:下载Git仓库
- fs-extra@11.3.0:增强文件系统操作
- inquirer@8.0.0:创建交互式命令行提示
- ora@4.1.1:显示命令行加载动画
PS:推荐使用标注的版本号以统一使用commonjs模式引用插件,有些库的高级版本升级了ES模块,感兴趣的朋友可以自行探索。
实现
首先创建项目,并初始化npm
mkdir my-cli && cd my-cli
npm init
根据需要生产package.json文件,如下
{
"name": "my-cli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
接着安装指定版本的依赖,安装后的package.json文件如下
{
"name": "my-cli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.1.2",
"commander": "^13.1.0",
"download-git-repo": "^3.0.2",
"fs-extra": "^11.3.0",
"inquirer": "^8.0.0",
"ora": "^4.1.1"
}
}
接着我们就可以编写业务代码。
首先创建bin和generators两个文件夹,然后分别创建文件bin/my-cli.js和generators/create.js,最终工程目录如下图
然后分别编写代码
bin/my-cli.js
使用 commander 模块创建了一个命令行工具,提供 create 命令用于创建新项目。主要功能如下:
设置版本号为 1.0.0。
定义 create 命令,接收项目名称作为参数,并调用 create 函数创建项目。
解析命令行参数,若无参数则显示帮助信息。
#!/usr/bin/env node
const { Command } = require('commander');
const program = new Command();
const create = require('../generators/create');
program
.version('1.0.0')
.command('create <app-name>')
.description('create a new project')
.action((name) => {
create(name);
});
program.parse(process.argv);
if (!program.args.length) {
program.help();
}
generators/create.js
是通过命令行工具创建一个新项目,用户可以选择不同的模板并填写项目描述和作者信息,然后下载对应的模板到指定目录,并更新 package.json 文件。
使用 inquirer 提示用户输入项目描述、作者和选择模板。
检查目标目录是否存在,如果存在则终止程序。
显示加载动画并下载所选模板。
下载成功后,更新 package.json 文件中的项目名称、描述和作者信息。
const fs = require('fs-extra');
const inquirer = require('inquirer');
const chalk = require('chalk');
const path = require('path');
const download = require('download-git-repo');
const ora = require('ora');
const templates = [
{
name: 'Vue3.0后台管理系统',
value: 'direct:http://你的项目地址.git',
},
{
name: 'Vue3.0大屏项目',
value: 'direct:http://你的项目地址.git',
},
{
name: 'Uniapp移动端项目',
value: 'direct:http://你的项目地址.git',
},
];
module.exports = async (name) => {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'description',
message: 'Project description',
},
{
type: 'input',
name: 'author',
message: 'Author',
},
{
type: 'list',
name: 'template',
message: 'Choose a template:',
choices: templates,
}
]);
const root = path.join(process.cwd(), name);
console.log(`project directory: ${root}`);
if (fs.existsSync(root)) {
console.log(chalk.red(`Target directory ${chalk.cyan(root)} already exists.`));
return;
}
// 显示加载动画
const spinner = ora(`Downloading template ${chalk.cyan(answers.template)}...`).start();
download(answers.template, root, { clone: true }, (err) => {
if (err) {
spinner.fail(chalk.red(`Failed to download template: ${err}`));
return;
}
spinner.succeed(chalk.green(`Template downloaded successfully.`));
const packageJsonPath = path.join(root, 'package.json');
if (fs.existsSync(packageJsonPath)) {
const packageJson = fs.readJsonSync(packageJsonPath);
packageJson.name = name;
packageJson.description = answers.description;
packageJson.author = answers.author;
fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
console.log(chalk.green(`Successfully created project ${chalk.cyan(name)}.`));
}else{
console.log(chalk.yellow(`No package.json found in the template. Skipping package.json update.`));
}
});
};
最后修改package.json文件,讲执行入口指向bin/my-cli.js文件,修改后package.json文件代码如下
{
"name": "my-cli",
"version": "1.0.0",
"description": "",
"bin": {
"my-cli": "./bin/my-cli.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.1.2",
"commander": "^13.1.0",
"download-git-repo": "^3.0.2",
"fs-extra": "^11.3.0",
"inquirer": "^8.0.0",
"ora": "^4.1.1"
}
}
至此业务代码已经开发完成。
运行
开发过程中,我们可以使用
npm link
全局链接脚手架,这样就可以随时模拟使用脚手架,通过
my-cli create myproj
就可以选择生成模板项目,如下图
当然也可以发布脚手架项目到npm或者私库上面,只需要登录对应库,使用publish命令即可
npm publish
然后就可以使用npm全局安装脚手架
npm install -g my-cli
最后使用npx运行即可
npx my-cli create myProj
至此,自定义项目脚手架的简单流程就已经结束了。
当然各位可以根据需求,增加命令行提示内容,只需要修改generators/create.js增加inquirer输入提示即可。