directory
- The scaffold
- Global command
- Interactive input
- Pull the remote repository code
- To optimize the
- conclusion
1. Scaffolding
Today, the bricks at the construction site were a little hot. I looked up at the sky and thought for half a minute. Then I decided to build a scaffold for the convenience of moving bricks in the future.
Sorry, the wrong one. Here it is:
Many of you have used scaffolding such as vue-CLI, create-React-app, or Angular-CLI. A command line can quickly put up a project framework, say no to slash-and-burn copy and paste, and free up productivity in minutes.
As an aspiring cutout, this fishing artifact must be arranged immediately.
Ok, so the question is: what is scaffolding?
In terms of expression form, scaffolding mainly has the following characteristics:
- A command that can be executed globally;
- Can realize interactive input, such as input project name, select configuration items and so on;
- Automatically pull github or GitLab remote repository code.
Of course, advanced scaffolding can do more than that, but let’s start with the simplest implementation.
2. Global commands
2.1 Basic Principles
Let’s unpack and see how global commands like vue-CLI are implemented. You can use NPM config get prefix to install vUE -cli, for example, C:\Users\ User name \AppData\Roaming\ NPM:
You can see that there are many files with the same name as global commands in this directory, as well as a node_modules folder. Our globally installed dependencies are in node_modules. Go to @vue-cli, this is vue-CLI source package.
The package.json in vue-CLI has this key configuration:
"bin": {
"vue": "bin/vue.js"
},
Copy the code
The bin/vue.js script must end with #! /usr/bin/env node,
When NPM is installed globally, the corresponding executable with the same name is generated based on this configuration.
When we run vue, the system will run vue.js as a Node program.
The NPM link command is provided in the NPM documentation to allow users to generate a global command for custom scaffolding.
NPM Link does two main steps:
- The first is to generate a link file in the node_modules folder of the NPM global installation path. This link file points to the folder where the command is executed, which is our scaffolding source folder.
- Second, generate an executable file with the same name as configuration bin in the NPM global installation path.
So, with NPM link, we can generate a node global command.
NPM link official documentation: docs.npmjs.com/cli/v6/comm…
2.2 Implementation of global Commands
Without further ado, let’s start with a global command.
1) Execute NPM init to initialize a package.json:
2) Add bin configuration to package.json:
"bin": {
"test-cli": "./test.js"
},
Copy the code
3) Add the corresponding execution script file test.js:
#! /usr/bin/env node
console.log("Hello! My CLI!");
Copy the code
4) Execute NPM link in package.json equivalent directory
5) Run the global command test-cli on the console and see the output:
Done!
3. Interactive input
By doing this, the user can execute the global command into our test.js file, and the rest of the functionality is free to play in JS.
The Node community has a large number of third-party modules that allow us to quickly develop and implement the desired functionality.
Inquirier, for one, currently has a 14.5K Star on Github that “aims to be an easy-to-embed and aesthetical-looking command-line tool.” As the name implies, with the Inquirier module, you can interact with the user’s input from the command line.
We need to know what the name of the project the user is creating and which remote repository code the user wants to download:
const inquirer = require("inquirer");
inquirer
.prompt([
{
type: "input".name: "project".message: "Project Name"}, {type: "list".name: "tpl".message: "Please select template".choices: ["vue"."react"],
}
])
.then((res) = > {
console.log(res);
const { project, tpl } = res;
// project is the name of the project entered by the user
// TPL is the template selected by the user
});
Copy the code
This code provides the user with an input option to enter the project name and a list option to select the template to download (we will later download the repository based on the template name).
Inquirer also has more options, which you can explore in the official documentation: github.com/SBoudrias/I…
4. Pull the remote warehouse code
Now we know which template code the user is downloading and where to download it:
const stores = [
{
name: "vue".url: "https://github.com/vuejs/vue.git"
},
{
name: "react".url: "https://github.com/facebook/react.git"}]Copy the code
There are several third-party modules to pull github or GitLab remote repository code. I choose Nodegit. This project currently has 4.9K star on Github and is very easy to use:
const Git = require("nodegit");
/** Clone remote repository code */
// url: source code repository address; Path: the destination path to download. Cb: callback function after downloading
const gitClone = (url, path, cb) = >{
console.log("Downloading remote repository code...")
console.log(url)
Git.Clone(url, path)
.then(function(res) {
console.log("Download completed")
cb(true)
})
.catch(function(err) { console.log("Download failed"+err); cb(false)}); }Copy the code
Nodegit website: github.com/nodegit/nod…
So far three basic functions have been realized!
5, to optimize
I think I can go further, such as download the source code, and then help me automatically install the dependency package:
const process = require('child_process');
/** Install the dependency package */
const install = (path) = >{ // path is the path of package.json in the source template
console.log("Installing dependencies...")
const cmd = 'cd '+path+' && yarn';
process.exec(cmd, function(error, stdout, stderr) {
console.log(error);
console.log(stdout);
console.log(stderr);
console.log("Installation complete")}); }Copy the code
Before I saw a lot of scaffolding came with the wind of the art word, as a pursuit of the cut figure son, this must be arranged! This also uses a third party module figlet (github.com/patorjk/fig…
const figlet = require('figlet');
figlet('My CLI! ', {horizontalLayout:"full"}, function(err, data) {
if (err) {
console.log('Something went wrong... ');
console.dir(err);
return;
}
console.log(data)
// do something...
});
Copy the code
Many scaffolds also provide parameter configuration, help information, and so on, mostly through the Commander module (github.com/tj/commande… , 20.7kstar), I won’t expand it in detail here, I also implemented it briefly in the demo project, it is very powerful and easy to use.
Demo is open source: github.com/youzouzou/t…
The demo simply implements the basic functionality of scaffolding, explores the use of several Node modules, and has a lot to refine. The best way to learn further is to look at the mature scaffolding source code, and then imitate to practice, combined with the actual situation, to find the most suitable for their own team.
6, summary
To do a good job, he must sharpen his tools.
In fact, scaffolding is not tied to the above implementation form, any tool that can improve efficiency, in a sense can be called scaffolding.
Imitation is only the beginning, innovation is the real beginning.