Overview of front-end engineering and scaffolding tools

Article description: This article is the notes and experience of the front-end training camp of Regao. If there is something wrong, I hope you can point out and teach, thank you! 

1. The definition of engineering and the main problems to be solved 

From traditional websites to the current H5, mobile apps, desktop applications and small programs, the front-end requirements for developers have undergone drastic changes.

the problem we are facing

  • I want to use ES6+, but there is a compatibility problem (traditional language or grammar drawbacks)
  • I want to use Less/Sass/PostCSS to enhance the programming of CSS, but the operating environment cannot directly support it (modularization/componentization cannot be used)
  • The code and resource files need to be compressed manually before deployment and online, and the code needs to be manually uploaded to the server during the deployment process (repetitive mechanical work)
  • Multi-person collaborative development, it is impossible to rigidly unify everyone's code style, and the quality of the code pulled back from the warehouse cannot be guaranteed (unified code style, quality assurance)
  • When developing some functions, you need to wait for the back-end service interface to be completed in advance (rely on back-end service interface support, and overall rely on back-end projects)

2. Engineering performance during a project

Engineering performance: All means for the purpose of improving efficiency, reducing costs, and quality assurance belong to engineering.

All repetitive tasks should be automated. Engineering is not equal to a specific tool. The core of engineering is a plan or structure for a project as a whole, and tools in this process are only used to help us land and implement this kind of plan or structure.

Three, engineering and Node.js

Without node.js, there would be no front-end today.

Engineering:

  • Scaffolding tool development
  • Automated build system
  • Modular packaging
  • Project code standardization
  • Automated deployment

4. Overview of scaffolding tools and common scaffolding tools

The essential role of scaffolding: create project infrastructure, provide project specifications and conventions, usually when developing the same project, there will be some same conventions:

  • Same organizational structure
  • Same development paradigm
  • Same module dependency
  • Same tool configuration

Use scaffolding tools to build a specific type of skeleton, and then perform follow-up development work based on this type of skeleton. For example, the process of creating a project in an IDE is a scaffolding workflow.

Commonly used scaffolding tools:

  • React project=》create-react-app
  • vue.js => vue-cli
  • Angular project=》angular-cli

It is nothing more than creating a corresponding project infrastructure based on information, and it is represented by a general-purpose scaffolding tool such as yeoman. They can provide a set of templates to generate a corresponding project structure. This type is generally very flexible. And it's easy to expand. There is also a type of scaffolding tool like plop, which is used to create certain types of files during the development of the project, such as the files needed to create a component\module.

Five, yeoman

Yeoman is a scaffolding tool for creating modern web projects. Unlike vue-cli, yeoman is more like a scaffolding platform. You can use yeoman with different generators to create any type of project, which means you can create your own generator. So as to customize our own front-end scaffolding tools. In the eyes of many people who focus on framework-based development, yeoman is too general and not focused enough.

Use npm to install globally: yarn global add yo.

Yeoman needs to be used with a specific generator. To find the generator of the corresponding project type, use the generator-node, first install the generator globally: yarn global add generator-node

The yo node command installs a specific generator. If yo is not an internal or external command, it is not installed globally. Use the global installation command:

After that reuse yo node

Generated basic project structure and code

Sub Generator

Sometimes we only need to create some specific types of files on the basis of existing projects, such as creating a readme for an existing project, or adding some types of configuration files to the original project type, such as eslint, babel . If this is the case, you can use the Sub Gennerator provided by Yeoman.

Custom Generator:

Based on Yeoman's own scaffolding, Generator is essentially an NPM module.

Basic structure of Generator:

If you need to provide multiple server generators, you can add a new same-level directory to the same-level directory of the app

In addition to the specific structure, another difference is that the module name of yeoman's Generator is Generator-<name>:

$ mkdir generator-sample //创建Generator的文件夹

Use yarn to create and initialize the package.json file

yarn init

Install a module of yarn-generator. This module provides a mechanism for generators. This mechanism provides some tool functions to make it more convenient for us to create generators.

Entry file in the generator:

Link this module to the global scope by means of yarn link to make it a global module package. In this way, yeoman finds our own Generator-sample when working.

yarn link

Perform yeoman operations in the project directory

yo sample

Create a file based on the template:

Create files based on templates. Compared with manually creating each file, the method of template greatly improves efficiency.

With the template file, we don’t need to use the write method of fs to write the file when generating the file, and write the file to the target directory through the template method.

Receive user input data:

For the dynamic data of the template, such as project title, project name, it is generally obtained by asking the user through command line interaction. In the Generator, if we want to initiate a command line interactive query, we can implement the promiting method in the Generator type

Vue Generator case

  • Create and initialize the Generator folder, and then install the yeoman-generator module 
  $ mkdir generator-vue
  $ cd generator-vue
  $ yarn init # 或者 npm init
  $ yarn add yeoman-generator # or npm install yeoman-generator -D
  • Copy the directory structure generated by vue to the templates of Generator and use it as a template file

Project directory generated by vue:

After copying to Generator:

  • According to the custom Generator step, modify the writing method (no longer write a single file like before, it needs to batch generate the structure we just prepared in advance, create a templates directory, copy the structure we created to the templates ):
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(){//不再像之前写入单个文件,它需要批量把我们刚刚所提前准备好的结构给它批量生成,创建一个templates目录,把我们创建的结构拷贝到templates当中
        //把每一个文件都通过模板转换到目标路径

        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'
          ]

          templates.forEach(item =>{
              //item =>每个文件路径
              this.fs.copyTpl(
                  this.templatePath(item),
                  this.destinationPath(item),
                  this.answers
              )
          })
    }
}
  • Create an empty folder (my-proj) to generate the corresponding project file according to the template:

The name of the yo Generator

Generated new vue project file:

 Release Generator

Publishing the Generator is actually publishing a Generator module. The written Generator module can be published as a public module through a command such as npm publish. Before doing this, we will host the project source code to the public source code repository.

git init//初始化本地仓库
git add .
git commit -m"feat:initial commit"
git remote add origin https://gitee.com/lyle1111/generator-zce-vue.git//添加远程仓库
git push -u origin master //提交

Execute the release command in the interface:

When you execute it for the first time, you will be asked to enter the username, email and password of mpm, and you only need to enter the password when you enter it later.

Commands when logging in and logging out:

yarn login 或者 npm login
yarn logout 或者 npm logout

The following error means that you need to go to the mailbox to activate your account:

If the following error occurs, the name of the released generator conflicts with others:

Just change the name in package.json

If you use Taobao's mirror resources, the following errors will occur, because Taobao mirrors are read-only and cannot be released as modules.

 

Can modify mirror resources

  $ npm config set registry https://registry.yarnpkg.org  # yarn 镜像源
  $ npm config set registry https://registry.npmjs.org # node 默认镜像源

Or follow the relevant mirror resources directly after the command

  $ yarn publish --registry-https://registry.yarnpkg.com # yarn 镜像源
  $ yarn publish --registry-https://registry.npmjs.org # node 默认镜像源

Finally, the run is complete:

 Go to the npm official website to see the module just released:

 After being sent to npm, this module can be installed globally via npm or yarn, and then used by yeoman (yo this Generator).

Plop

A small tool for creating specific types of files in a project. It is similar to the Sub Generator in Yeoman, but it is generally not used independently, but integrated in the project to automatically create the same type of project files, such as the files needed to create a component/module. Plop can improve the efficiency of creating duplicate files.

step:

  • Install the plop module as a project development dependency
  • Create a plopfile.js file in the project root directory
  • Define the scaffolding task in the plopfile.js file
  • Write templates for generating specific types of files
  • Run scaffolding tasks through the CLI provided by Plop

use:

Integrate plop in the project and install the plop module

  yarn add plop --dev # 或者 npm install plop -D

In the project root directory, create a new profile.js file to define Plop scaffolding tasks

//Plop 入口文件,需要导出一个函数
// 此函数接收一个 plop 对象,用于创建生成器任务

module.exports = plop => {
    //setGenerator接收两个参数,一个是生成器的名字,一个是生成器的配置选项
    plop.setGenerator('component',{
        description:'create a component',
        prompts:[
            /*
                可以在这个Generator当中指定工作的时候会发出的命令行问题,这些命令行问题会出现交互环节
            */
            {
                type:'input',//指定这个问题的输入方式
                name:'name',//指定这个问题的返回值的一个键
                message:'component name',//屏幕上给出的提示
                default:'MyComponent'//这个问题的默认答案
            }
        ],
        actions:[
            /*
                actions是这个生成器在完成命令行交互过后需要执行的一些动作,可以是一个数组,这个数组当中为每一个动作对象
            */
            {
                type:'add',//这个动作的类型,为add,代表添加文件,
                path:'src/components/{
   
   {name}}/{
   
   {name}}.js',//指定需要添加的文件会被添加到哪个具体的路径
                templateFile:'plop-templates/component.hbs'//模板文件
            },
            {
                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'
            }
        ]
    })
}

Create a corresponding template file. The template file is written using the Handlebars template engine, and is generally placed under plop-templates in the root directory:

Template file (component.hbs):

import React from 'react';
//这些文件遵循handlebars 模板语法
export default () =>(
    <div className = "{
   
   {name}}">
        <h1>{
   
   {name}} Component</h1>
    </div>
)

When installing plop, Plop provides a CLI application. Since yarn will automatically find the command line tool in the bin directory under node_modules, you can start this program through yarn

  yarn plop component //yarn plop 定义的Generator名称

After success: 

 

Six, the working principle of scaffolding:

The scaffolding tool is actually an application of node cli.

  •  Create a new folder and use yarn init to initialize, and then add the attribute bin to the initialized package.json, set the entry file, and specify the entry file of the CLI application

  • Install the inquiry module, and realize user interaction by using the inquiry module

 

 yarn add inquirer // 或者 npm install inquirer
  • Install ejs module for file rendering
 yarn add ejs // 或者 npm install ejs
  • Write the cli.js file
#!/user/bin/env node
  
// Node CLI 应用入口文件必须要有这样的文件头
// 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
// 具体就是通过 chmod 755 cli.js 实现修改

// 脚手架的工作过程:
// 1. 通过命令行交互询问用户问题
// 2. 根据用户回答的结果生成文件

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(answers => {
    // 根据用户回答的结果生成文件

    // 模板目录
    const tmplDir = path.join(__dirname, 'templates')

    // 目标目录
    const destDir = process.cwd()

    // 将模板下的文件全部转化到目标目录
    fs.readdir(tmplDir, (err, files) => {
        if (err) throw err
        files.forEach(file => {
            // 每一个file都是相对于templates下的相对路径
            // 通过模板引擎渲染文件,这里采用 ejs
            /**
             * renderFile() 方法 接收三个参数
             * 一,文件的绝对路径
             * 二,渲染的数据
             * 三,回调函数
             */ 
            ejs.renderFile(path.join(tmplDir, file), answers, (err, result) => {
                if (err) throw err

                // 将结果写入目标文件路径
                fs.writeFileSync(path.join(destDir, file), result)
            })
        })
    })
})

Guess you like

Origin blog.csdn.net/weixin_41962912/article/details/110392787