Foreword: blogger 2020.3 formally enter the front end, target senior front end engineer, experience is still shallow, if the content of the article is wrong, welcome to correct.

When you think of front-end scaffolders, you immediately think of LibCs such as vue-cli, Crate – React-app, and Angular-cli, but they are not scaffolders, they are scaffolding tools used to create scaffolders.

In daily development, we often use these scaffolding tools to help us create scaffolding projects. But we may not always have a clear idea of what a scaffold is, what a scaffold tool is, and what problems it solves. This article will start with understanding scaffolding, then explore the principles of scaffolding automation scripting tools, then learn how to use Plop and Yeoman tools to help us build scaffolding, and finally learn how to use Yeoman tools to customize scaffolding tools.

One: know scaffolding

1. Concept of scaffolding

The concept of scaffolding in Baidu Encyclopedia: scaffolding is to ensure the smooth construction process and set up the working platform. The concept is a bit awkward.

  • Construction scaffolding

  • Bed scaffolding

Combining these two pictures with the concepts in Baidu Encyclopedia, we should have a clearer understanding of scaffolding. Scaffolding provides a base platform for subsequent workers to work in a more standardized and convenient way. To base it on it, to change it, is a spiritual description of scaffolding.

Back on the front end, the staff of course refers to the code developers, and the working platform can mean an entire project at large, or several related files or a single file at a small scale.

Based on the above understanding of scaffolding, let’s list a few common scaffolds in daily development and classify them:

Daily sample Scaffolding/foundation work platform Type of scaffold
Creating an HTML file H5 template code Single document scaffold
Creating the React component A template.js file, a template.css file, and a template.test.js file Multifile scaffolding
Create the React project React Template project Project scaffolding

Well, after the above analysis and summary, we have basically achieved the purpose of understanding scaffolding. Next we discuss solving another phenomenal scaffolding problem, this problem is scaffolding reuse.

2. Reuse of scaffolding

With the exception of custom scaffolds, most scaffolds are reusable, that is, a scaffold template can be extracted. This has a lot to do with the fact that it is a basic working platform. Most of the time, it is because we need to carry out some template specifications, conventions and pre-work for the work to be carried out that we can visualize a scaffold. In the front end, the above example of the basic work platform, have template two words, they are the use of scaffolding template scaffolding.

Change a perspective, the scaffolding can also often used to solve the problem of reuse, so on the front end of development, we often use the intent of the scaffold, and is the solution to create a file or project when reuse problem (pay attention to not only the code structure and code reuse, but also a development mode of reuse, involves development routines, norms, conventions, and so on).

When we use scaffolding like create-React-app and VUE – CLI on a daily basis, our main goal is to reuse some of the development patterns (often referred to as best practices) that scaffolding tools generate. Creating projects and code structures is just a passing and superficial thing.

Rushing to use scaffolding tools for business development without understanding the development patterns they create can be one of the root causes of bad daily development and bad code.

Digression, after the above discussion, we have understood the reuse of scaffolding, let’s discuss the scaffolding problem.

3. Scaffolding construction

For the front end, scaffolding is a vehicle for development patterns that are characterized by one or more files or projects with specific structure and content. So for scaffolding, it’s just a matter of preparing these raw materials (specific structures and content, which are reused as template files or projects) and then scaffolding (create files, files) according to certain behavioral logic (manual/script). Of course, usually we don’t build a scaffold that is the same as the raw material, we will take the user’s input or configuration file and then build the scaffold, to achieve part of the scaffolding customization.

Raw materials (template files/projects) depend on the scenario and are not discussed in this article. The following article will focus on the construction process of scaffolding after the preparation of raw materials.

In forward, need project/file content reuse, we are often addressed by artificial copy, but this is almost 2021 years, in accordance with any simple mechanical repetition labor should be let the machine to complete thoughts, we are going to build a scaffold should be automated, more convenient, customize a scaffold generation tool.

Before discussing the automation of scaffolding, I feel it is necessary to reiterate that the soul of scaffolding is not in the process of scaffolding construction, much less in automation, the soul of scaffolding is in the raw materials (usually document templates, project templates).

Ok, after the above analysis, let’s first discuss the principle of scaffolding automation script/tool, and then discuss how to use Plop to build single/multiple file type scaffolding, Finally, explore how to build a project-type scaffold using Yeoman and how to build a scaffold tool based on Yeoman.

Two: the principle of scaffolding automatic construction script/tools

When we use scaffolding tools such as React-create-app and VUe-CLI to build a scaffolding project, it will first ask some questions, and then the scaffolding will create a scaffolding project based on the answers to these questions combined with its own project template.

In light of this need and the scaffolding knowledge above, let’s explore the principles of these scaffolding tools. Let’s first use the idea of functional programming to think about how to write scaffolding automation scripts:

  • Input: scaffold template (raw material), template parameters input by users
  • Output: single file/multi-file/project
  • Mapping: Template parsing and I/O reading and writing operations

Based on this idea, we implemented a single-file scaffolding tool (multi-file and project-type scaffolding are just more complex and work in the same way) that can automatically generate a named file parsed from the resulting template based on the template file content and user input, as shown in the following example:

1. Principle exploration example: single file scaffolding automatic creation script

  • Templates (template.txt) : EJS template engine specification
xxxx
<%= param1 %>
xxxx
Copy the code
  • Automated create scripts (cli.js)
const inquirer = require('inquirer'); Const fs = require(const fs = require('fs');
const path = require('path');
const ejs = require('ejs'); Const {Transform} = require(const {Transform} = require('stream'); // Inquirer. Prompt ([{type: 'input'.name: 'name'.message: 'file name? '
    },
    {
      type: 'input'.name: 'param1'.message: 'param1? '
    }
  ])
  .then(anwsers => {
    // 1FileName and folder path (user command path) const fileName = anwsers. const param1 = anwsers.param1; const dirPath = process.cwd(); //2Const tmplPath = path.join(__dirname,'template.txt');
    const filePath = path.join(dirPath, fileName + '.txt');
    // 3Const read = fs.createreadStream (tmplPath); const read = fs.createreadStream (tmplPath); constwrite= fs.createWriteStream(filePath); Const transformStream = new Transform({Transform: const transformStream = new Transform({Transform: (chunk, encoding, callback) => { const input = chunk.toString(); // Const output = ejs.render(input, {param1}); // Callback (null, output); } }) read.pipe(transformStream).pipe(write);
  })

Copy the code
  • Execute the script
c:\workspace\automate node cli.js
? project Name? result
? param1? oooo
Copy the code
  • Template rendering result (result.txt)
xxxx
oooo
xxxx
Copy the code

File flow is used in the code, so I’ll mention it briefly. In this example, you can use readFileSync and writeFileSync to read and write files. File flow is mainly used to solve the problem that the file content is too large, preventing the read file from occupying too much or even full of the running memory of the program.

Ok, the above example is a basic scaffolding automation script. Although simple, I think this is the core logic of the scaffolding automation script and the tool.

For a good automation script and tool, not only powerful, excellent performance, but also easy to use. This modification optimization can be achieved by extracting it into a separate NPM CLI module and linking it globally, following the example of mature scaffolding tools. In addition, if you want to share it for others to use, you can publish the CLI module to Github and NPM Repository. Now let’s talk about how to do that.

2. Script/tool usability considerations: Package it as an independent NPM CLI global module and publish it

Packaging as a separate scaffold generic module is as simple as extracting templates and scripts into a new NPM module. Here we explore how to configure a common module into a cli global module. The purpose of packaging NPM CLI global module is to make other modules can access and call. According to the idea of finding access and call, we configure a common module as CLI module, which can be achieved through the following steps:

  • Add a header to the entry CLI script (cli.js)
#! /usr/bin/env node

# Start script content...
Copy the code
  • Configuration entry (package.json) : Configuration bin option {” command name “: “entry file path”}
	"bin": {
		"testCli": "./cli.js"
	}
Copy the code
  • Chain to the global
yarn link
#After yarn succeeds, you can view the testcli. CMD file in the yarn global bin command.
Copy the code
  • Test using
testCli
#If the command cannot be found, check whether the global bin path of YARN is not configured as an environment variable.
Copy the code

With the above steps, the CLI module can be invoked in another module using the configured bin command, which automatically finds the cli module’s entry file and executes the scaffolding script.

If you need to make it easier for others to use, consider publishing this module to Github and NPM Repository. Here’s how:

  • Publish to Github: Github repo address
git init
git remote add origin https://github.com/iamjwe/scaffolding-demo
git add .
git commit -m "initial"
git push -u origin master
Copy the code
  • Publish to NPMPKG/YARnpkg
# After the permission is authenticated
npm/yarn publish
# Note 1: If the mirror source is used, the --registry parameter should be added to display the push specification
npm publish --registry=https://registry.npmjs.org
# Note 2: It is very easy to have the same name of the NPM package and trigger the naming problem of spam detection, so you need to change the name of the package and re-publish it
Copy the code

At this point, a simple scaffolding tool is all the way from development to release. In daily development, we usually don’t implement the scaffolding tool from 0 to 1 ourselves for complex scaffolding, because writing scripts based on the Node API requires a lot of attention to the logical process of IO reading and writing, template parsing and so on. This misses the point, since the purpose of automation with scripts or tools is to improve efficiency.

Standing on the shoulders of giants, let’s look at how to scaffold single/multiple file types with Plop, and finally how to scaffold a project type with Yeoman and how to build a scaffold tool based on Yeoman. In order to achieve the purpose of improving the efficiency of scaffolding and building scaffolding tools.

Three: build scaffolding for single/multiple file types based on Plop

Plop is a useful and frequently used tool in daily development. When we encounter a need to scaffolding a single/multiple file type, such as scaffolding a React component (creating a.js template, a.css template, and a.test.js template), Plop would have been a good helper. While you can’t fully customize scaffolding scripts/tools using Plop, scripting under Plop’s specifications can invoke its encapsulated apis to implement configured scaffolding tools. This allows us to focus more on the task itself and less on the implementation details of the task, thus improving development efficiency.

GitHub: Plop repo: Plop repo: Plop repo: Plop repo: Plop repo: Plop repo

Step1: install the Plop tool

yarn add plop --dev
Copy the code

After the preceding command is executed, a plop package is displayed under node_module and a plop. CMD file is displayed under node_module/. Bin, which requires that the plop tool can be invoked using the yarn/NPX plop task name command.

Step2: prepare the template content file

For example, the react component target js file: component.hbs

import React from 'react';

export default () => (
  <div className="{{name}}">
    <h1>{{name}} Component</h1>
  </div>
)
Copy the code

Step3: Write Plop task scripts

Create a plopfile.js file in the root directory of the project as the entry file for plop tasks. We can then implement the function of the configured scaffold tool by writing the tasks we want it to do in this entry file.

The react component automatically creates a.js template content file, a.css template content file, and a.test.js template content file based on the predefined template content.

module.exports = plop= > {
  // Generator is the task unit of Plop, and Component is the task name
  plop.setGenerator('component', {
    description: 'create a component'.// Accept user input
    prompts: [{type: 'input'.name: 'name'.message: 'component name'.default: 'MyComponent'}].// Task behavior
    actions: [{type: 'add'.// adds the file
        path: 'src/components/{{name}}/{{name}}.js'.// File output location
        templateFile: 'plop-templates/component.hbs'// Template file location
      },
      {
        type: 'add'.path: 'src/components/{{name}}/{{name}}.css'.templateFile: 'plop-templates/component.css.hbs'
      },
      {
        type: 'add'.path: 'src/components/{{name}}/{{name}}.test.js'.templateFile: 'plop-templates/component.test.hbs'})}}]Copy the code

Step4: execute Plop tasks using Plop

yarn plop component
Copy the code

4. Build a project type scaffolding based on Yeoman

Yeoman is a WEB scaffolding tool for modern WEB applications that I know primarily for creating project type scaffolding. Yeoman is a more versatile scaffolding tool than create-React-app and Vue-CLI tools that focus on a single frame. Let’s explore the workflow of setting up a scaffolding project using Yeoman by using someone else’s project template (Generator).

Step1: install Yeoman

yarn global add yo
Copy the code

Step2: install project template generator

The following example installs a Node project template

// generator repo https://yeoman.io/generators/
yarn global add generator-node
Copy the code

Step3: run generator with yo to create the template project

Remove generator- from the project template name to create a project as an argument to Yo

yo node
Copy the code

Five: Customize a scaffold tool based on Yeoman

Create a custom scaffolding tool based on Yeoman that is usually used to build project type scaffolding. In this process, we need to prepare our own scaffold template project and write our own Generator module. As with Plop, while not fully customizable with Yeoman as opposed to fully custom implementation scaffolding scripts/tools, scripting under Yeoman’s specification makes it easier to write scripts by calling its encapsulated apis. This allows us to focus more on the task itself and less on the implementation details of the task, thus improving development efficiency.

Step1: install Yeoman

Step2: prepare the project template

See the following Vue template project directory structure diagram:

Step3: write your own generator module: create the logic of the project based on the template project

The custom implementation here is a simple generator: copy and parse the template project to create a project to the current path

  • Create and initialize a module project starting with generator- (generator-demo)
  • Copy project template to current module
  • Write generator entry files: Parse project templates to create projects
const Generator = require('yeoman-generator')

module.exports = class extends Generator{// Receive user input Only () {return this.prompt([
      {
        type: 'input'.name: 'name'.message: 'Your project name'.default: this.appname}]).then(answers => {this.answers = answers})} create a new project based on the user input and the template project Writing () {// The list of file names should be read const using the IO script templates = ['.browserslistrc'.'.editorconfig'.'.env.development'.'.env.production'.'.eslintrc.js'.'.gitignore'.'babel.config.js'.'package.json'.'postcss.config.js'.'README.md'.'public/favicon.ico'.'public/index.html'.'src/App.vue'.'src/main.js'.'src/router.js'.'src/assets/logo.png'.'src/components/HelloWorld.vue'.'src/store/actions.js'.'src/store/getters.js'.'src/store/index.js'.'src/store/mutations.js'.'src/store/state.js'.'src/utils/request.js'.'src/views/About.vue'.'src/views/Home.vue'] templates. ForEach (item => {// use the fs copyTpl method: This.fs.copytpl (this.templatepath (item), this.destinationPath(item), this.answers)})}}Copy the code
  • Use YARN Link to link the current module globally so that yo can be found when it is used
  • Optionally publish generator modules to GitHub, NPM, and generator Repo

The idea and implementation have been described above and will not be described here.

Step4: run generator with yo to create the template project

yo demo
Copy the code

The end of this article, audience master you go, welcome to visit next time.