engineering

define

Front-end engineering refers to the means to improve efficiency and reduce costs through tools in accordance with certain standards and specifications.

All the means to improve efficiency, reduce costs, and ensure quality for the purpose of engineering

Main problem solved

  • A weakness of traditional language or grammar
  • Modularity/componentization cannot be used
  • Repetitive mechanical work
  • Uniform code style, quality assurance
  • Rely on back-end service interface support
  • Overall reliance on back-end projects

Engineering ≠ a tool

At this stage, some tools are so large, such as WebPack, that some novices mistakenly think that engineering means Webpack. As long as you use Webpack, you have engineering. In fact, this is not the case. Tools are not the core of engineering. The core of engineering is the overall planning or architecture of the project. Tools are only a means to implement this planning or architecture in the process.

Scaffolding tool

Summary of Scaffolding Tools

The essential role of scaffolding is to create the project infrastructure and provide project specifications and conventions.

Same convention:

  • Same organizational structure
  • Same development paradigm
  • Same module dependencies
  • Same tool configuration
  • Same basic code

Commonly used scaffolding tools

React project –> create-React-app, vue project –>vue-cli, and Angular project –> Angular-CLI. Yeoman is a general-purpose project scaffolding tool that generates a project structure from a set of templates, which is flexible and easy to scale. Plop is used to create specific types of files during project development, such as files needed to create a component/module.

Yeoman

The basic use

Yonpm I yo –global install the corresponding generator, NPM I Generator-node –global Run generatoryo node sub Generator with yo to create a specific type of file based on an existing project, for example, yo node: CLI

Summary of usage Steps

  1. Know your needs
  2. Find the appropriate Generator
  3. The global scope installs the Generator found
  4. Run the corresponding Generator through yo
  5. Enter options interactively on the command line
  6. Generate the project structure you need

A custom Generator

The custom Generator builds its own scaffolding based on Yeoman. Create the Generator

A Generator is essentially an NPM module

Basic structure of Generator

The command

generator-<name>

The sample

// Create the generator-sample directory
mkdir generator-sample
cd generator-sample\
// Initialize package.json
npm init
// Install the Yeoman dependency
npm i yeoman-generator
Copy the code

Next go to the Generator -sample folder and create a generators/app/index.js file

// index.js
// This file serves as the core entry for the Generator
// We need to export a type inherited from Yeoman Generator
// As the Yeoman Generator works, it automatically calls some of the lifecycle methods we defined in this type
// In these methods, we can call some utility methods provided by the parent class to achieve some functions, such as file writing

const Generator = require('yeoman-generator')
// Export a type that inherits from the Generator
module.exports = class extends Generator {
  writing () {
    // Yeoman automatically calls this method during the file generation phase
    // Here we try to write files to the project directory
    this.fs.write(
        // The absolute file path
        this.destinationPath('temp.txt'),
        Math.random().toString()
    )
  }
}
Copy the code

Then we link to the global scope via NPM link to make it a global module package, so that Yeoman can find the generator sample we wrote when he works. You can then run the generator with yo Sample to create a temp.txt.

  • Create files from the template

In many cases, there are many files that need to be automatically created, and the contents of the files are relatively complex. In this case, you can use templates to create files. First create generators/app/templates/foo. TXT file

// This is a template file foo.txt
// Internally you can use EJS template tags to output data
// For example: <%= title %>
// Other EJS syntax is also supportedThe < %if(success) {%> hahaha <%}%>Copy the code

Once you have the template, you can write the file to the target directory as a template when the file is generated

// index.js
// This file serves as the core entry for the Generator
// We need to export a type inherited from Yeoman Generator
// As the Yeoman Generator works, it automatically calls some of the lifecycle methods we defined in this type
// In these methods, we can call some utility methods provided by the parent class to achieve some functions, such as file writing

const Generator = require('yeoman-generator')

module.exports = class extends Generator {
  writing () {
    // Yeoman automatically calls this method during the file generation phase

    // Write the file to the target directory in template mode
    // Path of the template file
    const tmpl = this.templatePath('foo.txt')
    // Output the target path
    const output = this.destinationPath('foo.txt')
    // Template data context
    const context = { title: 'Hello zce~'.success: false }
    // Automatically map template files to the output directory
    this.fs.copyTpl(tmpl, output, context)
  }
}
Copy the code
  • Receive user input data
// index.js
// This file serves as the core entry for the Generator
// We need to export a type inherited from Yeoman Generator
// As the Yeoman Generator works, it automatically calls some of the lifecycle methods we defined in this type
// In these methods, we can call some utility methods provided by the parent class to achieve some functions, such as file writing

const Generator = require('yeoman-generator')

module.exports = class extends Generator {
  prompting () {
    // This method is automatically called by Yeoman when the user is asked
    // In this method, you can invoke the prompt() method of the parent class to issue a command line query to the user
    // Return a promise
    return this.prompt([
      {
        type: 'input'.name: 'name'.message: 'Your project name'.default: this.appname // Appname is the name of the project build directory
      }
    ])
    .then(answers= > {
      this.answers = answers
    })
  }
  writing () {
    // Yeoman automatically calls this method during the file generation phase

    // Path of the template file
    const tmpl = this.templatePath('bar.html')
    // Output the target path
    const output = this.destinationPath('bar.html')
    // Template data context
    const context = this.answers

    this.fs.copyTpl(tmpl, output, context)
  }
}
Copy the code

Vue Generator case

// Create a directory
mkdir generator-jc-vue
cd generator-jc-vue\
// Initialize package.json
npm init
// Install the Yeoman dependency
npm i yeoman-generator
Copy the code

Create a generator home directory file (generators/app/index.js)

Create a generators/app/templates directory, copy the structure of the project as a template, and change the project name to the template engine syntax<%= name %>

// index.js
const Generator = require('yeoman-generator')

module.exports = class extends Generator {
  prompting () {
    return this.prompt([
      {
        type: 'input'.name: 'name'.message: 'Your project name'.default: this.appname
      }
    ])
    .then(answers= > {
      this.answers = answers
    })
  }

  writing () {
    // Convert each file to the target path through the template

    const 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'
    ]
    // Iterate to generate the corresponding object file
    templates.forEach(item= > {
      // item => each file path
      this.fs.copyTpl(
        this.templatePath(item),
        this.destinationPath(item),
        this.answers
      )
    })
  }
}
Copy the code

Generate the project with the yo jc-vue command

Release the Generator

Since a Generator is actually an NPM module, publishing a Generator is to publish an NPM module. We only need to publish the Generator module written by ourselves into a public module by using the NPM publish command.

Plop

Plop is a tool for creating specific types of files in a project. It is usually integrated into a project to automate the creation of files of the same type, not independently.

// Install dependencies
npm i plop --dev
Copy the code

Create a new plopfile.js file in the project root directory

// Plop entry file, need to export a function
// This function receives a plop object to create the generator task

module.exports = plop= > {
  // setGenerator(generator name, generator configuration options)
  plop.setGenerator('component', {
    // Generator description
    description: 'create a component'.// Command line problem
    prompts: [{type: 'input'.name: 'name'.message: 'component name'.default: 'MyComponent'}].// The action that the generator performs after completing the command line problem
    actions: [{type: 'add'.// represents adding files
        path: 'src/components/{{name}}/{{name}}.js'.templateFile: 'plop-templates/component.hbs' // Template file
      },
      {
        type: 'add'.// represents adding files
        path: 'src/components/{{name}}/{{name}}.css'.templateFile: 'plop-templates/component.css.hbs'
      },
      {
        type: 'add'.// represents adding files
        path: 'src/components/{{name}}/{{name}}.test.js'.templateFile: 'plop-templates/component.test.hbs'})}}]Copy the code
/ / the plop
npm plop component
Copy the code

How scaffolding works

Most scaffolding works by asking you a set of pre-set questions when it is launched and using your answers in conjunction with the template file to generate a project structure.

mkdir sample-scaffolding
cd sample-scaffolding\
npm init
Copy the code

Add the bin field to the package.json file to specify the entry file for the CLI project

// package.json
{
  "name": "sample-scaffolding"."version": "0.1.0 from"."main": "index.js"."bin": "cli.js"."author": "zce <[email protected]> (https://zce.me)"."license": "MIT"."dependencies": {
    "ejs": "^ 2.6.2." "."inquirer": "^ 7.0.0." "}}Copy the code

Add the cli.js file

#! /usr/bin/env node
// The Node CLI application entry file must have this header
// In Linux or macOS, you need to change the read/write permission of this file to 755, so that this file can be used as a CLI entry
Chmod 755 cli.js

// The working process of scaffolding:
// 1. Ask the user interactive questions through the command line
// 2. Generate a file based on the answer results of the user

const fs = require('fs')
const path = require('path')
const inquirer = require('inquirer')
const ejs = require('ejs')

inquirer.prompt([
  {
    type: 'input'.name: 'name'.message: 'Project name? '
  }
])
.then(anwsers= > {
  // Generate a file based on the results of the user's answers

  // The template directory
  const tmplDir = path.join(__dirname, 'templates')
  // The target directory
  const destDir = process.cwd()

  // Convert all files in the template to the target directory
  fs.readdir(tmplDir, (err, files) = > {
    if (err) throw err
    files.forEach(file= > {
      // Render the file through the template engine
      ejs.renderFile(path.join(tmplDir, file), anwsers, (err, result) = > {
        if (err) throw err

        // Write the result to the destination file path
        fs.writeFileSync(path.join(destDir, file), result)
      })
    })
  })
})
Copy the code

Run NPM link to link this module to the global execution of sample-scaffolding to generate the file