Teach you to build a front-end scaffold tool from scratch.

This article is original and reproduced with the author’s information: Jrain Lau
Project address:https://github.com/jrainlau/s …

Preface

In the actual development process, it is a headache to build the project structure from scratch, so various scaffolding tools have emerged. The author uses moreyoeman,express-generatorAndvue-cliIs one of them. They are rich in functions, but the core function is to quickly build a complete project structure. Developers only need to develop on the basis of the generated project structure, which is very simple and efficient.

As a person who will not stir up death star, he began to ponder their principle after he became familiar with that use method. After careful study of the documents and source code, I finally found out the core principle and built a model calledSCIONScaffolding.

Now let’s take SCION as an example to build a scaffolding tool of our own from scratch.

Core principle

yoemanConstruction projects need to be providedyoeman-generator.yoeman-generatorIn essence, it is a project template with a complete file structure. Users need to manually transfer thesegeneratorDownload to local, thenyoemanAccording to thesegeneratorAutomatically generate various projects.

vue-cliIt provides quite rich options and setting functions, but its essence is also different from remote warehouseTemplatePull to the local, rather than what is “locally generated” black technology.

In this way, there is a train of thought-first, different model projects are established, and then scaffolding refers to the model projects to generate actual projects according to user’s instructions. Sample projects can be built into scaffolding or deployed in remote warehouses. For a wider application range,SCIONThe second method is adopted.

Technical selection

  • node.js: The latest version is recommended as the basic component of the whole scaffold tool.

  • es6: new version ofnode.jsFores6The degree of support is already very high, usees6Can greatly improve the development efficiency and development experience.

  • commanderThe tool developed by TJ Great Spirit can better organize and process the input of command line.

  • co: An asynchronous process control tool developed by TJ Dashen writes asynchronous code in a more comfortable way.

  • co-prompt: It is also the work of TJ Great God … The traditional command line can only input all parameters and options in one line at a time. Using this tool, prompt information can be provided automatically and user input can be received step by step. The experience is similar.npm initThe process of inputting parameters step by step.

Overall structure

According to international practice, we must first understand the overall structure and look at the picture before we start development.
图片描述

First understandTemplateThe concept of. A template is a template of a project, including the complete structure and information of the project.
The template information is stored in a database calledtemplates.jsonIn the first half of this year.
Users can use the command line totemplates.jsonAdd, delete and list.
By selecting different templates, SCION will automatically pull the corresponding templates from the remote warehouse to the local to complete the construction of the project.

The final document structure of the whole scaffold is as follows:

=================
 |__ bin
 |__ scion
 |__ command
 |__ add.js
 |__ delete.js
 |__ init.js
 |__ list.js
 |__ node_modules
 |__ package.json
 |__ templates.json

Entry file

First of all, establish a project inpackage.jsonWrite dependency and execution insidenpm install

"dependencies": {
 "chalk": "^1.1.3",
 "co": "^4.6.0",
 "co-prompt": "^1.0.0",
 "commander": "^2.9.0"
 }

Create under root directory\binFolder, in which to create a no suffixscionDocuments. This ..bin\scionThe file is the entrance file of the whole scaffold, so we first wrote it.

The first is some initialization code:

#!  /usr/bin/env node --harmony
 'use strict'
 //Define the file path of scaffold
 process.env.NODE_PATH = __dirname + '/../node_modules/'
 
 const program = require('commander')
 
 //Define Current Version
 program
 .version(require('../package').version )
 
 //Define usage methods
 program
 .usage('<command>')

As can be seen from the previous architecture diagram, scaffolding supports users to enter 4 different commands. Now let’s write a method for handling these four commands:

program
 .command('add')
 .description('Add a new template')
 .alias('a')
 .action(() => {
 require('../command/add')()
 })
 
 program
 .command('list')
 .description('List all the templates')
 .alias('l')
 .action(() => {
 require('../command/list')()
 })
 
 program
 .command('init')
 .description('Generate a new project')
 .alias('i')
 .action(() => {
 require('../command/init')()
 })
 
 program
 .command('delete')
 .description('Delete a template')
 .alias('d')
 .action(() => {
 require('../command/delete')()
 })

commanderThe specific use method of the is not expanded here, you can go directly toThe official websiteLook at the detailed documents.
Finally, don’t forget to process parameters and provide help information:

program.parse(process.argv)
 
 if(!  program.args.length){
 program.help()
 }

Please look at the complete codeHere.
UsenodeRun this file and see the output below, which proves that the import file has been written.

Usage: scion <command>
 
 
 Commands:
 
 add|a      Add a new template
 list|l     List all the templates
 init|i     Generate a new project
 delete|d   Delete a template
 
 Options:
 
 -h, --help     output usage information
 -V, --version  output the version number

Processing user input

Create under project root directory\commandA folder dedicated to storing command processing files.
Create under root directorytemplates.jsonFile and write the following contents to store template information:

{"tpl":{}}

Add template

Enter\commandAnd create a new oneadd.jsDocuments:

'use strict'
 const co = require('co')
 const prompt = require('co-prompt')
 const config = require('../templates')
 const chalk = require('chalk')
 const fs = require('fs')
 
 module.exports = () => {
 co(function *() {
 
 //Receive user input parameters step by step
 let tplName = yield prompt('Template name: ')
 let gitUrl = yield prompt('Git https link: ')
 let branch = yield prompt('Branch: ')
 
 //Avoid adding repeatedly
 if (!  config.tpl[tplName]) {
 config.tpl[tplName] = {}
 Tpl [tplname] ['url'] = gitul.replace ([\ u0000-\ u0019]/g,'')//filters unicode characters
 config.tpl[tplName]['branch'] = branch
 } else {
 console.log(chalk.red('Template has already existed!'  ))
 process.exit()
 }
 
 //write template information into templates.json
 fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config), 'utf-8', (err) => {
 if (err) console.log(err)
 console.log(chalk.green('New template added!  \n'))
 console.log(chalk.grey('The last template list is: \n'))
 console.log(config)
 console.log('\n')
 process.exit()
 })
 })
 }

Delete template

Similarly, in\commandCreate under folderdelete.jsDocuments:

'use strict'
 const co = require('co')
 const prompt = require('co-prompt')
 const config = require('../templates')
 const chalk = require('chalk')
 const fs = require('fs')
 
 module.exports = () => {
 co(function *() {
 //Receive user input parameters
 let tplName = yield prompt('Template name: ')
 
 //Delete the corresponding template
 if (config.tpl[tplName]) {
 config.tpl[tplName] = undefined
 } else {
 console.log(chalk.red('Template does not exist!'  ))
 process.exit()
 }
 
 //write template.json
 fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config),     'utf-8', (err) => {
 if (err) console.log(err)
 console.log(chalk.green('Template deleted!'  ))
 console.log(chalk.grey('The last template list is: \n'))
 console.log(config)
 console.log('\n')
 process.exit()
 })
 })
 }

List templates

establishlist.jsDocuments:

'use strict'
 const config = require('../templates')
 
 module.exports = () => {
 console.log(config.tpl)
 process.exit()
 }

Build project

Now we come to the most important part-building a project. Similarly, in\commandA new one calledinit.jsDocuments of:

'use strict'
 const exec = require('child_process').exec
 const co = require('co')
 const prompt = require('co-prompt')
 const config = require('../templates')
 const chalk = require('chalk')
 
 module.exports = () => {
 co(function *() {
 //Process user input
 let tplName = yield prompt('Template name: ')
 let projectName = yield prompt('Project name: ')
 let gitUrl
 let branch
 
 if (!  config.tpl[tplName]) {
 console.log(chalk.red('\n × Template does not exit!'  ))
 process.exit()
 }
 gitUrl = config.tpl[tplName].url
 branch = config.tpl[tplName].branch
 
 // git command, pull the project remotely and customize the project name
 let cmdStr = `git clone ${gitUrl} ${projectName} && cd ${projectName} && git checkout ${branch}`
 
 console.log(chalk.white('\n Start generating...'))
 
 exec(cmdStr, (error, stdout, stderr) => {
 if (error) {
 console.log(error)
 process.exit()
 }
 console.log(chalk.green('\n √ Generation completed!'  ))
 console.log(`\n cd ${projectName} && npm install \n`)
 process.exit()
 })
 })
 }

As you can see, this part of the code is also very simple, the key sentence is

let cmdStr = `git clone ${gitUrl} ${projectName} && cd ${projectName} && git checkout ${branch}`

Its function is to clone from the remote warehouse to the custom directory and switch to the corresponding branch. Those who are familiar with git orders should understand that it is time for those who are not familiar with it to make up their lessons.

Global usage

In order to be used globally, we need topackage.jsonSet it inside:

"bin": {
 "scion": "bin/scion"
 },

When debugging locally, execute it under the root directory.

npm link

You can put thescionThe command is bound to the global and can be used directly in the futurescionTo begin a command without typing a longnode scionSuch orders.

Now that our scaffolding tools have been built, let’s give it a try!

Use test

  • Add | a add template command
    图片描述

  • Init | i build project command
    图片描述

  • Delete | d delete template command and list | l list template command
    图片描述

We’re done! Now that our entire scaffolding tool has been built, we only need to know the git https address and branch of the template to add it to SCION continuously. if the team works together, we only need to share SCION’stemplates.jsonDocuments are fine.

Postscript

What does not seem complicated actually took a lot of effort to build from scratch. The biggest problem is not knowing how to look like at the beginning.npm initIn that way, the user input can be processed step by step, and only one command line can be used to bring all the parameters. This kind of user experience is really bad. I studied itvue-cliAndyoemanAlso did not find the corresponding code, had to constantly google, finally found an article, can usecoAndco-promptThe realization of these two tools, once again worship the omnipotent TJ great god, also hope to have a small partner to tell mevue-cliHow do they come about?

This scaffold has only the most basic functions and is far from reaching the level of similar products on the market. Please fill it slowly in the future. Anyway, I really learned a lot in the process of completing SCION.

Thank you for reading. I am Jrain, welcome to pay attention.My column, will not regularly share their learning experience, development experience, carrying dry goods outside the wall. See you next time!