preface
In actual development, building the structure of a project from scratch can be a headache, so a variety of scaffolding tools were created. Yoeman, Express-Generator, and VUe-CLI are the ones I use most. They are rich in functions, but the most core function is to quickly build a complete project structure, developers only need to develop on the basis of the generated project structure, very simple and efficient.
As a non-fidgeting Death Star person, I started thinking about how they worked after I got familiar with them. After poring over the documentation and source code, I finally figured out its core principles and built a scaffolding called SCION based on that principle.
Now let’s take SCION as an example and build our own scaffolding tool from scratch.
Core principles
The YoEMAN construction project requires a Yoeman-Generator. Yoeman-generator is essentially a template of a project with a complete file structure. Users need to manually download these generators locally, and Yoeman automatically generates various projects based on these generators.
Vue-cli provides quite a wealth of options and Settings, but it’s also about pulling different templates locally from a remote repository, rather than being a “locally generated” hack.
The idea is to first create different sample projects, and then the scaffolding will reference the sample projects to generate the actual projects according to the user’s instructions. Sample projects can be built into scaffolding or deployed in remote warehouses. SCION takes the second approach for a wider range of applications.
Technology selection
-
Node.js: A fundamental part of the entire scaffolding tool, and the latest version is recommended.
-
Es6: The latest version of Node. js supports ES6, which greatly improves development efficiency and experience.
-
Commander: A tool developed by TJ to better organize and process command line input.
-
Co: TJ developed asynchronous flow control tool, with a more comfortable way to write asynchronous code.
-
Co-prompt: Or TJ’s work… In the traditional command line, you can only enter all parameters and options in a single line at a time. Using this tool, you can automatically provide prompt information and receive input step by step, similar to the process of entering parameters step by step in NPM Init.
Node.js: A fundamental part of the entire scaffolding tool, and the latest version is recommended.
Es6: The latest version of Node. js supports ES6, which greatly improves development efficiency and experience.
Commander: A tool developed by TJ to better organize and process command line input.
Co: TJ developed asynchronous flow control tool, with a more comfortable way to write asynchronous code.
Co-prompt: Or TJ’s work… In the traditional command line, you can only enter all parameters and options in a single line at a time. Using this tool, you can automatically provide prompt information and receive input step by step, similar to the process of entering parameters step by step in NPM Init.
The overall architecture
International convention, before starting to develop to understand the overall structure, look at the picture:
First understand the concept of a template. A template is a template for a project, containing the complete structure and information of the project. The template information is stored in a file called templates.json. You can add, delete, and list templates.json from the command line. By selecting different templates, SCION will automatically pull the corresponding templates from the remote repository to the local site to complete the project construction.
The final file structure of the entire scaffold is as follows:
=================
|__ bin
|__ scion
|__ command
|__ add.js
|__ delete.js
|__ init.js
|__ list.js
|__ node_modules
|__ package.json
|__ templates.json
Copy the code
Entrance to the file
First create the project, write the dependencies in package.json and execute NPM install:
"dependencies": {
"chalk": "^ 1.1.3." "."co": "^ 4.6.0"."co-prompt": "^ 1.0.0"."commander": "^ 2.9.0"
}Copy the code
Create the \bin folder in the root directory and create a scion file with no suffix in it. The bin\scion file is the entry file to the scaffold, so we write it first.
First, some initialization code:
#! /usr/bin/env node --harmony
'use strict'
// Define the scaffold file path
process.env.NODE_PATH = __dirname + '/.. /node_modules/'
const program = require('commander')
// Define the current version
program
.version(require('.. /package').version )
// Define the usage method
program
.usage('<command>')Copy the code
As you can see from the previous architecture diagram, scaffolding supports user input of four different commands. Now let’s write how to handle these four commands:
program
.command('add')
.description('Add a new template')
.alias('a')
.action((a)= > {
require('.. /command/add')()
})
program
.command('list')
.description('List all the templates')
.alias('l')
.action((a)= > {
require('.. /command/list')()
})
program
.command('init')
.description('Generate a new project')
.alias('i')
.action((a)= > {
require('.. /command/init')()
})
program
.command('delete')
.description('Delete a template')
.alias('d')
.action((a)= > {
require('.. /command/delete')()
})Copy the code
The specific usage of COMMANDER is not explained here. You can go to the official website for detailed documentation. Finally, don’t forget to handle parameters and provide help information:
program.parse(process.argv)
if(! program.args.length){ program.help() }Copy the code
See the complete code here. Run the file using Node and see the following output to prove that the entry 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 numberCopy the code
Processing user input
Create a \command folder at the root of your project to store command processing files. Templates. Json file in the root directory and write the following to hold template information:
{"tpl": {}}Copy the code
Add the template
Go to \command and create a new add.js file:
'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 = (a)= > {
co(function* () {
// Accept parameters entered by the user step by step
let tplName = yield prompt('Template name: ')
let gitUrl = yield prompt('Git https link: ')
let branch = yield prompt('Branch: ')
// Avoid repeated additions
if(! config.tpl[tplName]) { config.tpl[tplName] = {} config.tpl[tplName]['url'] = gitUrl.replace(/[\u0000-\u0019]/g.' ') // Filter Unicode characters
config.tpl[tplName]['branch'] = branch
} else {
console.log(chalk.red('Template has already existed! '))
process.exit()
}
// Write the template information to 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()
})
})
}Copy the code
To delete a template
Similarly, create the delete.js file in the \command folder:
'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 = (a)= > {
co(function* () {
// Accepts parameters entered by the user
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()
}
/ / into the template. The 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()
})
})
}Copy the code
List template
Create list.js file:
'use strict'
const config = require('.. /templates')
module.exports = (a)= > {
console.log(config.tpl)
process.exit()
}Copy the code
Build the project
Now comes the most important part — building the project. Also, create a new file called init.js in the \command directory:
'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 = (a)= > {
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 to remotely pull the project 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(Generation '\ n) completed! '))
console.log(`\n cd ${projectName} && npm install \n`)
process.exit()
})
})
}Copy the code
As you can see, this part of the code is also very simple, and the key sentence is
let cmdStr = `git clone ${gitUrl} ${projectName} && cd ${projectName} && git checkout ${branch}`Copy the code
What it does is clone from the remote repository to the custom directory and switch to the corresponding branch. Git command: git command: git command: git command: git command: Git command: Git command
The global
To be used globally, we need to set this in package.json:
"bin": {
"scion": "bin/scion"
},Copy the code
Local debugging is performed in the root directory
npm linkCopy the code
You can bind the scion command globally, so you can start the command with scion instead of typing a long Node scion command.
Now that our scaffolding tools are set up, let’s give it a try!
Use the test
-
The add | add a template command
-
Init | I generating project command
-
The delete | d | l delete template command and list are listed template command
The add | add a template command
Init | I generating project command
The delete | d | l delete template command and list are listed template command
And you’re done! Now that the scaffolding tool is complete, all you need to know is the git HTTPS address and branch of the template to continue to add to SCION. For teamwork, just share SCION templates. Json files.