I have been working for two years, and I have been wondering how the front-end scaffolding is generated and what the principle is.
At the beginning of my work, I was busy with projects and didn’t have much work experience, so I didn’t have much spare time to do what I wanted to do. Now in the spare time to learn how to build their own scaffolding from 0.
There are many different ways to write scaffolding, I know the way shell and node shell did not understand, so I first work on the node way.
Initialize the NPM
NPM init all the way downCopy the code
Create an execution file cli.js
Add “bin”:”cli.js” to package.json
Connect the execution method of the current file globally using the NPM link
The MAC may prompt you to use sudo if you have no permission. Window users, please search baidu by yourself.
Run NPM link or sudo NPM linkCopy the code
If the following information is displayed, the connection is successful
Create a template
1. Create a folder called templates
2. Create the following file format
For details, please see juejin.cn/post/700215…
Templates we will use ejS plug-in to write templates need to add EJS dependencies
npm install ejs -S
Copy the code
How are parameters used in templates 🧐
The following
So how do parameters get passed into the template? I’ll elaborate when I write the cli.js file.
Write cli file contents
The first step is to interact using the Inquirer plugin methodBlog.csdn.net/qq_26733915…
The cli.js file executes NPM install Inquirer -s to install inquirer
// This sentence is very important to use node environment #! The /usr/bin/env node // inquirer plugin can be used for human-computer interaction to ask the creator questions. const inquirer = require('inquirer'); . Const question = [{type: 'input', message: 'projectName', default: 'my-app', name: 'projectName', }, { name: 'language', type: 'list', choices: ['react', 'vue'], default: 'react', }, { name: 'style', type: 'list', choices: ['less', 'sass'], default: 'less', }, { name: 'jsType', type: 'list', choices: [' javascript 'and' ts'], default: 'js'}, {type: "input", the message:' version 'name:' version 'default:' 1.0.0,}, {type: 'input', message: 'prot', default: '3000', name: 'prot', }, ]; inquirer.prompt(question).then((answer)=>{console.log(answer)})Copy the code
Myl -cli is directly executed because the file name is already chained globally
Then you can generate the file
Just call him the createProject
// node const fs = require('fs'); // node const path = require('path'); Const createProject=(answer)=>{// First we need to get the path to the current file using the fs method which is provided by Node. // You need to obtain the path of the current file before creating the file. */ const templatespath = path.join(__dirname, 'templates'); fs.mkdir(answer.projectName,{ recursive: true },()=>{ createFIles(templatespath, answer, answer.projectName); }) /** ej.renderFile cannot read the folder, so it needs to be created manually. */ fs.mkdir(' ${answer.projectname}/ SRC /app ', {recursive: true }, () => { const app = `${process.cwd()}/templates/src/app`; createFIles(app, answer, `${answer.projectName}/src/app`); }); }Copy the code
Extract a createFIles method to create the file
/** create files */ const createFIles = (templatespath, answer, Paths) => {fs.readdir(templatespath, (err, Files) = > {/ / files is an array traversal. This data files forEach ((file) = > {the if (the file = = = 'SRC' | | file = = = 'app') return; RenderFile (path.join(templatespath, file)); Answer).then((data) => {/** The following two if is to be compatible with different suffix file path.extName (file) obtain the file suffix name path.basename(file, '.ejs') gets the file name with the suffix.ejs. */ if (path.extname(file) === '.ejs') { file = `${path.basename(file, '.ejs')}.js`; } if (path.basename(file, '.js') === 'package') { file = 'package.json'; Fs.writefilesync (path.join(__dirname, '${paths}/${file}'), data); }) .catch((err) => { console.log(err); }); }); }); };Copy the code
Then we optimize the final complete cli.js file as follows
#! The /usr/bin/env node // inquirer plugin can be used for human-computer interaction to ask the creator questions. const inquirer = require('inquirer'); // node const fs = require('fs'); // node const path = require('path'); Const ejs = require('ejs'); const ejs = require('ejs'); // Loading task loading const Listr = require(' Listr '); Const {exec} = require('child_process'); const {exec} = require('child_process'); Const {projectInstall} = require('pkg-install'); // print logo const figlet = require('figlet'); // Outputs the color style of the text. const chalk = require('chalk'); const axios = require('axios'); const question = [ { type: 'input', message: 'projectName', default: 'my-app', name: 'projectName', }, { name: 'language', type: 'list', choices: ['react', 'vue'], default: 'react', }, { name: 'style', type: 'list', choices: ['less', 'sass'], default: 'less', }, { name: 'jsType', type: 'list', choices: ['js', 'ts'], default: 'js', }, { type: 'input', message: 'version', name: 'version', default: '1.0.0',}, {type: 'input', message: 'prot', default: '3000', name: 'prot', }, ]; /** create files */ const createFIles = (templatespath, answer, Paths) => {fs.readdir(templatespath, (err, Files) = > {/ / files is an array traversal. This data files forEach ((file) = > {the if (the file = = = 'SRC' | | file = = = 'app') return; RenderFile (path.join(templatespath, file)); Answer).then((data) => {/** The following two if is to be compatible with different suffix file path.extName (file) obtain the file suffix name path.basename(file, '.ejs') gets the file name with the suffix.ejs. */ if (path.extname(file) === '.ejs') { file = `${path.basename(file, '.ejs')}.js`; } if (path.basename(file, '.js') === 'package') { file = 'package.json'; Fs.writefilesync (path.join(__dirname, '${paths}/${file}'), data); }) .catch((err) => { console.log(err); }); }); }); }; console.log( chalk.green( '\r\n' + figlet.textSync('myl-cli', { font: 'Ghost', horizontalLayout: 'default', verticalLayout: 'default', width: 80, whitespaceBreak: true, }), ), ); /** * get template list * @returns Promise */ async function getRepoList() {return axios.get('https://api.github.com/orgs/zhurong-cli/repos'); @param {string} repo template name * @returns Promise */ async function getTagList(repo) {return axios.get(`https://api.github.com/repos/zhurong-cli/${repo}/tags`); } // create project const createProject = (answer) => { // const res = await getRepoList(); */ const templatespath = path.join(__dirname, 'templates'); ${answer.projectName} / / recursive: true }, () => { createFIles(templatespath, answer, answer.projectName); }); /** ej. RenderFile cannot read the folder, so it needs to be created manually. */ fs.mkdir(' ${answer.projectname}/ SRC /app ', {recursive: true }, () => { const app = `${process.cwd()}/templates/src/app`; createFIles(app, answer, `${answer.projectName}/src/app`); }); }; Inquirer.prompt(question).then(async (answer) => {/** Listr is a one-step loading plug-in. */ const tasks = new Listr([{title: = new Listr([{title: = new Listr)); chalk.yellow('create directory and file'), task: () => createProject(answer), }, { title: chalk.blue('create git'), task: () => exec('git init', { cwd: path.join(__dirname, answer.projectName), }), }, { title: chalk.magenta('npm install'), task: () => projectInstall({ cwd: path.join(__dirname, answer.projectName), prefer: 'npm', }), }, ]); await tasks.run(); });Copy the code
Then execute myl-cli
This article was written after I learned the article of a big man of the Nuggets. It’s not very detailed.
Finally attached big guy article address juejin.cn/post/696611… Big guy’s article is more detailed