Complete steps for developing cli with node. js

  • 2021-10-16 00:40:16
  • OfStack

Introduction to CLI

Command line interface (English: command-line interface, abbreviation: CLI) is the most widely used user interface before the popularity of graphical user interface. It usually does not support mouse. Users input instructions through keyboard, and computers execute them after receiving instructions.

At present, CLI is a commonly used tool in front-end development. The three front-end frameworks Vue, React and Angular all have corresponding CLI, including Webpack, the most popular front-end engineering packaging tool, and webpack-cli.

In modern front-end development, CLI improves the development efficiency. Let the corresponding front-end developers avoid a lot of repetitive operations and save a lot of time. The functions that CLI can accomplish include but are not limited to initializing and generating corresponding project templates, executing specific script files, and creating new modules in the project. Here's how front-end engineers use node. js to complete an CLI.

Create a project

Open the terminal and create the directory of moka-cli


mkdir moka-cli

Enter the directory and initialize the project


cd moka-cli
npm init -y

Create a new bin directory under the root directory, and create a new index. js file. At this time, the directory structure is as follows


|-- moka-cli
 |-- package.json
 |-- bin
  |-- index.js

Three libraries, commander, inquirer and chalk, are needed to develop cli


npm install commander inquirer chalk --save

Modify package. json file to use es moudle and add moka command


package.json

{
 "name": "moka-cli",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
+ "type": "module",
+ "bin": {
+ "moka": "./bin/index.js"
+ },
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1"
 },
 "keywords": [],
 "author": "",
 "license": "ISC",
 "dependencies": {
 "chalk": "^4.1.0",
 "commander": "^6.2.1",
 "inquirer": "^7.3.3"
 }
}

Next, you need to program in/bin/index. js, adding the following code on line 1, which tells the system to execute this file with node.


#!/usr/bin/env node

Add the following code


#!/usr/bin/env node

console.log('moka-cli run!')

Then install the project globally under the project root directory


npm install -g

Here, a simple CLI is completed. You can open the terminal, enter moka in any directory, and the console will print out the corresponding message.


$ moka
moka-cli run!

Introduction of the third square library

moka-cli wants to achieve the ability to create front-end development templates by using the moka command to create an vue or react project.

First, let's introduce the libraries used to the third party under 1

commander

Document address

The library used to realize commands will be used to realize create commands in moka-cli, and the following command line will be used to create a project of vue-demo


moka create vue vue-demo

inquirer

Document address

Realize user and terminal interaction library, when using create instruction in moka-cli, it will ask whether to overwrite existing items


cd moka-cli
npm init -y
0

chalk

Document address

Multiple colors of text and background can be displayed in the terminal interface

Core functions

Create the actions and templates directories in the root directory with the following directory structure


cd moka-cli
npm init -y
1

templats below used to store through CLI to generate the project template, here first casually create a few files show 1.

Modification/bin/index. js file


cd moka-cli
npm init -y
2

Modification of./actions/create. js file


import fs from 'fs';
import path from 'path';
import chalk from 'chalk';
import inquirer from 'inquirer';

import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const TEMPLATES = ['vue', 'react'];

const targetPath = process.cwd();

function createTemplate(template, name) {
 const templatePath = path.join(__dirname, '../', `templates/${template}`);

 function readAndCopyFile(parentPath, tempPath) {
 let files = fs.readdirSync(parentPath);

 files.forEach((file) => {
  let curPath = `${parentPath}/${file}`;
  let stat = fs.statSync(curPath);
  let filePath = `${targetPath}/${tempPath}/${file}`;
  if (stat.isDirectory()) {
  fs.mkdirSync(filePath);
  readAndCopyFile(`${parentPath}/${file}`, `${tempPath}/${file}`);
  } else {
  const contents = fs.readFileSync(curPath, 'utf8');
  fs.writeFileSync(filePath, contents, 'utf8');
  }
 });
 }

 readAndCopyFile(templatePath, name);
}

function deleteTemplate(path) {
 if (fs.existsSync(path)) {
 fs.readdirSync(path).forEach(function (file, index) {
  var curPath = path + '/' + file;
  if (fs.lstatSync(curPath).isDirectory()) {
  // recurse
  deleteTemplate(curPath);
  } else {
  // delete file
  fs.unlinkSync(curPath);
  }
 });
 fs.rmdirSync(path);
 }
}

export default function create(template, name) {
 if (!TEMPLATES.includes(template)) {
 console.log(chalk.red(`No ${template} Template`));
 return;
 }

 const projectPath = path.resolve(targetPath, name);

 if (fs.existsSync(projectPath)) {
 inquirer
  .prompt([
  {
   name: 'template-overwrite',
   type: 'confirm',
   message: `Template named ${name} is already existed, are you sure to overwrite?`,
   validate: function (input) {
   if (input.lowerCase !== 'y' && input.lowerCase !== 'n') {
    return 'Please input y/n !';
   } else {
    return true;
   }
   },
  },
  ])
  .then((answers) => {
  //  If you determine to override 
  if (answers['template-overwrite']) {
   //  Delete Folder 
   deleteTemplate(projectPath);
   console.log(chalk.yellow(`Template already existed , removing!`));
   // Create a new module folder 
   fs.mkdirSync(projectPath);
   createTemplate(template, name);
   console.log(
   chalk.green(`${template} template has been created successfully!`)
   );
  }
  })
  .catch((err) => {
  console.log(chalk.red(err));
  });
 } else {
 fs.mkdirSync(projectPath);
 createTemplate(template, name);
 console.log(
  chalk.green(`${template} template has been created successfully!`)
 );
 }
}

Finally, run the following command in the project root directory to reinstall moka-cli under 1


cd moka-cli
npm init -y
4

Find a random path and run moka create < template > [name] Command to build the project


cd moka-cli
npm init -y
5

The effect is as follows: 1 folder of react-demo will be generated under this directory, in which all of the contents under templates/react in the project of moka-cli will be stored


cd moka-cli
npm init -y
6

If you continue to create a project with the same name in this directory, you will be prompted whether to overwrite it. Enter y and continue to execute


cd moka-cli
npm init -y
7

The core logic of create command is to copy the files under/templates through fs module of node, and then put them in the specified path. The specific implementation can be achieved directly by looking at the code.

Summarize

CLI is an important tool to prompt the efficiency of front-end development. If there is a long-term maintenance project, it is a good choice to develop an CLI to complete some repetitive work.

moka-cli Haven't uploaded github yet. I will add the project address in the article after completing the project template under 1/templates.


Related articles: