preface

Because I was learning webpack before, I made a simple scaffold to facilitate my own development scaffolding or other things can be hot updated. Because every time you have to copy the scaffolding and use it as a basis for development, it’s a little bit annoying. So why not download it directly from the command line?

As the successor of the socialist front, of course, it is js with JS ah. So the NPM command line tool is here to fuck you!

Initialize the project

Create a new NPM project. I’m going to call it daily_template_cli. The goal is not only to download the webPack template above, but also to download all the other miscellaneous things you normally use.

Run NPM init in the project directory to generate package.json files. Fill in whatever you want. This is my 👇

{"name": "daily_template_cli", "version": "1.0.0", "description": "for download usually used template", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "lishang", "license": "ISC" }Copy the code

Define a simple command

To define the command we need a field called bin. This field corresponds to an object, key is our corresponding command and value is our corresponding file. Define a daily_template_cli command here.

{"name": "daily_template_cli", "version": "1.0.0", "description": "for download usually used template", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "bin": { "daily_template_cli": "index.js" }, "author": "lishang", "license": "ISC" }Copy the code

The corresponding file is set to index.js. We’ll create a new index.js file in the root directory and write the general start declaration for program learning.

// index.js #! /usr/bin/env node console.log('hello world! ')Copy the code

Note: The first line must add a script specifying the runtime environment (#! The/usr/bin/env node)!!!!!!

release

In order for our commands to work, we must publish this simple NPM package to NPM and install it globally. First check our warehouse address. Most of the time, we use the mirror address of Taobao, which we cannot publish. We need to change the address to the official address of NPM.

Run the following command on the CLI

npm config set registry https://registry.npmjs.org/
Copy the code

Then is the NPM release process, this does not need too much to say, you can Google or Baidu.

After a successful release, it looks like the following

Next, install it globally

npm install daily_template_cli -g
Copy the code

Type daily_template_cli on the command line to see hello World

Now that you have learned 1+1, please solve the $%$@%$#$problem. Let’s start writing our template download tool.

Pre show

If we change something, we have to publish it once, which will be very troublesome. Fortunately, NPM also considers this problem, and we can use NPM link to solve this problem.

Running NPM Link under our project creates a mapping that maps our development environment globally, so we don’t have to release hard after making local changes. NPM link usage and details are not discussed here, if you are interested, you can refer to this

Portal one

The official documentation

Option option

We use Commander to develop the command line. The official documentation

npm install commander
Copy the code

define-vOption to get the version number

Define an option with option that lets us get the version number with -v, –version

Modify the entry file index.js as follows

#! /usr/bin/env node const { program } = require('commander'); -v --verson program.option('-v, --version', 'get project version'); Parse (process.argv); // Get option const options = program.opts(); if (options.version) { let info = require('./package.json'); console.log(info.version); }Copy the code

To explain the code above, first we introduce the global object Program. According to the official documentation, there are several ways to introduce the COMMANDER object. Since the project is not too complex, you can simply introduce the global object Program.

We then define the command -v, –version. Here we use the option method. The commands defined in option are also called options, and we can give multiple names to an option, such as -v, –version. This option can be triggered later with either daily_template_cli -v or daily_template_cli –version.

By the way

— Can mark the end of the option, subsequent parameters are not interpreted by the command

For example, -v, –version, -ww, the -ww command is not recognized.

Parse (process.argv); // Get option const options = program.opts();Copy the code

The above two sentences are the parsed parameters and the options obtained after parsing. If we enter a command that carries an option, the corresponding key in the options obtained will be true. The following figure

To achieve the goal we started with, instead of using option, we will use command, also called command.

The command command

We can add commands by using command. The most obvious difference between command and option is that the operation defined by option is triggered by -xxx or — XXX, whereas command does not have a – or — prefix.

Dailiy_template_cli -v // This is the option option daily_template_cli init // this is the commandCopy the code

To define ainitThe command

In COMMANDER, commands can be used in a variety of ways, which is not explained here. If you are interested, please refer to the above documentation. In this case, commands are used as independent executable subcommands (official description). From my shallow experience, I prefer to call it the separation of commands into separate submodules.

Create an init.js file

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

function init() {
    console.log('install template');
} 

init();
Copy the code

Register the command in the index.js file

#! /usr/bin/env node const { program } = require('commander'); -v --verson program.option('-v, --version, -ww', 'get project version'); Program.mand ('init', 'download template', {executableFile: 'init'}); // Register init command and specify init.js file to handle program.mand ('init', 'download template', {executableFile: 'init'}); Parse (process.argv); const options = program.opts(); if (options.version) { let info = require('./package.json'); console.log(info.version); }Copy the code

And then duang!!

Command A command can take parameters. Let’s revamp our init command. Define a parameter filename, projectName

The init command above is modified as follows

program.command('init <projectName>', 'download template', { executableFile: 'init'}); 
Copy the code

Then in init.js

const { program } = require('commander'); program.parse(process.argv); Const args = program.args; Basic_cli init testDemo args is ['testDemo'] function init() {console.log('init', args)} init();Copy the code

The next step is to pull the template.

Download a Git template

Two NPM packages are introduced here

Download-git-repo Git download tool

Ora displays the loading effect

The main thing here is to modify the init.js file

const { program } = require('commander'); const { promisify } = require('util'); // util.promisify (node8) convert a callback method to a promise-return method const download = promisify(require('download-git-repo')); const ora = require('ora'); // Template address This address is on behalf of github. The main branch of the Daily_templates repository under JustDoIt521. const BASE_URL = 'github:JustDoIt521/daily_templates#main'; program.parse(process.argv); const args = program.args; Basic_cli init testDemo args is ['testDemo'] function init(projectName) { cloneTemplate(projectName); } async function cloneTemplate(projectName) { const processing = ora('clone is starting... '); processing.start(); try { await download(BASE_URL, projectName, {clone: false}); processing.succeed('success'); } catch(e) { processing.fail('fail'); } } init(... args);Copy the code

To summarize, here we parse the parameters through program.parse and fetch them through args. After obtaining the parameters, execute the init method and download the template.

And here’s the miracle:

You can see the results of our download here!!

Pay attention to

There is one thing to note. It is possible that you will get an error when you finish typing. The initial estimate is likely to be based on the Version of Node (since one failed on both my computers). Later unified Versions of Node will do. I’m currently using node version 14.16.0.

In addition If we use gihub directly copied down the address Such as https://github.com/JustDoIt521/daily_templates.git will have 128 error, so I adopted the above format.

The project address

Scaffold address