Scaffolding is often used in daily development, such as vue-CLI, react-create-app, angular-CLI, etc. Scaffolding is a quick way to create projects and build a base development environment. This article will take you to understand the working principle of scaffolding!

This article is developed in the MAC environment, the file path is different, copy the code in this article, may not run normally, please judge for yourself. Which [command] is used to check the disk address of the command.

Nodejs executes the JS file

Create a new test.js file:

console.log('This is a test! ');
Copy the code

We can execute this file with Node test.js:

As we know, a JS file can be executed by Node, but not by itself, because it does not have executable permissions. Chmod 777 grants executable permissions to js files:

However, test.js cannot be executed directly at this point because the JS file requires a parser (Node) to execute. Py files require a Python parser.

We can add #! To the test.js file header. /usr/bin/env node

#! /usr/bin/env node
console.log('This is a test! ');
Copy the code

At this point we can execute the js file with./test.js:

Why is that?

#! Shebang

#! This symbol is called shebang in Linux or Unix. On unix-like operating systems, a normal file with #! In many scripts, # is used to start a comment. If you run it as an execution script, this line is a comment, which is not useful, but just a sign that the file can be run as a script.

#! /usr/bin/env node indicates that the file is executed using node, which is derived from the /usr/bin/env environment variable.

Execute the JS file by command

How can we implement a simple command to execute the test.js file? Let’s take a look at how vue-CLI is implemented through VUE.

  • which vue
  • cd /usr/local/bin
  • ll

You can see that the vue command is actually a soft link (shortcut) that points to… /.. / Users/finget/config/yarn/global/node_modules/bin/vue and this address is also soft links, it finally points to @ vue/cli/bin/vue. Js

Js file. Similarly, we can create a soft link to test.js and execute it by command.

  • CD/Users/finget/NVM/versions/node/v12.16.1 / bin
  • ln -s /Users/finget/Desktop/test.js finget

We set up a finget command to execute test.js: finget

The finget command is executed as follows:

Write our first command init

Get the command

The process.argv property returns an array containing the command-line arguments passed in when the Node.js process is started. The first element will be process.execPath. The second element will be the path to the JavaScript file being executed. The remaining elements will be any other command line arguments.

const argv = require('process').argv;
console.log(argv);

const command = argv[2];
console.log(command);
Copy the code

Get the options

const options = argv.slice(3)
console.log(options); // [ '--name', 'test' ]
let [option, param] = []
if(options.length) {
  [option, param] = options;
  option = option.replace(The '-'.' ')
  console.log(option, param); // name test
}
Copy the code

So our first command init is done, and we can get the command and the parameter options, and we can do anything else, and that’s the basic idea of scaffolding.

In actual scaffolding development, such primitive parameter reading methods are not commonly used. Yargs and COMMANDER can quickly build a basic scaffolding framework.

Yargs extra reading

What’s Yargs?

Yargs helps you build interactive command line tools by parsing arguments and generating an elegant user interface.

Initialize thetest-cli

To prepare for later articles, let’s create a new test-CLI project.

mkdir test-cli
cd test-cli
mkdir bin
npm init -y
cd bin
touch index.js
vim index.js
Copy the code
// bin/index.js
#!/usr/bin/env node

console.log('test-cli')
Copy the code

Above we introduced the soft link through the way to implement the custom command to execute js files, now we can also implement through NPM link.

// package.json
"bin": {
  "test-cli": "bin/index.js"
}
Copy the code
cd test-cli

npm link
Copy the code

Test-cli is used as the name of the command, and bin/index.js is used as the entry file of the command.

yargs

yarn add yargs
Copy the code
// test-cli/bin/index.js
const yargs = require('yargs');
const {hideBin} = require('yargs/helpers');

console.log(hideBin(process.argv));
// There are --help and --version commands by default
const arg = hideBin(process.argv);
yargs(arg)
  .argv;
Copy the code

This sets up a basic scaffolding command, –help and –version, which Yargs implements.

Usage Description

yargs(arg)
  .usage("Usage: $0 <command> [options]")
  .strict()
  .argv;
Copy the code

DemandCommand Indicates the number of commands to be entered

yargs(arg)
  .usage("Usage: $0 <command> [options]")
  .demandCommand(1."A command is required. Pass --help to see all available commands and options.")
Copy the code

Alias alias

yargs(arg)
  .usage("Usage: $0 <command> [options]")
  .demandCommand(1."A command is required. Pass --help to see all available commands and options.")
  .strict()
  .alias("h"."help")
  .alias("v"."version")
Copy the code

Epilog is injected at the footer

yargs(arg)
  .usage("Usage: $0 <command> [options]")
  .demandCommand(1."A command is required. Pass --help to see all available commands and options.")
  .strict()
  .alias("h"."help")
  .alias("v"."version")
  .epilog('This is my CLI')
Copy the code

options

const cli = yargs(argv);
cli
  .options({
    debug: {
      type: 'boolean'.describe: 'Bootstrap debug mode'.alias: 'd'}})Copy the code

Group, a group

cli
  .group(['group1'].'this is group1')
  .group(['group2'].'this is group2')
Copy the code

command

  • Parameter 1: indicates the format of command
  • Parameter 2: Description of command describe
  • Parameter 3: Builder function, executed before command
  • Parameter 4: Handler function, the actual operation that command does
  • Parameter 5: aliases alias
cli
  .command('init [name]'.'Do init a project'.(yargs) = > {
    yargs
      .option('name', {
        type: 'string'.describe: 'name of a project',}}),(argv) = > {
    console.log(argv)
  })
Copy the code

recommendCommands

cli
  .usage("Usage: $0 <command> [options]")
  .demandCommand(1."A command is required. Pass --help to see all available commands and options.")
  .strict()
  .recommendCommands()
Copy the code

Incorrect command typing will prompt you:

parse

const pkg = require(".. /package.json");
const context = {
  myCliVersion: pkg.version,
};

cli
 .parse(argv, context);
Copy the code

The last

Welcome to exchange, write the wrong place, please correct!

Warehouse address: gitee.com/finget/test…

[Scaffolding for our small team — download templates through scaffolding]