node自定义命令行工具cli


目标创建一个叫做mcli的cli工具,实现下载项目模板

创建项目文件夹

mkdir vue-auto-router-cli

初始化package.json

npm init -y

安装依赖

npm i commander download-git-repo ora handlebars figlet clear chalk open watch -s

npm包名作用
commander用于定制命令
download-git-repo用于下载github项目
ora用于显示加载loading
figlet可以在命令行输出类似logo的海报,用于打印欢迎页面,是一个异步过程
clear清理命令行界面
chalk修改命令行输入的字符颜色
open打开浏览器
watch

自定义命令初体验

创建/bin/mcli.js文件

#!/usr/bin/env node
// 上一行代码指定代码解释环境为node
console.log("cli");

package.json配置可执行命令

  "bin": {
    "mcli": "./bin/mcli.js"
  },

这样就构建了一个命令mcli,在本地环境使用前,要先进行软连接npm link,相当于全局安装了mcli整个插件,然后就可以像其他命令行工具一样使用了

mcli
// 执行mcli命令后,会执行/bin/mcli.js中的代码

定制命令mcli init <name>, 实现在本地生成项目模板

目标:这一步主要借助于commander库,定制一条命令mcli init <name>,当输入该命令后,输出欢迎界面,从githuh下载一个vue项目模板到本地

输出欢迎界面
  • 修改/bin/mcli.js, 定制命令mcli init <name\>
#!/usr/bin/env node
// 上一行代码指定解释环境
const program = require("commander");
program.version(require("../package.json").version);

// 定义一个新的命令 mcli init xxx
program
  .command("init <name>")
  .description("init project")
  .action((name) => {
    // 当前命令执行的内容
    console.log("init" + name);
  });
// process表示当前主进程
// argv 表示当前命令携带的参数
program.parse(process.argv);

此时再执行命令mcli,就会显示当前可以执行的命令,效果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IuuWampU-1627119294646)(/Users/xiongweiliu/Library/Application Support/typora-user-images/image-20210721211446501.png)]

  • 定制命令mcli init <name>的执行内容,输出欢迎界面

新建文件/lib/init.js

// node自带的工具库util
// promisify可以将普通的方法包装成promise风格
const { promisify } = require("util");

// figlet可以在命令行输出类似logo的海报,用于打印欢迎页面,是一个异步过程
const figlet = promisify(require("figlet"));
// 清屏
const clear = require("clear");
// chalk可以修改命令行输出的字符颜色
const chalk = require("chalk");

const log = (content) => console.log(chalk.green(content));

module.exports = async (name) => {
  clear();
  const welcomeContent = await figlet(`mcli Welcome`);
  log(welcomeContent);
};

修改/bin/mcli.js中定义的命令mcli init <name>,将该命令的执行内容修改为

program
  .command("init <name>")
  .description("init project")
  .action(require("../lib/init"));

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-12crWFxx-1627119294649)(/Users/xiongweiliu/Library/Application Support/typora-user-images/image-20210721220445086.png)]

下载项目模板

本次下载的项目基于vue实现,主要功能点有:登陆/注册、token校验、列表/分页、点赞/点踩、个人中心上传头像,修改密码。
项目需要配置后端服务项目共同使用:https://github.com/littleluckly/vueDemoBackend.git

新建/lib/download.js

这一步主要涉及到如下知识点:

  • download-git-repo库从github下载项目模板
  • ora展示下载等待loading效果
const { promisify } = require("util");

module.exports.clone = async function (repo, dest) {
  const download = promisify(require("download-git-repo"));
  // 下载项目模板过程中展示loading
  const ora = require("ora");
  const process = ora(`下载ing......${repo}`);
  process.start();
  await download(repo, dest);
  process.succeed();
};

再次修改/lib/init.js内容,引入模板下载代码

module.exports = async (name) => {
  clear();
  const welcomeContent = await figlet(`mcli Welcome`);
  log(welcomeContent);

  // 下载项目模板
  const { clone } = require("./download");
  // 利用download-git-repo库下载项目,地址要求做一定的修改
  // 如下载的是http://github.com/littleluckly/vueDemo,则改成github:littleluckly/vueDemo
  // 众所周知的原因,github仓库下载过程可能很慢,要多试几次
  const repoName = "github:littleluckly/vueDemo"; 
  log("创建项目:");
  clone(repoName, name);
};
安装项目依赖

前两步已经构建好了一个可用的命令了,已经通过运行mcli init <name>在本地创建了一个项目模板,为了有一个更好的体验,不仅可以创建一个项目模板,还希望能够自动安装该模板的依赖

这一步主要涉及到如下知识点

  • 子进程child_processspawn方法开启子进程,下载依赖。

    参考https://blog.csdn.net/chy555chy/article/details/52556318

    spawn使用方法:http://nodejs.cn/api/child_process.html#child_process_child_process_spawn_command_args_options

  • 通过流Stream将子进程下载的依赖导入到主进程项目中

/lib/init.js中定义开启子进程的方法

// node自带的工具库util
// promisify可以将普通的方法包装成promise风格
const { promisify } = require("util");

// figlet可以在命令行输出类似logo的海报,用于打印欢迎页面,是一个异步过程
const figlet = promisify(require("figlet"));
// 清屏
const clear = require("clear");
// chalk可以修改命令行输出的字符颜色
const chalk = require("chalk");
// 载项目模板
const { clone } = require("./download");

const log = (content) => console.log(chalk.green(content));

// 开启子进程
const spawn = async (...args) => {
  const { spawn } = require("child_process");
  return new Promise((resolve) => {
    const proc = spawn(...args);
    // spwan开启的子进程返回两个标准输出 stdout 和 stderr 的流对象
    // 通过管道将pipe将子进程的流对象导入到主进程process
    proc.stdout.pipe(process.stdout);
    proc.stderr.pipe(process.stderr);

    proc.on("close", () => {
      resolve();
    });
  });
};

module.exports = async (name) => {
  clear();
  const welcomeContent = await figlet(`mcli Welcome`);
  log(welcomeContent);

  // 下载项目模板
  // 利用download-git-repo库下载项目,地址要求做一定的修改
  // 如下载的是http://github.com/su37josephxia/vue-template,则改成github:su37josephxia/vue-template
  const repoName = "github:su37josephxia/vue-template";
  log("创建项目:");
  clone(repoName, name);

  // 安装依赖
  log("安装依赖");
  await spawn("cnpm", ["install"], { cwd: `./${name}` });
  log(`
  👌安装完成
  To get Start:
  =================
  cd ${name}
  npm run serve
  =================
  `);
};

自动运行项目

安装依赖后,可以借助子进程进一步优化,自动运行项目,并在浏览器打开项目

  • spawn开启子进程运行项目
  • open库打开浏览器
	const open = require('open')
  // 运行项目,打开浏览
  await spawn("npm", ["run", "serve"], { cwd: `./${name}` });
  open("http://192.168.3.5:8080/");
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值