The purpose of,
The initial flow of a traditional front-end project looks like this:
As you can see, the traditional initialization steps take a lot of time. Moreover, in the case of manual operation, there is always the situation of leakage. This shortcoming can be fatal. There are even instances where the project repository address is not updated, resulting in the submission of code to the old repository, which is very embarrassing… Based on these situations, the purpose of writing a command line tool (CLI) is clear:
- For the initialization of new projects
- Using a tool for initialization can save time during the initial stage of a project
- Avoid leakage
- Eliminate the problem of not updating the project repository address
Here is a schematic of the new process:
Second, automated process analysis
Here is the automation flowchart:
Two important things can be learned from the flowchart:
- Configuration information
- Template file
The role of the command line tool is to fuse the two information and provide an interactive platform for users.
3. Tool preparation
3.1 Configuring The Information Tool
You need to interact with users to obtain configuration information. Programmers generally use terminal input commands for project operations. So, two tools have been chosen for support.
- commander
A command line completion solution that borrows from Ruby Commander concepts
Commander can accept arguments passed from the command line
Example:
Npg-cli --help ♫ ♫ ♪ -♫ Npm-package-cli ♫ ♫ ♪ -♫ Usage: NPg-CLI [options] Options: -V, --version output the version number -h, --help output usage information run testcli and edit the setting.Copy the code
- inquirer
A collection of commonly used interactive command-line user interfaces.
The Inquirer uses interrogative statements to interact with the user and receive parameters
Example:
Npg-cli ♫ ♫ Prompts ♪ (13) ♫ npm-package-cli ♫ ♫ Lead them to complete the project configuration.? project nametest? Version 1.0.0? descriptionCopy the code
3.2 Template Information Tool
Front-end JavaScript template engines, such as EJS, Jade, etc. Based on the parameters passed in, the template tag can be replaced to generate HTML.
If you treat all project files, regardless of file name extensions, as EJS templates, you can use EJS syntax in the file content. Then replace the file based on the configuration information to generate a new file.
In fact, the industry has developed mature tools based on this idea.
- mem-fs
Mem-fs reads files and stores them in memory.
- mem-fs-editor
Mem-fs-editor is a compilation of in-memory file information using EJS syntax. Finally, the commit method is called to output the final file.
3.3 Message Tool
In addition to console.log, you can also use chalk, which is more colorful. In this way, you can output more intuitive and friendly prompts.
3.4 File Operations
File operation, with industry mature ShellJS. Using ShellJS, you can simplify the following steps in a project:
- Some project files, do not need to modify, only direct copy. You can use
shelljs.copySync
Synchronously generated. - Some folders, which need to be built in advance, can be used
shelljs.mkdir
To create a
Four, implementation,
The following will be divided and explained according to the creation process of my open source project — NPM-package-CLI.
4.1 the initialization
Create project folder npm-package-cli and run NPM init in this folder to generate package.json. The project structure is as follows:
npm-package-cli
|-- package.json
Copy the code
4.2 Generating global Commands
The global directive to be generated here is NPG – CLI.
4.2.1 Creating an Execution File
Create folder bin and create a shell script file named CLI in the folder (note that the file name extension cannot be added). The clishell script file contains the following contents:
#! /usr/bin/env node
console.log('hello world');
Copy the code
Among them, the #! /usr/bin/env node tells the compiler to run code as node.
Add the following to package.json:
"bin": {
"npg-cli": "bin/cli"
}
Copy the code
At this point, the project structure is as follows:
npm-package-cli
|-- bin
|-- cli
|-- package.json
Copy the code
4.2.2 Link instructions to global
There are two ways to link directives:
npm link
npm install -g
For the two methods to take effect, you need to run them in the npm-package-CLI folder. NPG – CLI command is used to point to the global bin file to achieve soft chain.
Holdings run
Run commands in any folder:
npg-cli
#The output
hello world
Copy the code
At this point, a basic instruction is completed, followed by the elaboration of the work content of the instruction.
4.3 Initializing operation Creation
Creation is meant to consolidate all operations and provide an interface to the command file CLI. Creation is structured as follows:
class Creation{
constructor() {// code
}
do() {// code
}
// other function
}
Copy the code
Where the do method is exposed to a script file cli call.
The Creation class is placed in SRC /index.js.
At this point, the project structure is as follows:
npm-package-cli
|-- bin
|-- cli
|-- src
|-- index.js
|-- package.json
Copy the code
4.4 to modifycli
file
#! /usr/bin/env nodeconst Creator = require('.. /src/index.js'); const project = new Creator(); project.do();Copy the code
In this way, as long as the implementation of a good DO method, you can complete the NPG – CLI command run.
4.5 Reading Cli Parameters
To implement nPG-CLI –help, use the tool COMMANDER mentioned above. Create a SRC /command. Js file with the following contents:
const commander = require('commander');
const chalk = require('chalk');
const packageJson = require('.. /package.json');
const log = console.log;
function initCommand(){
commander.version(packageJson.version)
.on('--help', ()=>{
log(chalk.green(' run testcli and edit the setting.'));
})
.parse(process.argv);
}
module.exports = initCommand;
Copy the code
At this point, the project structure is as follows:
npm-package-cli
|-- bin
|-- cli
|-- src
|-- command.js
|-- index.js
|-- package.json
Copy the code
Then execute initCommand() in the creation.do method to take effect.
// src/index.js Creation
const initCommand = require('./command');
class Creation{
// other code
do(){ initCommand(); }}Copy the code
At this point, run the NPG -cli –help command, you can see:
Usage: npg-cli [options]
Options:
-V, --version output the version number
-h, --help output usage information
run testcli and edit the setting.
Copy the code
4.6 Obtaining User Input Configuration Information
To retrieve information entered by the user, use the tool Inquirer. Create a SRC /setting.js file with the following contents:
const inquirer = require('inquirer');
const fse = require('fs-extra');
function initSetting(){
let prompt = [
{
type: 'input'.name: 'projectName'.message: 'project name',
validate(input){
if(! input){return 'project name is required.'
}
if(fse.existsSync(input)){
return 'project name of folder is exist.'
}
return true; }},// other prompt
];
return inquirer.prompt(prompt);
}
module.exports = initSetting;
Copy the code
At this point, the project structure is as follows:
npm-package-cli
|-- bin
|-- cli
|-- src
|-- command.js
|-- index.js
|-- setting.js
|-- package.json
Copy the code
Then execute initSetting() in creation.do to take effect.
// src/index.js Creation
const initCommand = require('./command');
const initSetting = require('./setting');
class Creation{
// other code
do(){
initCommand();
initSetting().then(setting= > {
// After user input, json data setting of all input information will be obtained}); }}Copy the code
Here, the Inquirer. Prompt method returns a Promise object after loading the questions to collect. After the collection is complete, the configuration information is retrieved in the THEN method for the next step of template replacement.
4.7 Replacing Template Files
To replace the template file, use the tools mem-fs and mem-fs-editor. File operation, to use the tool shellJS.
Create a new SRC /output.js file with the following contents:
const chalk = require('chalk');
const fse = require('fs-extra');
const path = require('path');
const log = console.log;
function output(creation){
return new Promise((resolve, reject) = >{
// Get the configuration information
const setting = creation._setting;
const {
projectName
} = setting;
// Get the folder where the current command line execution environment resides
const cwd = process.cwd();
// Initialize the folder path
const projectPath = path.join(cwd, projectName);
const projectResolve = getProjectResolve(projectPath);
// Create a project folder
fse.mkdirSync(projectPath);
// Copy the folder
creation.copy('src', projectResolve('src'));
// Replace the file content based on the configuration information
creation.copyTpl('package.json', projectResolve('package.json'), setting);
// Output files in memory to hard disk
creation._mfs.commit((a)= > {
resolve();
});
});
}
module.exports = output;
Copy the code
The output method does the following:
- New project folder
- Read the template file and replace it according to the configuration information
mem-fs-editor
thecopyTpl
Methods) - Copy other files
- Output the final file to hard disk
The most important step here is to execute the commit method of mem-fs-editor after calling the mem-fs-editor method to output the files in memory to the hard disk.
In creation.do, the output method is called to output the new project file. Open the SRC /index.js file and add the following method to the file:
// src/index.js Creation
const initCommand = require('./command');
const initSetting = require('./setting');
const output = require('./output');
class Creation{
// other code
do(){
initCommand();
initSetting().then(setting= > {
// After user input, json data setting of all input information will be obtained
this._setting = Object.assign({}, this._setting, setting);
// Output file
output(this).then(res= > {
// Project output completed}); }); }}Copy the code
4.8 Stage summary
The process of automatically initializing a project is as follows:
- Reading user Configuration
- Reading a template file
- According to the configuration, the template file is compiled and the final file is output
The command line tool is an effective integration of these three points, linking them into a standardized process.
Five, the release of NPM package attention points
5.1 How to Install Dependency Packages
All third-party toolkits used in command line tools need to be installed in –save mode. Json is shown in the Dependencies field:
"dependencies": {
"chalk": "^" 2.4.2."commander": "^ 3.0.0"."fs-extra": "^ 8.1.0"."inquirer": "^ 6.5.0"."mem-fs": "^ 1.1.3." "."mem-fs-editor": "^ 6.0.0"."shelljs": "^ 0.8.3"
},
Copy the code
This way, other users will automatically install these dependencies when they install your published CLI tools.
5.2 .gitignore
file
NPM officially removes. Gitignore files by default, regardless of how you declare them. Gitignore files need to publish. The solution is to change the name of. Gitignore to gitignore. When using the CLI tool, change the file name back. Example:
creation.copy('gitignore', projectResolve('.gitignore'));
Copy the code
Vi. Open source project
NPM -package- CLI, which I created, is a CLI tool specifically used to generate personal NPM package projects. The generated project includes the following function points:
- Support TypeScrpt
- Mocha + CHAI automated testing with support for writing test cases in TypeScript
- Support test coverage
coverage
- Support for ESLint, including lint checking for TypeScript
- Git commit Specifications are committed
- Git version is automatically labeled (standard-version) and updated
CHANGELOG.md
- The output NPM package supports various module specifications (AMD, CMD, CommonJS, ESModule)
CLI tool installation method:
npm install -g npm-package-cli
Copy the code
Open source repository address: github.com/wall-wxk/np… If it is helpful to you, please give me a Star. Yours is definitely the motivation for me to move forward
Friends who like my articles can follow me in the following ways:
- “Star” or “watch” my GitHub blog
- RSS subscribe to my personal blog:Mr. Wang’s base