第五步

下面,我们还在bin文件夹中,我们接下来编辑utilscheckDire.js文件。

const fs = require("fs");
const chalk = require("chalk");

module.exports = function (dir, name{
  let isExists = fs.existsSync(dir);
  if (isExists) {
    console.log(
      chalk.red(
        `The ${name} project already exists in  directory. Please try to use another projectName`
      )
    );
    process.exit(1);
  }
};

这个文件没有自定义的部分,你只需要直接用即可。这里我们看到引入两个模块,分别是fs、chalk。Node.js内置的fs模块就是文件系统模块,负责读写文件。chalk模块是美化命令行输出样式,使输出命令不再单调。

我们看到这里导出一个函数,函数有两个参数:分别是dir和name。我们这里先暂且不看这个函数,先只知道需要传两个参数就可以。

第六步

下面我们先分析binindex.js文件,这个文件是命令行工具的入口文件,非常重要。同样,这里不需要自定义,直接用就可以。


#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const commander = require('commander');
const inquirer = require('inquirer');
const checkDire = require('./utils/checkDire.js');
const { exec } = require('child_process');
const { version } = require('../package.json');
const { promptTypeList } = require('./config');

commander
 .version(version, '-v, --version')
 .command('init ')
 .alias('i')
 .description('Enter the project name and initialize the project template')
 .action(async (projectName) => {
  await checkDire(path.join(process.cwd(), projectName), projectName);
  inquirer.prompt(promptTypeList).then((result) => {
   const { url, gitName, val } = result.type;
   console.log(
    'The template type information you selected is as follows:' + val
   );
   console.log('Project initialization copy acquisition...');
   if (!url) {
    console.log(
     chalk.red(`${val} This type is not supported at the moment...`)
    );
    process.exit(1);
   }
   exec('git clone ' + url, function (error, stdout, stderr{
    if (error !== null) {
     console.log(chalk.red(`clone fail,${error}`));
     return;
    }
    fs.rename(gitName, projectName, (err) => {
     if (err) {
      exec('rm -rf ' + gitName, function (err, out{ });
      console.log(
       chalk.red(`The ${projectName} project template already exist`)
      );
     } else {
      if (fs.existsSync(`./${projectName}/.git/config`)) {
       exec('git remote rm origin', { cwd`./${projectName}` });
       console.log(
        chalk.green(
         `✔ The ${projectName} project template successfully create`
        )
       );
      }
     }
    });
   });
  });
 });

commander.parse(process.argv);

我们从头开始看,我们会看到引入了fs、path、chalk、commander、inquirer、child_process。

path 模块提供了用于处理文件和目录的路径的实用工具。

下面指令执行后,改变al寄存器内容的指令是_npm指令_arm指令和thumb指令

commander是完整的 node.js 命令行解决方案,它有很多用法,具体你可以参照Commander中文文档:

https://github.com/tj/commander.js/blob/master/Readme_zh-CN.md

inquirer是通用交互式命令行用户界面的集合。开始通过npm init创建package.json文件的时候就有大量与用户的交互,而现在大多数工程都是通过脚手架来创建的,使用脚手架的时候最明显的就是与命令行的交互,如果想自己做一个脚手架或者在某些时候要与用户进行交互,这个时候就不得不提到inquirer.js了。

child_process模块是nodejs的一个子进程模块,可以用来创建一个子进程,并执行一些任务。比如说就可以直接在js里面调用shell命令。

介绍完引入的模块,然后再介绍下面的代码。你会看到下面的代码大部分都用到了commander的方法。

首先,commander.version(version, ‘-v, –version’),.version()方法可以设置版本,之后就可以使用-v或–version命令查看版本。

通过 .command(‘init

‘) 可以配置命令。这里的意思是初始化你的项目名称,你可以根据自己的需求设置。也可以使用.alias(‘i’)简写初始化配置命令,原来npm init

,现在也可以使用npm i

命令。

.description(‘Enter the project name and initialize the project template’)这行代码中.description方法则是对上面初始化配置项目名的描述。

.action((projectName, cmd) => {…})这行代码中.action方法是定义命令的回调函数,我们发现它使用了async/await这组关键字用来处理异步。首先npm指令,await checkDire(path.join(process.cwd(), projectName), projectName);传入两个参数分别为项目所在的目录、项目名称。我们这里先分析checkDire方法,也就是之前utilscheckDire.js文件内的方法。

module.exports = function (dir, name{
  let isExists = fs.existsSync(dir);
  if (isExists) {
    console.log(
      chalk.red(
        `The ${name} project already exists in  directory. Please try to use another projectName`
      )
    );
    process.exit(1);
  }
};

fs.existsSync(dir)以同步的方法检测目录是否存在。如果目录存在 返回 true ,如果目录不存在 返回false。如果存在了,就执行下面的提示并退出终止进程。

接着,我们又回到binindex.js文件。接着往下执行,到了inquirer.prompt()这个方法,这个方法的作用主要是启动提示界面(查询会话),第一个参数是包含问题对象的问题(数组)(使用反应式接口,还可以传递一个Rx.Observable实例),这里我们传入的是configindex.js文件中的promptTypeList属性,它是一个数组。

 promptTypeList: [
  {
   type'list',
   message'Please select the template type to pull:',
   name'type',
   choices: [
    {
     name'strview-app',
     value: {
      url'https://github.com/maomincoding/strview-app.git',
      gitName'strview-app',
      val'strview-app',
     },
    },
   ],
  },
 ],

inquirer.prompt()这个方法返回一个Promise对象,所以这里可以then()方法来获取返回的数据。然后我们通过解构来分别获取到url、gitName、val这三个属性值。

const { url, gitName, val } = result.type;

然后,下面就是输出命令以及执行命令的环节了。我分为两部分来分析剩余代码,第一部分如下:


console.log('The template type information you selected is as follows:' + val);
console.log('Project initialization copy acquisition...');

if (!url) {
 console.log(chalk.red(`${val} This type is not supported at the moment...`));
 process.exit(1);
}

我们这里有一个判断语句,就是判断远程仓库地址是否是假值,如果是假值的话,就执行提示并退出终止进程。

接着,我们分析第二部分:

exec('git clone ' + url, function (error, stdout, stderr{
 if (error !== null) {
  console.log(chalk.red(`clone fail,${error}`));
  return;
 }
 fs.rename(gitName, projectName, (err) => {
  if (err) {
   exec('rm -rf ' + gitName, function (err, out{ });
   console.log(chalk.red(`The ${projectName} project template already exist`));
  } else {
   if (fs.existsSync(`./${projectName}/.git/config`)) {
    exec('git remote rm origin', { cwd`./${projectName}` });
    console.log(
     chalk.green(`✔ The ${projectName} project template successfully create`)
    );
   }
   }
 });
}

这部分主要是执行命令,也是最关键的部分。这部分首先使用了exec()方法,第一个参数是要执行的命令,第二个参数是回调函数。

首先,我们执行exec(‘git clone ‘ + url)来下载远程项目,接着我们进入回调函数,如果有错误,就输出提示并退出。否则,将使用fs.rename()方法将文件重命名。因为我们下载的远程仓库名不一定跟我们初始化配置的名字一样。

如果错误,就删除远程项目工程目录。否则,就判断./${projectName}/.git/config文件是否存在,如果存在就执行exec(‘git remote rm origin’, { cwd:./${projectName}});命令删除远程仓库地址。这是因为需要自定义配置仓库地址,而不是直接使用下载的仓库地址。最后,提示创建成功。

最后一行。commander.parse(process.argv);这行代码中.parse()的第一个参数是要解析的字符串数组,也可以省略参数而使用process.argv。指明,按 node 约定。

第七步

到了这一步,所有配置文件都配置完成了。如果你想开源的话,你可以参照线上自己生成一个LICENSE文件。这个文件是软件许可证,可以去github去自动生成这个文件。

最后,我们就要发布我们这个命令行工具了。注意,在发布之前,需要改一下你的版本号。 如之前是1.0.0,现在可以改成2.0.0。具体这三个数字怎么定义npm指令,也有说法。第一部分为主版本号,变化了表示有了一个不兼容上个版本的大更改。第二部分为次版本号,变化了表示增加了新功能,并且可以向后兼容。第三部分为修订版本号,变化了表示有bug修复,并且可以向后兼容。

npm publish

发布成功。

第八步

这里以strview-cli为例。

你可以全局安装你的脚手架。

npm i strview-cli -g

下面指令执行后,改变al寄存器内容的指令是_npm指令_arm指令和thumb指令

安装完成之后,你可以查看版本。

strview-cli -v

最后,就是初始化项目了,

是自定义项目名称。

strview-cli init 

or

strview-cli i 

结语

谢谢阅读,希望没有耽误你的时间。

你可以自己封装一个常用的项目工程,可以通过这种方式来初始化你的项目。这样,才会显得有逼格!!!哈哈哈~

关于作者

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: muyang-0410