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-generator
Andvue-cli
Is 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
yoeman
Construction projects need to be providedyoeman-generator
.yoeman-generator
In essence, it is a project template with a complete file structure. Users need to manually transfer thesegenerator
Download to local, thenyoeman
According to thesegenerator
Automatically generate various projects.
vue-cli
It provides quite rich options and setting functions, but its essence is also different from remote warehouseTemplate
Pull 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,SCION
The 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 of
node.js
Fores6
The degree of support is already very high, usees6
Can 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 init
The 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 understandTemplate
The 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.json
In the first half of this year.
Users can use the command line totemplates.json
Add, 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.json
Write 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\bin
Folder, in which to create a no suffixscion
Documents. This ..bin\scion
The 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')()
})
commander
The 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.
Usenode
Run 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\command
A folder dedicated to storing command processing files.
Create under root directorytemplates.json
File and write the following contents to store template information:
{"tpl":{}}
Add template
Enter\command
And create a new oneadd.js
Documents:
'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\command
Create under folderdelete.js
Documents:
'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.js
Documents:
'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\command
A new one calledinit.js
Documents 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.json
Set it inside:
"bin": {
"scion": "bin/scion"
},
When debugging locally, execute it under the root directory.
npm link
You can put thescion
The command is bound to the global and can be used directly in the futurescion
To begin a command without typing a longnode scion
Such 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.json
Documents 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 init
In 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-cli
Andyoeman
Also did not find the corresponding code, had to constantly google, finally found an article, can useco
Andco-prompt
The realization of these two tools, once again worship the omnipotent TJ great god, also hope to have a small partner to tell mevue-cli
How 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!