Node.js-based CLI tools have emerged in a number of ways, especially the scaffolding tools that used to be the most frequently changed. Pure build tools include Grunt, gulp, Webpack, Parcel and Rullup. Each front-end framework has its own CLI tools, such as create-React-app, vue-CLI and Angular-CLI, as well as integrated solutions such as FIS, JDF, and UMI. However, the application scenario of each team is different, and the above tools may not fully meet the requirements. It is time to develop a customized CLI tool yourself.
The main content
cli
How is the command executed- create
npm
包 - Create an executable file
- About command line arguments
- Operating Environment Check
- Update the inspection
- Test and release
To develop cli tools, you need to know what cli is and how to execute your command-line tools in cli.
cli
How is the command executed
The Command Line Interface (CLI) is a tool or application that interacts with each other through the Command Line. Different operating systems have different built-in CLI:
- unix-like
- bash
- sh
- csh
- zsh
- .
- windows
- cmd.exe
- PowerShell
Typically, a command corresponds to an executable file in the system, such as CD or ls. When a user enters a command to execute on the CLI, the CLI looks for the executable file with the same name in the pre-configured lookup path and runs it. The search PATH is usually stored in an environment variable called PATH.
For example, an OSX system can know its contents with the command $PATH:
$ $PATH
-bash: /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
Copy the code
Let’s see how to create the executable.
createnpm
包
Start by creating an NPM package with the NPM init command:
$ mkdir cli-test
$ cd cli-test
$ npm init -y
Wrote to /cli-test/package.json:
{
"name": "cli-test"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": []."author": ""."license": "ISC"
}
Copy the code
Create an executable file
- in
cli-test
Create a new file in the root directorybin/index.js
#! /usr/bin/env node ...Copy the code
Note the #! On the first line. The/usr/bin/env node, #! /usr/bin/env indicates where to find the parser, and node is the name of the parser (indicating that the file is run by Node.js).
- And in the
package.json
Add a configuration item to:
{
"bin": {
"cli-test": "bin/index.js"}}Copy the code
Specify the cli name as cli-test and the executable file as bin/index.js. When the user installs this module through NPM install, NPM automatically creates an executable file based on the operating system, such as /usr/local/bin/cli-test in OSX and associate it with the executable file.
- for
bin/index.js
Add executable permission (UNIX-like) :
chmod +x bin/index.js
Copy the code
Bin /index.js is also a Node.js module, which can reference other Node.js modules without adding execution permissions:
#! /usr/bin/env node require('.. /cli.js')Copy the code
About command line arguments
Each function is invoked by different commands, and each function receives different parameters. For example, vue-cli is commonly used. You can enter vue on the terminal and press Enter to view all commands supported by vue-CLI and their optional parameters:
$ vue
Usage: vue <command> [options]
Options:
-V, --version output the version number
-h, --help output usage information
Commands:
create [options] <app-name> create a new project powered by vue-cli-service
add [options] <plugin> [pluginOptions] install a plugin and invoke its generator in an already created project
invoke [options] <plugin> [pluginOptions] invoke the generator of a plugin inan already created project inspect [options] [paths...] inspect the webpack configin a project with vue-cli-service
serve [options] [entry] serve a .js or .vue file in development mode with zero config
build [options] [entry] build a .js or .vue file in production mode with zero config
ui [options] start and open the vue-cli ui
init [options] <template> <app-name> generate a project from a remote template (legacy API, requires @vue/cli-init)
config [options] [value] inspect and modify the config
outdated [options] (experimental) check for outdated vue cli service / plugins
upgrade [options] [plugin-name] (experimental) upgrade vue cli service / plugins
info print debugging information about your environment
Run vue <command> --help for detailed usage of given command.
Copy the code
process.argv
In Node.js you can use the process.argv array to get arguments for command line input:
// bin/index.js
console.log(process.argv);
Copy the code
$ cli-test one two=three four
['/usr/local/bin/node'.'/path/to/cli-test'.'one'.'two=three'.'four']
Copy the code
But process.argv doesn’t distinguish commands, parameters, and parameter values, so we need to introduce a third-party yargs-Parser module.
const yArgsParser = require("yargs-parser");
// This is the command
const command = process.argv[2];
console.log(command);
// one
// This is the parameter
const args = yArgsParser(process.argv.slice(3));
console.log(args);
// args is an object:
// { two: 'three', four: true }
Copy the code
Help information
Each command line tool should have a help display function. For example, if you enter vue without any command or parameter (you can also add the parameter -h or –help), the output information is vue-CLI help, which contains all supported commands and optional parameters.
if(! command) {console.log('Show help information');
return; }Copy the code
On the path
When developing command line tools, you need to pay attention to two path information:
- Path to the executable script file
- Current working path of node.js process
The path of the executable script file is the path of the current script file, for example, bin/index.js. You can obtain the value of the path by using __dirname.
// bin/index.js
console.log(__dirname);
Copy the code
$ cli-test
/path/to/bin
Copy the code
This path allows you to read or write files, such as configuration information, caches, etc. that are in the installation path of the command line tool.
The current working path of Node.js is the path where the user runs the command line tool on the terminal. You can obtain the value of this path by running process.cwd().
// bin/index.js
console.log(process.cwd());
Copy the code
$ cd /path/to/test
$ cli-test
/path/to/test
Copy the code
From this path, you can know where the user wants to use the command line tool and read the user-defined configuration file, such as vue configuration file vue.config.js.
commander.js
If you find the above method of processing commands and parameters tedious and want to make a command line tool quickly, you can use the third-party module commander. Js.
Comcommander.js is a complete Node.js command-line solution inspired by Ruby’s Commander. It is well documented and has an official Chinese version, which I won’t go into here.
User behavior interaction
In order to provide a more user-friendly user experience, some interactive behavior feedback functions are usually added, such as task execution waiting prompt, output result highlighting prompt and user input prompt.
Task execution waiting prompt
Ora is a great tool for waiting hints and is easy to use:
const Ora = require("ora");
// Instantiate a spinner
const spinner = new Ora();
// Set up the copy
spinner.text = "Loading";
// Start displaying the wait prompt
spinner.start();
setTimeout(() = > {
// Display a success message and exit spinner
spinner.succeed();
}, 3000);
Copy the code
The output is highlighted
Chalk defines a string-like module in the command line terminal that outputs various types of text messages:
const chalk = require("chalk");
const log = console.log;
// Output has colored text
log(chalk.blue("Hello") + " World" + chalk.red("!"));
// Outputs text with color and background color
log(chalk.blue.bgRed.bold("Hello world!"));
// Multi-segment text output
log(chalk.blue("Hello"."World!"."Foo"."bar"."biz"."baz"));
// Nested styles
log(chalk.red("Hello", chalk.underline.bgBlue("world") + "!"));
// For more styles such as bold, center line, italics, please refer to the official documentation
Copy the code
User input interaction
The Inquirer module integrates the user interaction functions of common command line tools, such as input, Number, Confirm, list, RawList, expand, Checkbox, Password, and Editor.
- Text input
const inquirer = require("inquirer");
(async function () {
const answers = await inquirer.prompt([
{ name: "username".message: `Please enter your username`},]);console.log(answers.username); }) ();Copy the code
- Individual choice
const inquirer = require("inquirer");
(async function () {
const answers = await inquirer.prompt([
{
name: "gender".message: `Please enter your gender`.type: "list".choices: ["male"."female"],},]);console.log(answers.gender); }) ();Copy the code
For more information, please refer to the official documentation: github.com/SBoudrias/I…
Operating Environment Check
Some command line tools need to be installed by a third-party tool or run in a special environment (for example, node.js version v10 or later). Therefore, before running any program, you need to check whether the user’s current operating environment can use the tool properly.
Check the Node.js version
NPM provides for configuring engines in package.json to declare the version of Node.js, or to declare the version of NPM:
{
"engines": {
"node": "> = 10.13.0"."npm": "~ 6.9.0"}}Copy the code
When the user installs this command line tool, NPM checks the current node.js version and warns if it does not meet the requirements. If the engineer-strict parameter is included, NPM reports an error.
Of course, developers can also check this programmatically when running the command line tool, using the third-party module Node-semver:
const semver = require("semver");
const requiredVersion = require(".. /package.json").engines.node;
const nodeVersion = process.version;
if(! semver.satisfies(nodeVersion, requiredVersion)) {console.log("Node.js version must satisfy" + requiredVersion + "To run the tool");
return;
}
Copy the code
Other Environmental Checks
If the tool is dependent on other environments, you can use a similar method of checking, but the method of obtaining the version number of each tool may be slightly different. You can also refer to some sophisticated command-line tools and add a doctor command (such as cli-test doctor) for environment checking.
Update the inspection
Usually an application will not only release a version, but constantly iterative new version, when the NPM package release a new version the user is unable to perceive, so I need every time the user to use this tool, take the initiative to go to check the latest version of the online, if the user USES the version is too old will take the initiative to prompt the user to upgrade.
Getting the version of the current NPM package is easy by reading version from package.json. Access to the latest version number some trouble with online, need to use the node. Js HTTP modules initiate an HTTP request to the http://registry.npmjs.org/ [module name], the result is a json string, This contains the dist-tags. Latest field to get the latest version.
For example, a third-party HTTP request library, AXIos, is used
const axios = require("axios");
module.exports = async (pkgName, currentVersion) => {
const { data, status } = await axios.get(
`http://registry.m.jd.com/${pkgName}`,
{
timeout: 1000});if (status === 200) {
const latest = data["dist-tags"] ["latest"].split(".");
const current = currentVersion.split(".");
if (latest[0] !== current[0]) {
console.log("This module has been upgraded to Mayor");
} else if (latest[1] !== current[1] || latest[2] !== current[2]) {
console.log("This module version has been updated, please upgrade"); }}};Copy the code
Test and release
test
After the command line tool is developed, you need to test whether its function is correct. NPM provides the NPM link command to simulate the installation of local modules, and yarn Link can also be used.
It is common to compile the source code and run through the unit tests in their entirety before releasing. Compilation and unit testing will vary from project to project and will not be covered here. One thing to note is that in case you forget to compile and test your code when publishing, you can configure scripts.prepublish in package.json.
{
"scripts": {
"compile": "run compile"."test": "run test"."prepublish": "npm run compile && npm run test"
}
Copy the code
release
NPM provides dist-tag to mark the current release, which defaults to latest and can be customized. Publish –tag next: NPM publish –tag next: NPM publish –tag next: NPM publish –tag next: NPM publish –tag next NPM install [email protected] or run NPM install cli-test@next to specify the latest version of tag Next to be installed.
How do YOU develop a Node.js command-line (CLI) tool from scratch
The resources
- node.js api
- NPM package management
- yargs-parser
- node-semver
- axios