preface
I used to think that scaffolding was a lofty thing, something that only a great big man could write about, something he could only aspire to. In fact, it is not because of difficulties that we give up, but because giving up is difficult. If you’re willing to spend a day and a half exploring, you can write your own scaffold.
Scaffolding is a word I believe everyone is familiar with, more or less know or use, such as vue-CLI in Vue, create-React-app in REAT and so on. Using scaffolding to develop, give us the feeling is convenient, fast. But we need to understand some of the things built into scaffolding, otherwise it is relatively inflexible to modify. Ready-made scaffolding is not always adequate for our daily work environment, so we sometimes have to build the framework of a project from scratch. Git clone: Git clone,git clone,git clone,git clone And so on. Scaffolding is designed to save us from these operations. It is essentially a remote download of a template for a new project. Think of it as an advanced clone, providing interactive commands to dynamically modify our template project.
This article is mainly based on the framework I built in my previous study and work. This includes the tools used, as well as detailed code steps. In the process of learning, I also consulted a lot of materials and learned from a lot of big wigs. I wrote the details so that I could review them by myself in the future. I also learned with some partners who wanted to build scaffolding. In fact, the real implementation of a basic function of the scaffolding, the amount of code is not much.
Tools used
The development of scaffolding need to use some of the tools, if you have used it before you can skip, if not, it is recommended to understand, but also welcome to recommend better tools.
Commander Command line development tool
Commander is a powerful function that provides users with command line input and parameter resolution. It is an essential skill for front-end node CLI development. Here focuses on the introduction of some basic usage, not to do in-depth development, there is a need to read the relevant library documentation.
-
Version Defines the version of the scaffold
-
Option Defines the options of commander.
2.1 Custom marks < must > : can be divided into long and short marks, separated by commas, vertical lines or Spaces; Flags can be followed by mandatory or optional parameters, including <> and []
2.2 Option Description < Omission without error > : Flag description is displayed when using the –help command
2.3 Default Value < omitted >
var program = require('commander'); Program.version ('0.0.1', '-v, --version'). Option ('-i --init <name>[option]', 'init a project', 'myFirstProject') .parse(process.argv); // Parse command line argumentsCopy the code
-
Command Add command name, parameter resolution:
3.1 Command Name < Must > : A command can be followed by parameters contained in <> or []. The last argument to the command can be variable, as in the example, adding… Mark; Arguments passed after the command are passed to the action callback and to the program.args array
3.2 Command description < omitted > : If it exists and action(fn) is not displayed, the subcommand program will be started, otherwise an error will be reported
3.3 Configuration Options: noHelp and isDefault can be configured
-
Action Defines the callback function for a command
-
Alias Defines the alias of a command
-
Description Defines the description of the command
var program = require('commander'); The program version (' 0.0.1 ', '- v, --version').command('init <name>[option]').description(' initialize project ').action((name)=>{console.log(name)}) .parse(process.argv); // Parse command line argumentsCopy the code
Download-git-repo Downloads the template repository
This is used to download remote templates and supports GitHub, GitLab, Bitbucket, etc.
- The installation
npm i download-git-repo
- use
const download = require('download-git-repo') download(repository, destination, options, Callback) // repository: // destination: // repository: // destination: // directory: //options: {clone: Git clone //callback callback function, which accepts a single parameterCopy the code
Ora indicates the command line loading progress
This is a nice load, like the one that goes around when you download it, and it works like this:
const ora = require('ora') let spinner = ora('downloading template ... ') // spinner.start() // spinner.fail(' Project template download failed '); // spinner. Succeed (' project template downloaded successfully '); .Copy the code
Inquirer command line interaction tool
This is a powerful interactive command line tool that you need to use if you want to interact with the user, as follows:
const inquirer = require('inquirer'); Inquirer. Prompt ([// some interactive questions {type:'input', // the type of questions name:'author', // the key message stored in the returned object :' Please enter the author', // the description of the question; Default: "// default...}]). Then (answers => {// answers => {});Copy the code
There are also many configuration items, and interaction types input, confirm, list, rawList, expand, checkbox, password, Editor, etc., interested students can learn to try.
The chalk command line outputs character styles
This is used to modify the console output content style, such as color, bold, font background color, etc., as follows:
const chalk = require('chalk'); console.log(chalk.green('success')); .Copy the code
start
After understanding the above knowledge, we can officially start to build scaffolding.
- Create a new folder,
npm init
Create a projectpackage.json
file - Modify the
package.json
Of the filebin
Field to set the scaffold entry file
"bin": {
"me-cli": "./index.js"
},
Copy the code
- New import file
index.js
, in the entry fileAt the top of theAdd code#! /usr/bin/env node
Declare that the command line script is written by Node.js - Download the required tool dependency package, because I decided to use these tools by referring to the information before, here is not to explain, directly download again
npm i commander download-git-repo inquirer ora chalk
Copy the code
Design instruction
I’ll define the scaffolding command as me-cli.
Me -cli -v/me-cli --version '// View the scaffold version me-cli -h/me-cli --help' // View the scaffold configuration items and functions me-cli init Template name project name // Scaffold initialization template project Me -cli list // View a list of templates available for scaffolding...Copy the code
This time to achieve the most basic functions, can be added later.
The entry file code is as follows:
#! /usr/bin/env node const program = require('commander'); // program.version ('0.0.1', '-v, ') --version').command('list').description(' View all available project templates ') program.command ('init <template> <project>') .description(' Initialize the project template project ')Copy the code
Installation and commissioning
- When we have uploaded to the NPM repository, we can pass
npm i -g me-cli
To install - When we develop local debugging, we can do it in the project directory
npm link
Create a soft connection and then use the instructions as normal. But don’t forget the last thing you need to do before downloading the NPM librarynpm unlink
Unbind to avoid instruction conflicts. npm link
After that, we can executeme-cli -v
andme-cli -h
The result is as follows:
Specific instruction writing
me-cli list
The specific code is as follows:
#! /usr/bin/env node const program = require('commander'); // program.version ('0.0.1', '-v, ') --version').command('list').description(' View all available project templates ').action(()=>{console.log(' reactCli Base template reactReduxCli ') ReactMobxCli reactTsCli typescript template ')}) program.command ('init <template> <project>').description(' Initialize the project template project ') program.parse(process.argv); // Parse command line argumentsCopy the code
And then we can run it and see what happens
me-cli init
This part is our main part, to achieve the function of pulling the project template from the remote side.
- First we need to define a template object
/ / templates available const templates = {' reactCli: {url: 'https://github.com/1149308443/react', downloadUrl: '1149308443/ act#master', description: 'me-cli scaffolding react'},... }Copy the code
The downloadUrl inside the object is the actual download address, and the branch after **#** is not prefixed. As for the other two terms, we use them for our own more intuitive view, there is no special function.
- So first we defined it
<template> <project>
Template name and project name, the two required parameters, are printed in the callback and determine that the template name must be inside the template list.
Program.command ('init <template> <project>').description(' initialize the project template project ').action((templateName, projectName)=>{ console.log(templateName, projectName) if(! (templateName in templates)){console.log(' Error downloading templates, please enter correct templates '); return; } let { downloadUrl } = templates[templateName]; console.log(downloadUrl) })Copy the code
Correct input at this point will get our template download address and project name.
- The introduction of
download-git-repo
Download the template and configure the template as follows:
const download = require('download-git-repo'); // Template repository download tool... Download (downloadUrl, projectName, err => {if(err){console.log(' Error downloading template '); }else{console.log(' Template downloaded successfully '); }})...Copy the code
Here we can actually download a template normally, and that’s not the end of it.
- The introduction of
ora
Add a download status identifier. - The introduction of
chalk
Add styles to the command line output. - The introduction of
inquirer
After the template is downloaded successfully, the user’s input can be obtained through modification with the user to modify the template project content. - The introduction of
fs
The module modifies the template project based on user inputpackage.json
At this point, our ME-CLI init template name project name directive is complete and configured as follows:
Program.command ('init <template> <project>').description(' initialize the project template project ').action((templateName, ProjectName)=>{const spinner = ora(' downloading template... ').start(); if(! (templateName in templates)){spinner. Fail (' Error downloading template, please enter the correct template '); return; } let { downloadUrl } = templates[templateName]; // The first parameter is the github repository address, the second parameter is the project directory name created, Clone (download url, projectName,err => {console.log(downloadUrl, projectName,err); If (err){spinner.fail(' error downloading template '); }else{spinner. Succeed (' download template successfully '); Inquirer. Prompt ([{type:'input', name:'name', message: 'please enter projectName ', default: projectName}, {type: 'input', name: 'description', message: 'Please enter project introduction ', default:'}, {type: 'input', name: 'author', message: 'Please enter author name ', default: }]). Then ((answers)=>{fs.readFile(' ${projectName}/package.json ', 'utf8', function(err, Data){if(err){console.log(chalk. Red (' read configuration failed ')); return; } let package = JSON.parse(data) Object.assign(package,answers); package = JSON.stringify(package,null, 4); Fs. writeFile(' ${projectName}/package.json ', package, 'utf8', (err) => {if(err){console.log(chalk. Red (' failed to modify configuration ')); return; } console.log(chalk. Green (' project initialization succeeded '))}); })})})})Copy the code
Release NPM
Now that we have the basic functionality, it’s time to upload to the NPM repository.
- First we need to register an NPM account
- Create a new one in the root directory
.npmignore
File, something like that.gitignore
Is that we neglected to sendnpm
On. - Then go back to our root directory and execute
npm login
Log in your ownnpm
Account, and execute it laternpm publish
Publish.
Note that when publishing the NPM repository, the source of the repository must be the NPM source. If it is not set back first, set it back again after publishing.
NPM config get registry // Run this command to view the repository sourceCopy the code
NPM config set HTTP: / / registry=http://registry.npmjs.org / / execute this command to set the source warehouseCopy the code
- If it’s just a test, you want to start
npm
Warehouse deletion, can be executednpm unpublish --force
Delete from warehouse. It seems that only within 24 hours of sending a package can you undo it, and you can’t send it again within 24 hours… - When we’re done we can go straight from
npm
Kuratto, global installation, executenpm unlink
Unbind local debug, executenpm i -g me-cli
Global installation, and then we can use our scaffolding command normally, note that the module name had better be added when untying
conclusion
After practice, will find that the implementation of a basic function of scaffolding is really not difficult, difficult is to make it fine. There are a lot of functions to slowly explore, in-depth study. Only in this way can we further improve our scaffolding, which is limited by my technical level and needs to be improved in the later period.
For this study note, I hope you can correct the bad points and put forward any good suggestions in the comments section. I also hope you can study together and make progress together.