打造自己的前端脚手架tool-cli,用nodejs实现命令行创建项目

接触前端开发的同学们知道,现在流行的前端开发框架都有自己的项目创建脚手架,例如vue的vue-cli,这篇文章带领大家打造自己的前端脚手架,暂命名为tool-cli,用它来创建项目。
接下来即将实现的功能如下:

  1. 创建可执行文件
  2. 解析命令行参数

创建可执行文件

首先我们需要安装nodejs下载偶数版本安装就行,然后进行脚手架项目的创建,创建一个名为tool-cli的目录,进入tool-cli目录创建tool、testProject两个目录,先进入tool目录打开命令行执行npm init一路按回车键,结果如下图所示:

hai@haideMBP tool-cli % mkdir testProject
hai@haideMBP tool-cli % cd tool 
hai@haideMBP tool % npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.
  
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (tool) 
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /Users/hai/software/tool-cli/tool/package.json:

{
  "name": "tool",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Is this OK? (yes) 
hai@haideMBP tool %

在testProject同样适用npm init命令进行初始化项目

接下来在tool目录中创建bin目录并创建index.js文件,文件目录结构如下:

├── bin
│   └── index.js
└── package.json

使用文本编辑器打开index.js中输入

#!/usr/bin/env node
console.log('我创建了一个输出字符串的代码,哈哈哈!')

现在我们可以在tool目录中运行该程序了,在这个目录打开命令行输入node bin/index.js能看到我们写的文字了,下面是执行结果。

hai@haideMBP tool % node bin/index.js
我创建了一个输出字符串的代码,哈哈哈!
hai@haideMBP tool %

现在我想在testProject测试目录中运行我们的脚手架,先在tool目录的package.json中添加"bin": "./bin/index.js",,最终文件内容如下:

{
  "name": "tool",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "bin": "./bin/index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

还需要做一个链接,在tool目录运行命令npm link,输出结果如下:

hai@haideMBP tool % npm link

changed 1 package, and audited 3 packages in 1s

found 0 vulnerabilities

然后在testProject目录运行命令npm link tool,然后我们在testProject目录就可以使用tool命令了,让我们看看效果:

hai@haideMBP testProject % npm link tool

up to date, audited 3 packages in 1s

found 0 vulnerabilities
hai@haideMBP testProject % tool
我创建了一个输出字符串的代码,哈哈哈!

这样可执行文件就被我们创建好了,接下来让我们添加执行命令吧!

解析命令参数

现在我们要做的是添加一个create命令,从gitee网站拉取项目模板并创建项目,使用commander这个npm包帮助我们简化解析命令参数工作,在tool目录下执行npm install [email protected],安装完成显示如下:

hai@haideMacBook-Pro tool % npm install [email protected]

added 1 package, and audited 2 packages in 3s

found 0 vulnerabilities

将tool目录下bin/index.js文件的内容改为如下内容:

#!/usr/bin/env node

const { Command } = require('commander');

const program = new Command();

const pkg = require("../package.json");

// 这里是告诉命令行我们的工具名称、说明和版本,使用的是package.json中的内容
program
.name(pkg.name)
.description(pkg.description)
.version(pkg.version);

// 这里添加create命令
program
.command("create")
.description("创建模版")
.action(() => {
	console.log("我执行了创建命令!!!")
});

program.parse(process.argv);

让我们打开一个新的命令行进入testProject目录,执行tool命令,将会看到如下输出:

hai@haideMBP testProject % tool
Usage: tool [options] [command]

Options:
  -V, --version   output the version number
  -h, --help      display help for command

Commands:
  create          创建模版
  help [command]  display help for command

试着输入tool -Vtool create看看输出吧。

接下来在tool目录中创建src目录,在src中创建commands子目录,在创建一个create.js文件,这个文件将用来处理拉取项目模板的具体操作。现在tool目录结构如下所示:

hai@haideMacBook-Pro tool % mkdir -p src/commands
hai@haideMacBook-Pro tool % touch src/commands/create.js
hai@haideMacBook-Pro tool % tree
.
├── bin
│   └── index.js
├── node_modules
│   └── commander
│       ├── LICENSE
│       ├── Readme.md
│       ├── esm.mjs
│       ├── index.js
│       ├── lib
│       │   ├── argument.js
│       │   ├── command.js
│       │   ├── error.js
│       │   ├── help.j
│       │   ├── option.js
│       │   └── suggestSimilar.js
│       ├── package-support.json
│       ├── package.json
│       └── typings
│           ├── esm.d.mts
│           └── index.d.ts
├── package-lock.json
├── package.json
└── src
    └── commands
        └── create.js

8 directories, 18 files

在create.js文件中添加如下内容,其中inquirer用来添加交互式操作,download-git-repo用来下载模板,ora用来添加下载等待动画,chalk用来给输出文字添加特定的颜色。

const chalk = require('chalk');
const download = require("download-git-repo");
const ora = require("ora");
const inquirer = require("inquirer");

// 远程模板列表
const remoteList = {
	"kotlin": "https://github.com/babyfish-ct/jimmer.git",
	"java": "https://github.com/babyfish-ct/jimmer.git",
};

// 模版下载方法
const create = (remote, name, option) => {
	const downSpinner = ora("正在下载模板...").start();
	return new Promise((resolve, reject) => {
		download(remote, name, option, (err) => {
			if (err) {
				downSpinner.fail();
				console.log("err", chalk.red(err));
				reject(err);
				return;
			}
			downSpinner.succeed(chalk.green("模板下载成功!"));
			resolve();
		});
	});
};

  

module.exports = ()=>{
inquirer
	.prompt([
		{
			type: "input",
			name: "projectName",
			message: "请输入项目名称",
		},
		{
			type: "list",
			name: "language",
			message: "请选择开发语言",
			choices: [
				{
				name: "Kotlin",
				value: 'kotlin',
				description: "Kotlin版本Jimmer",
				},
				{
				name: "Java",
				value: 'java',
				description: "Java版本Jimmer",
				},
			],
		},
	])
	.then((answers) => {
		create(`direct:${remoteList[answers.language]}`, answers.projectNam);
	
	});

}

安装这些npm依赖在tool目录下执行命令

npm install [email protected] [email protected] [email protected] [email protected]

然后在bin/index.js文件中修改内容如下:

#!/usr/bin/env node

const { Command } = require('commander');
const create = require('../src/commands/create');
const program = new Command();

const pkg = require("../package.json");

// 这里是告诉命令行我们的工具名称、说明和版本,使用的是package.json中的内容
program
.name(pkg.name)
.description(pkg.description)
.version(pkg.version);

// 这里添加create命令
program
.command("create")
.description("创建模版")
.action(() => {
	create();
});

program.parse(process.argv);

不出意外的话,在testProject目录执行tool create命令就可以看到提示说请输入项目名称啦,按照提示进行输入,选择会看到在执行命令目录创建了一个为输入项目名称的新目录。

hai@haideMBP testProject % tool create
? 请输入项目名称 ttt
? 请选择开发语言 Kotlin
? 模板下载成功!

好了,这就完成了项目的创建了,接下来就看自己想添加什么命令了,例如添加编译命令、启动命令、模块创建命令等等。

注意:
我们使用的npm包并不是最新的,要使用最新的npm包需要执行npm install chalk inquirer download-git-repo ora来安装npm包,最新报需要使用import方式导入npm包,那么接下来就交给你们实践将require方式引用改import方式吧。排查问题方式在https://www.npmjs.com/网站搜索对应npm包,一般会有使用方式说明,如果没有的话进入对应的github仓库或者官网都会有说明的。