Develop scaffolding and encapsulate automated build workflows

Engineering Overview

Definition of engineering and main problems to be solved

  • Fully armed: Improve combat effectiveness through engineering.

  • Problem 1: You want to use the new ES6+ features, but have compatibility problems.

  • Problem 2: You want to use Less/Sass/PostCSS to enhance the programmability of CSS but the runtime environment does not support it directly.

  • Problem 3: You want to use a modular approach to improve project maintainability but the runtime environment does not directly support it.

  • Problem 4: Code and resource files need to be manually compressed before deployment.

  • Problem 5: The deployment process requires manual uploading of code to the server.

  • Problem 6: When developing in collaboration, you can’t rigidly agree on everyone’s code style.

  • Problem 7: The quality of code pulled back from the repository is not guaranteed.

  • Problem 8: Some functions need to wait for the back-end service interface to be completed in advance.

  • Question classification

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

The performance of engineering during a project.

  • All the means to reduce cost and increase efficiency, quality assurance for the purpose of all belong to engineering ☚

  • All repetitive tasks should be automated.

    • Create a project

      • Create the project structure.
      • Create a specific type of file.
    • coding

      • Formatting code
      • Checking code Style
      • Compile/build/package
    • Preview/Test

      • Web Server/Mock
      • Live Reloading/HMR
      • Source Map
    • submit

      • Git Hooks
      • Lint-staged
      • Continuous integration
    • The deployment of

      • CI/CD
      • Automatic release

Engineering ≠ a tool

  • Tools are not the core of engineering
  • The core of engineering is the overall planning or architecture of the project
  • Tools are simply a means of landing a planning or architectural process.

Engineering with Node.js

  • Project Powered by Node.js

  • Node.js gives the front end a new stage.

  • Front-end engineering is strongly driven by Node.js.

  • Implement engineering

    • Scaffolding tool development
    • Automated construction system
    • Modular packaging
    • Project code normalization
    • Automated deployment

Scaffolding tool

The role of scaffolding

  • Originator of front-end engineering

  • Used to create the project infrastructure

  • Provide project specifications and conventions

    • Same file organization structure
    • Same development paradigm
    • Same module dependencies
    • Same tool configuration
    • Same basic code
  • You can quickly build a skeleton of a specific type of project

  • Example: The IDE project creation process is a scaffolding workflow.

  • The front-end scaffolding is a separate tool.

  • Goal: To solve the complexity of our project creation process.

Commonly used scaffolding tools

  • Scaffolding tools used to create projects

    • Scaffolding tools that serve a particular type of project

      • The React project ↝ create – React – app
      • Vue. Js project ↝ Vue – cli
      • Agular project ↝ presents – the cli
      • Common ground: Generate project infrastructure based on the information you provide.
      • The difference: Generally only applies to projects within the framework they serve.
    • General purpose project scaffolding tool

      • Represented by Yeomen.
      • You can generate a corresponding project structure from a set of templates.
      • Very flexible
      • It’s easy to expand
  • Scaffolding of another kind

    • Used to create certain types of files during project development
    • This is represented by Plop
    • Example: files needed to create a component/module.
  • Focus on a few representative tools

    • Yeoman
    • Plop
  • How scaffolding works

    • Once started, some preset questions are asked, and the answers are combined with some template files to generate the project structure.
    • Scaffolding is essentially a Node CLI application.

General purpose scaffold tool analysis

Yeoman

- The Web's scaffolding tool for modern Webapps - As The oldest, most powerful and versatile tool, we could use a lot of scaffolding for modern webapps. - More like a scaffolding platform - Official definition: a scaffolding tool for creating modern Web applications. - You can use generators to create any type of project. - Cons: Yeoman is considered too generic and unfocused by many framework-focused folks. They prefer to use tools like VUe-CLI. - Basic use - Dependent Node environment - YARN Global add YO - With Generator: YARN global add generator-node - New project use: Yo node - Summary - Install yo - NPM install yo -- global-yarn global add yo - Install the corresponding generator- NPM install generator-node -- global-yarn global add generator-node - Run generator-cd path/to/ project-dir-mkdir my-module-yo node-sub with yo Generator - Sub-level Generator - uses: Yo node: CLI - General use step -1, identify your requirements - 2, find the appropriate generator-3, install the generator-4 found globally, run the corresponding generator-5 from Yo, interoperate with the command line option -6, Generate the project structure you need - Example: Web application generator YARN Global Add Generator - WebApp Yo webApp - Custom Generator - Build your own scaffolding based on Yeoman. - Create a Generator module - The Generator is essentially an NPM module. - the Generator structure - the Generator/app/index, js - Generator/component/index. The js - package. Json - named: Generator -<name> - Case demonstration - mkdir generator-sample - CD generator-sample - yarn init - Initialize package.json file - yarn add Yeoman -generator -vscode Open: code. -Create file: Generator /app/index.js - this file is the core entry for Generator - needs to export a type inherited from Yeoman Generator - Yeoman Generator Some of the lifecycle methods we defined in this type are automatically invoked at work. - We can implement some functions in these methods by calling some of the utility methods provided by the parent class, such as file writing.Copy the code
					- const Generator  =   require('yeoman-generator')
					- module.exports = class extends Generator {
    writing () {
        // Yeoman automatically calls this method during file generation
        // We are trying to write files to the project directory
        this.fs.write(this.destinationPath('temp.txt'), Math.random().toString())
    }
}
					- yarn link
Copy the code
- cd .. -mkdir my-proj -cd my-proj -yo sample -create file from template -create template file: App /templates/foo. TXT - Templates follow the EJS template syntax - <%= name %> - <% if(success) {%> Generate file content <%} %> - Write files to target by template - Template file path: Const temp1= this.templatepath ('foo.txt') - Output target path: const output= this.destinationPath('foo') - template data context: Const context = {name: 'SJZ'} -this.fs.copytpl (temp1, output, context) -Yo sample - The template method is much more efficient than manually creating each file. - Module. Exports = class extends Generator {only selected by targets () {// Yeoman will automatically invoke this method when interrogating the user. // In this method, you can invoke the parent class prompt() method to issue a command line query to the user. return this.prompt([ { type:'input', name: 'name', message: 'sjz', default: This.appname}]). Then (answers ⥤ {console.log(answers) this.answers = answers})}Copy the code
}

Copy the code
- Vue Generator case - mkdir Generator - SJZ - vue-cd Generator - SJZ - vue-yarn init - yarn add yeoman- Generator - code. - Create main entry file: generator/app/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 () {const templates = [] Templates. ForEach (item ⥤ {// item ⥤ each file path this.fs.copyTpl(this.templatepath (item), this.destinationPath(item), this.answers ) }) }Copy the code
} - Create the templates directory and copy the prepared files and directory structure into the templates directory. - yarn linkCopy the code
- cd .. -mkdir my-proj -cd my-proj-yo sjz-vue -publish Generator -host the project source code to a public source code repository. Git status - git add. - git commit -m "feat: Git push -u origin master - NPM publish/yarn publish - yarn The publish - registry=https://registry.yarnpkg.com - question: mirror, taobao is a read-only imageCopy the code

Plop

- A nice little scaffolding tool - is a small tool for creating specific types of files in a project, similar to the Sub Generator in Yeoman. - Generally not used independently - generally integrated into the project to automate the creation of the same type of files - Usage scenarios: The same type of files must be created repeatedly. For example, three files (CSS, js, and HTML) must be created to create components in react. New plopfile.js file - entry file for plop work - need to export a function - object parameters that receive a plop in the function - parameter plop object provides a series of utility functions - these utility functions are used to create generator tasks. On the code -Copy the code
module.exports = plop ⥤ {
     plop.setGenerator('generatorName',  {
        description: 'Generator description'.prompts: [{type: 'input'.name: 'name'.message: 'Screen prompt'.default: 'Default answer',}],actions: [{type: 'add'.// Add a brand new file
                path: 'src/components/{{name}}/{{name}}.js'.templateFile: 'plop-templates/component.hbs'}, {type: 'add'.// Add a brand new file
                path: 'src/components/{{name}}/{{name}}.css'.templateFile: 'plop-templates/component.css.hbs'}, {type: 'add'.// Add a brand new file
                path: 'src/components/{{name}}/{{name}}.test'.templateFile: 'plop-templates/component.test.hbs',},]})}Copy the code
- Run - YARN plop generatorName - summary - 1, install plop module as project development dependency - 2, create plopfile.js file - 3 in project root directory, define scaffolding task - 4 in plopfile.js file, Write a template for generating a specific type of file - 5 that runs the scaffolding task through the CLI provided by PLOpCopy the code

Develop a scaffold

  • mkdir sample-scaffolding

  • cd sample-scaffolding

  • yarn init

    • Initialize the package.json file.
  • VsCode opens: code.

  • Add the bin property to package.json

    • The value of ‘cli. Js’
  • Root directory to create a new file: cli.js

    • This file must have a specific header: #! /usr/bin/env node

      • Under the Linux/macOS systems

        • You also need to change the read and write permission on this file to 755
        • In particular, chmod 755 cli.js is used to achieve the modification
    • Contents: the console. The log (‘ SJZ)

  • yarn link

    • Link scaffolding to global
  • Then you can do it from the command line: sample-scaffolding

    • Running result: SJZ
  • The specific process of implementing scaffolding

    • 1. Ask the user questions through command line interaction

      • Install the query module Inquirer

        • yarn add inquirer
    • 2. Generate files according to the results of user answers

    • Cli.js code implementation


		- 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 ⥤ {// Generate a file based on the user's answer
    // Template directory
    const tmplDir = path.join(__dirname, 'templates')
    // Target directory
    const destDir = process.cwd()
    // Convert all files under the template to the target directoryFs.readdir (tmplDir, (err, files) ⥤ {if(err) throwErr files. ForEach (file ⥤ {// Render files through the template engineEjs. renderFile(path.join(tmplDir,file), answers, (err, result) ⥤ {if(err) throw err
               fs.writeFileSync(path.join(destDir, file), result)
          })
       })
    }
})

Copy the code
- Create template file - templates/index.html - templates/style. CSS - Install the template engine - yarn add EJsCopy the code

Automated build

Introduction to the

  • All repetitive tasks should be automated

  • Name to explain

    • automation

      • Machines do some of the work instead of hand
    • build

      • You can think of it as transformation
      • To convert one thing into something else.
  • The automated construction or conversion of source code to production code

    • This transformation or build process is called an automated build workflow.
  • role

    • You can get rid of problems caused by runtime environment compatibility

    • Allow efficient syntax, specifications, and standards

      • ECMAScript Next

      • Sass

      • A template engine

        • Abstract duplicate code in source files
      • Most of these uses are not directly supported by browsers

      • ☞ features that are not supported can be built to transform using an automated build tool.

    • Can improve development efficiency

First experience with automated builds

  • Create a new Sass file: SCSS /main.scss

    • content

      • $body-bg: #f8f9fb

$body-color: #333

body { margin: 0 auto; padding: 20px; max-width: 800px; Background – color: body – bg. color:body-bg; Color: the body – bg. color:body-color; }

  • yarn add sass –dev

  • Run./node_modules/. Bin /sass SCSS /main. SCSS CSS /style.css

    • style.css
    • style.css.map
  • NPM Scripts

    • Wrap build command

    • Add scripts configuration to package.json

      • “scripts”: {

    “Build “: “sass SCSS /main.scss CSS /style.css –watch”, // “preserve”: “yarn build”, // NPM Scripts hook mechanism “serve”: “browser-sync . –files “css/*.css””, “start”: “run-p build serve”,

}

- yarn build - yarn serve-yarn start - The simplest way to automate the build workflow - yarn add browser-sync --dev - Used to start a test server to run the project. - yarn add NPM -run-all --dev - Run multiple tasks at the same time.Copy the code

Common automated build tools

Grunt

- Introduction - The first front-end build system - the plugin ecosystem is perfect - plug-ins can automate almost anything you want. - Disadvantages - The working process is implemented based on temporary files, so the build speed is correspondingly slow. - For example, to complete the sass file construction - first do the sass file compilation operation - then automatically add some private attributes prefix. - Then compress the code - Grunt has disk operations at each step of the process. - Basic use - initialize package.json file - yarn init --yes - Add grunt module - yarn add grunt - Add gruntfile.js file - code gruntfile.js - Grunt entry file - used to define tasks that need to be performed automatically by Grunt - needs to export a function that takes a Grunt parameter - Grunt is an object that provides some API for creating tasks - codeCopy the code
- module.exports = grunt ⥤ {grunt. RegisterTask ('taskName', () ⥤ {
         console.log('sjz')
     })

     grunt.registerTask('taskName1'.'Task Description', () ⥤ {
         console.log('sjz515')})// grunt. RegisterTask ('default', 'default task description ', () ⥤ {
     // console.log('sjz515')
     // })

     grunt.registerTask('default'['taskName'.'taskName1'])

     grunt.registerTask('async-task', () ⥤ {
         setTimeout(() ⥤ {console.log('sjz515')},1000)
     })

     grunt.registerTask('async-task1'.function () {
         const done = this.async()
         setTimeout(() ⥤ {console.log('sjz515')
              done()
          }, 1000)})}Copy the code
- yarn grunt taskName - yarn grunt taskName1 - yarn grunt - The default task does not need to be specified. - yarn grunt async-task-grunt Supports synchronization mode by default Description Console. log is not executed in the asynchronous task. Exports = grunt ⥤ {grunt. RegisterTask ('bad', 'yarn grunt async-task1 - Can be successfully executed - Flag task failed - module.exports = grunt ⥤ {grunt. () ⥤ {console.log(' SJZ ') return false}) grunt. RegisterTask ('async-task1', Function () {const done = this.async() setTimeout(()⥤{console.log('sjz515') done(false)}, 1000)})Copy the code

}

- If a task fails, subsequent tasks will not be executed. - You can specify the --force parameter to control whether a task fails to be executed. Exports = Grunt ⥤ {Grunt. InitConfig ({taskName: 'SJZ ', foo: {bar: 'SJZ'}}) grunt. RegisterTask ('taskName', () ⥤ {console.log(grunt. Config ('taskName'))}) grunt. () ⥤ {console.log(grunt. Config ('foo.bar'))})Copy the code

}

- yarn grunt taskName - yarn grunt foo - grunt Multi-target task - In multi-target mode, a task can be configured to form multiple sub-tasks. -module.exports = grunt ⥤ {grunt. InitConfig ({build: {options: {foo: 'bar'}, CSS: {options: {foo: 'baz'}}, js: '2' } }) grunt.registerMultiTask('build', function() { console.log('multi task~') console.log(`target: ${this.target}, data:${this.data}, options: ${this.options()}`) })Copy the code

}

- YARN grunt build - YARN grunt build: CSS - Use of the grunt plug-in -module.exports = grunt ⥤ {grunt. InitConfig ({exports = grunt.clean: {
             temp: 'temp/*.js'.temp1: 'temp/**',
         }
     })
    grunt.loadNpmTasks('grunt-contrib-clean')}Copy the code
- yarn grunt clean - yarn add grunt-contrib-clean - Implement common build tasks - yarn add grunt-sass sass -- dev-const sass = require('sass')Copy the code
const loadGruntTask = require('load-grunt-tasks')
module.exports = grunt ⥤ {grunt. InitConfig ({exports = grunt.sass: {
             options: {
                 sourceMap: true.implementation: sass
             },
             main: {
                  files: {
                     'dist/css/main.css': 'src/scss/main.scss'}}},babel: {
             options: {
                 sourceMap: true.presets: ['@babel/preset-env']},main: {
                  files: {
                     'dist/js/app.js': 'src/js/app.js'}}},watch: {
             js: {
                files: [' 'src/is/*.js], tasks: ['babel'] }, { css: { files: [''src/scss/*.scss], tasks: ['sass']}}}) // Grunt. LoadNpmTasks ('grunt-sass') loadgruntttasks (grunt -sass grunt.registerTask('default', ['sass', 'babel', 'watch']) }Copy the code
- yarn grunt sass - yarn grunt babel - yarn grunt watch - yarn grunt - yarn add grunt-babel @babel/core @babel/preset-env -- dev-yarn add load-grunt-tasks -- dev-yarn add grunt-contrib-watch --dev - has mostly receded from the historical stageCopy the code

Gulp

- Introduction - Recommended - A good solution to the problem of Grunt's slow build - everything is done in memory. - Multiple tasks can be executed at the same time by default. - The usage is more intuitive than Grunt. - The plugin ecosystem is also very well developed. - The most popular front-end construction system on the market at present - basic use - core features: - yarn init --yes - initialize package.json file - install Gulp module - yarn add Gulp --dev - Install Gulp module - CLI module - Create gulpfile.js file - code Gulpfile.js - gulp entry file - defines tasks by exporting member functions - has removed the synchronous code mode in the latest gulp, specifying that each task must be asynchronous. On the code -Copy the code

- gulpfile.js

- exports.foo = done ⥤ {
    console.log('sjz')
    done() // Indicate that the task is complete
}
Copy the code
- yarn gulp foo - exports.default = done ⥤ {console.log('default SJZ ') done() // Indicates that the task is completeCopy the code

}

-yarn gulp -gulp4.0 -const gulp = require('gulp') -gulp.task ('bar', done ⥤{Copy the code
  console.log('bar')
   done()
})

Copy the code
-yarn gulp bar -const {series, parallel} = require ('gulp')Copy the code
exports.task1 = done ⥤ {
    setTimeout(() ⥤ {console.log('sjz1')
       done() // Indicate that the task is complete
    }, 1000)

exports.task2 = done ⥤ {
    setTimeout(() ⥤ {console.log('sjz2')
       done() // Indicate that the task is complete
    }, 1000)

exports.task3 = done ⥤ {
    setTimeout(() ⥤ {console.log('sjz3')
       done() // Indicate that the task is complete
    }, 1000)}exports.foo = series(task1, task2, task3)
exports.bar = parallel(task1, task2, task3)

Copy the code
- yarn gulp foo - yarn gulp bar - three methods of gulp asynchronous task -exme. callback = done ⥤ {console.log(' SJZ callback') done() // Mark task completionCopy the code

}

exports.callback_error = done ⥤ {
    console.log('sjz callback_error')
    done(new Error('task failed')) // Indicate that the task is complete
}
Copy the code
- yarn gulp callback - yarn gulp callback_error-exports. promise = done ⥤ {console.log(' SJZ promise') return Promise.resolve()Copy the code

}

exports.promise_error = done ⥤ {
    console.log('sjz Promise error')
    return Promise.reject(new Error('task failed'))}Copy the code
			- yarn gulp promise
			- yarn gulp promise_error

		- constTimeout = time ⥤ {return new Promise(resolve ⥤ {
         setTimeout(resolve, time)
    })
}
exports.async = async () ⥤ {
    console.log('async task')
    await timeout(1000)}Copy the code
		- yarn gulp async

	- const fs = require('fs')
Copy the code
exports.stream = () ⥤ {
    console.log('sjz stream')
    const readStream = fs.createReadStream('package.json')
    const writeStream = fs.createReadStream('package.json')
    return 
}
exports.stream1 = done ⥤ {
    console.log('sjz stream1')
    const readStream = fs.createReadStream('package.json')
    const writeStream = fs.createWriteStream('temp.txt')
    readStream.pipe(writeStream)
    readStream.on('end', () ⥤ {done()})}Copy the code
-yarn gulp stream -gulp build process -const fs = require('fs')Copy the code
const {} = require('stream')

exports.default = () ⥤ {
    // File read stream
    const read = fs.createReadStream('normalize.css')
    // Write the file to the stream
    const write = fs.createWriteStream('normalize.min.css')
    / / transition flow
    const transform = new Transform({
        transform: (chunk, encoding, callback) ⥤ {
           // The core conversion process is implemented
           // chunk ⥤ What is read in the read stream (Buffer)
           const input = chunk.toString()
           input.replace(/\s+/g.' ').replace(/ / \ \ *. +? \*\//g.' ')
           callback(null, input)
        }
    })
    // Import the read file into the write file stream
    read
            .pipe(transform) / / conversion
            .pipe(write) / / write
    return read
}
Copy the code
-const {SRC, dest} = require('gulp') -yarn gulp - the streaming build system - const {SRC, dest} = require('gulp')Copy the code
const cleanCss = require('gulp-clean-css')
const rename = require('gulp-rename')
exports⥤. Default = () {return src('src/*.css')
    .pipe(cleanCss())
    .pipe(rename({ extname: '.min.css' }))
    .pipe(dest('dist'))}Copy the code
- yarn gulp -yarn add gulp-clean-css -- dev-yarn add gulp-rename -- dev-gulp Automatic build cases - Prepare web application cases to be built. - git clone https://github.com/zce/zce-gulp-demo - open directory - code with vscode zce - gulp - demo/web application case analysis - public directory - Files that do not need to be processed and will be copied directly to the build folder - SRC directory - where code is written during development - all files in this folder will be built. -yarn add gulp --dev - create gulpfile.js file as an entry file - style compile task - const {SRC, dest} = require('gulp')Copy the code
const sass = require('gulp-sass')
exportsStyle = () ⥤ {return src('src/assets/styles/*.scss', { base: 'src' } )
        .pipe(sass({ outputStyle: 'expanded' }))
        .pipe(dest('dist'))}module.exports = {
     style
}
Copy the code
-yarn gulp style -yarn add gulp-sass --dev - script file compilation -const {SRC, dest} = require('gulp')Copy the code
const babel = require('gulp-babel')
exports.script = () ⥤ {
    return src('src/assets/scripts/*.js', { base: 'src' } )
        .pipe(babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))}module.exports = {
     script
}
Copy the code
-yarn gulp script -yarn add gulp-babel -- dev-yarn add @babel/ core@babel /preset-env --dev - page file compilation task -const {SRC, preset) dest } = require('gulp')Copy the code
const swig = require('gulp-swig')

const data = {
    menus: [].pkg: require('package.json'),
    date: new Date()}exports.page = () ⥤ {
    return src('src/*.html', { base: 'src' } )
        .pipe(swig({ data }))
        .pipe(dest('dist'))}module.exports = {
     page
}

Copy the code
-yarn add gulp-swig --dev - gulp- const {SRC, dest} = require('gulp') -yarn add gulp-swig --dev - gulp- const {SRC, dest} = require('gulp')Copy the code
const imagemin = require('gulp-imagemin')
exports.image = () ⥤ {
    return src('src/assets/images/**', { base: 'src' } )
        .pipe(imagemin())
        .pipe(dest('dist'))}exports.font = () ⥤ {
    return src('src/assets/fonts/**', { base: 'src' } )
        .pipe(imagemin())
        .pipe(dest('dist'))}module.exports = {
     image,
     font
}
Copy the code
-yarn gulp image -yarn gulp gulp font -yarn add gulp-imagemin --dev - gulp-imagemin -- const {SRC, dest} = require('gulp')Copy the code
exports.extra = () ⥤ {
    return src('public/**', { base: 'public' } )
        .pipe(dest('dist'))}module.exports = {
     extra
}
Copy the code
-- dev-const loadPlugins = require('gulp-load-plugins')Copy the code
constPlugins = loadPlugins() - replaceCopy the code
- const {SRC, dest} = require('gulp')Copy the code
exportsStyle = () ⥤ {return src('src/assets/styles/*.scss', { base: 'src' } )
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest('dist'))}module.exports = {
     style
}
Copy the code
-yarn gulp style -yarn add gulp-sass --dev - script file compilation -const {SRC, dest} = require('gulp')Copy the code
exports.script = () ⥤ {
    return src('src/assets/scripts/*.js', { base: 'src' } )
        .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))}module.exports = {
     script
}

Copy the code
-yarn gulp script -yarn add gulp-babel -- dev-yarn add @babel/ core@babel /preset-env --dev - page file compilation task -const {SRC, preset) dest } = require('gulp')Copy the code
const data = {
    menus: [].pkg: require('package.json'),
    date: new Date()}exports.page = () ⥤ {
    return src('src/*.html', { base: 'src' } )
        .pipe(plugins.swig({ data }))
        .pipe(dest('dist'))}module.exports = {
     page
}
Copy the code
-yarn add gulp-swig --dev - gulp- const {SRC, dest} = require('gulp') -yarn add gulp-swig --dev - gulp- const {SRC, dest} = require('gulp')Copy the code
exports.image = () ⥤ {
    return src('src/assets/images/**', { base: 'src' } )
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))}exports.font = () ⥤ {
    return src('src/assets/fonts/**', { base: 'src' } )
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))}module.exports = {
     image,
     font
}
Copy the code
- yarn gulp image-yarn gulp font -yarn add gulp-imagemin --dev - hot update development server -yarn add browser-sync -- dev-const browserSync = require('browser-sync')Copy the code
const bs = browserSync.create()
exports.serve = () ⥤ {bs.init({notify: false.port: 2080.files: 'dist/**'.open: true.server: {
            baseDir: 'dist'.routes: {
               '/node_modules': 'node_modules'}}})}module.exports = {
     serve
}
Copy the code
- const {SRC, dest, parallel, series, watch} = require('gulp') -yarn gulp serve - const {SRC, dest, parallel, series, watch} = require('gulp')Copy the code
const browserSync = require('browser-sync')
const bs = browserSync.create()
exports.serve = () ⥤ {watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)
Copy the code
// The following listener has no meaning when developing, Need to comment out / / watch (' SRC/assets/images / * *, image) / / watch (' SRC/assets/fonts / * *, the font) / / watch (' public / * *, extra) watch([ 'src/assets/images/**', 'src/assets/fonts/**', 'public/**' ], bs.reload) bs.init({ notify: false, port: 2080, files: 'dist/**', open: true, server: { baseDir: ['dist', 'src', 'public'], routes: { '/node_modules': 'node_modules' } } })Copy the code
}

module.exports = {
     clean,
     serve
}

Copy the code
- yarn gulp clean - yarn gulp serve - Problem - Swig template engine cache mechanism may cause the page will not change. Const {SRC, dest, parallel} = require('gulp')Copy the code
const compile = parallel(style, script, page, image, font)
module.exports = {
     compile
}
Copy the code
- yarn gulp compile - Build task -Copy the code
const { src, dest, parallel, series } = require('gulp')
const del = require('del')
constClean = () ⥤ {return del(['dist'])}const compile = parallel(style, script, page)
// Tasks performed before going online
const build = series(clean, parallel(compile, image, font, extra))
module.exports = {
     build,
     clean,
     develop
}
Copy the code
- yarn gulp build - yarn gulp clean - yarn add del - dev - development tasks - const develop = series (the compile, Reload - const {SRC, dest} = require('gulp')Copy the code
exportsStyle = () ⥤ {return src('src/assets/styles/*.scss', { base: 'src' } )
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest('dist'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     style
}
Copy the code
-yarn gulp style -yarn add gulp-sass --dev - script file compilation -const {SRC, dest} = require('gulp')Copy the code
exports.script = () ⥤ {
    return src('src/assets/scripts/*.js', { base: 'src' } )
        .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     script
}

Copy the code
-yarn gulp script -yarn add gulp-babel -- dev-yarn add @babel/ core@babel /preset-env --dev - page file compilation task -const {SRC, preset) dest } = require('gulp')Copy the code
const data = {
    menus: [].pkg: require('package.json'),
    date: new Date()}exports.page = () ⥤ {
    return src('src/*.html', { base: 'src' } )
        .pipe(plugins.swig({ data }))
        .pipe(dest('dist'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     page
}
Copy the code
-yarn add gulp-swig --dev - const {SRC, dest, parallel, series, watch} = require('gulp') -yarn add gulp-swig --dev - const {SRC, dest, parallel, series, watch} = require('gulp')Copy the code
const browserSync = require('browser-sync')
const bs = browserSync.create()
exports.serve = () ⥤ {watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)
Copy the code
// The following listener has no meaning when developing, Need to comment out / / watch (' SRC/assets/images / * *, image) / / watch (' SRC/assets/fonts / * *, the font) / / watch (' public / * *, extra) watch([ 'src/assets/images/**', 'src/assets/fonts/**', 'public/**' ], bs.reload) bs.init({ notify: false, port: 2080, // files: 'dist/**', open: true, server: { baseDir: ['dist', 'src', 'public'], routes: { '/node_modules': 'node_modules' } } })Copy the code

}


const develop = series(compile, serve)

module.exports = {
     clean,
     serve,
     develop
}

Copy the code
-yarn gulp build-yarn add gulp-useref -- dev-const {SRC, dest } = require('gulp')Copy the code
exports.useref = () ⥤ {
    return src('dist/*.html', { base: 'dist' } )
        .pipe(plugins.useref({ searchPath: ['dist'.'. '] }))
        .pipe(dest('dist'))}module.exports = {
     useref
}
Copy the code
-yarn gulp useref - compression HTML, CSS, JS - const {SRC, dest} = require('gulp')Copy the code
exports.useref = () ⥤ {
    return src('dist/*.html', { base: 'dist' } )
        .pipe(plugins.useref({ searchPath: ['dist'.'. ']}))// html,js,css
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
             collapseWhitespace: true.minifyCSS: true.minifyJS: true,
         })))
        .pipe(dest('release'))}module.exports = {
     useref
}

Copy the code
- yarn gulp compile - yarn gulp useref - yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev - yarn add gulp-if --dev - Redesign the build process - clean -Copy the code
const { src, dest, parallel, series } = require('gulp')
const del = require('del')
constClean = () ⥤ {return del(['dist'.'temp'])}const compile = parallel(style, script, page)
// Tasks performed before going online
const build = series(clean, parallel(compile, image, font, extra))
module.exports = {
     build,
     clean,
     develop
}

Copy the code
- const {SRC, dest} = require('gulp')Copy the code
exportsStyle = () ⥤ {return src('src/assets/styles/*.scss', { base: 'src' } )
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     style
}

Copy the code
-yarn gulp style -yarn add gulp-sass --dev - script file compilation -const {SRC, dest} = require('gulp')Copy the code
exports.script = () ⥤ {
    return src('src/assets/scripts/*.js', { base: 'src' } )
        .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     script
}
Copy the code
-yarn gulp script -yarn add gulp-babel -- dev-yarn add @babel/ core@babel /preset-env --dev - page file compilation task -const {SRC, preset) dest } = require('gulp')Copy the code
const data = {
    menus: [].pkg: require('package.json'),
    date: new Date()}exports.page = () ⥤ {
    return src('src/*.html', { base: 'src' } )
        .pipe(plugins.swig({ data }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     page
}
Copy the code
-yarn add gulp-swig -- dev-serve-const {SRC, dest, parallel, series, watch } = require('gulp')Copy the code

const browserSync = require('browser-sync')
const bs = browserSync.create()
exports.serve = () ⥤ {watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)
Copy the code
// The following listener has no meaning when developing, Need to comment out / / watch (' SRC/assets/images / * *, image) / / watch (' SRC/assets/fonts / * *, the font) / / watch (' public / * *, extra) watch([ 'src/assets/images/**', 'src/assets/fonts/**', 'public/**' ], bs.reload) bs.init({ notify: false, port: 2080, // files: 'dist/**', open: true, server: { baseDir: ['temp', 'src', 'public'], routes: { '/node_modules': 'node_modules' } } })Copy the code

}

const develop = series(compile, serve)

module.exports = {
     clean,
     serve,
     develop
}
Copy the code
				- useref

					- const { src, dest } = require('gulp')
Copy the code
exports.useref = () ⥤ {
    return src('temp/*.html', { base: 'temp' } )
        .pipe(plugins.useref({ searchPath: ['temp'.'. ']}))// html,js,css
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
             collapseWhitespace: true.minifyCSS: true.minifyJS: true,
         })))
        .pipe(dest('dist'))}module.exports = {
     useref
}
Copy the code
- const build = series(clean, parallel(compile, useref), image, font, Extra) - YARN gulp build - yarn gulp develop - SupplementCopy the code
			- 

module.exports = {
     clean,
     build,
     develop
}
Copy the code
- "scripts": {"clean": "gulp clean", "build": "gulp build", "develop": "Gulp develop",} -yarn clean-yarn build-yarn develop -. Gitignore ignore file -dist - temp - How to extract the common automated build process in multiple projects? Gulpfile + Gulp = Gulpfile + Gulp CLI ⥤ zce-pages - create a repository zce-pages -cd.. - Yarn Global add zce-cli - Run the -zce init nm zce-pages -cd zce-pages -git init -git remote add Origin command -git status -git add. -git commit -m "feat: Initial commit" -git push -u origin master - Extract Gulpfile to module -code. -a - Copy the contents of gulpfile.js in zce-gulp-demo to lib/index.js in zce-pages. - Copy all development dependencies in package.json under zce-gulp-demo to package.json under zCE-pages as project dependencies. - Install dependencies in zce-pages. - yarn - Delete the contents of gulpfile.js in zce-gulp-demo. - Delete the development dependencies in package.json in zce-gulp-demo Delete the node_modules folder under zCE-gulp-demo. - Use zCE-pages in zCE-gulp-demo. - Use yarn link - yarn link "zCE-pages" in zCE-pages Module. exports = require ('zce-pages') -yarn - yarn build - Gulp is not an internal command -yarn add gulp-cli -- dev-yarn build - Error: Local gulp not found -yarn add gulp -- dev-yarn build - Error: } Cannot find module './package.json' -do a new file called pages. Config. js in zce-gulp-demo. [], pkg: require('package.json'), date: Const {SRC, dest} = require('gulp') new Date()}} - update lib/index.js - const {SRC, dest} = require('gulp')Copy the code

const cwd = process.cwd()
let config = {
   // default config
}

try {
   const loadConfg = require(`${cwd}/pages.config.js`)
   config = Object.assign({}, config, loadConfig)
} catch(e) {}

exports.page = () ⥤ {
    return src('src/*.html', { base: 'src' } )
        .pipe(plugins.swig({ data: config.data }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     page
}
Copy the code
						- yarn gulp page
						- yarn build

							- Cannot find module '@babel/preset-env'
							- const { src, dest } = require('gulp')
Copy the code
exports.script = () ⥤ {
    return src('src/assets/scripts/*.js', { base: 'src' } )
        .pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     script
}
Copy the code
Lib /index.js - const {SRC, dest} = require('gulp')Copy the code

const cwd = process.cwd()
let config = {
   // default config
   build: {
       src: 'src'.dist: 'dist'.temp: 'temp'.public: 'public'.paths: {
           styles: 'assets/styles/*.scss'.scripts: 'assets/scripts/*.js'.pages: '*.html'.images: 'assets/images/**'.fonts: 'assets/fonts/**'.styles: 'assets/styles/*.scss',}}}try {
   const loadConfg = require(`${cwd}/pages.config.js`)
   config = Object.assign({}, config, loadConfig)
} catch(e) {}

exports.page = () ⥤ {
    return src('src/*.html', { base: 'src' } )
        .pipe(plugins.swig({ data: config.data }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))module.exports = {page} - Replaces dead constants. Exports = {page} - Replaces dead constantsCopy the code
						- clean

		
Copy the code
					- 
const { src, dest, parallel, series } = require('gulp')
const del = require('del')
constClean = () ⥤ {return del(config.build.dist, config.build.temp])
}
const compile = parallel(style, script, page)
// Tasks performed before going online
const build = series(clean, parallel(compile, image, font, extra))
module.exports = {
     build,
     clean,
     develop
}
Copy the code
						- style

							- const { src, dest } = require('gulp')
Copy the code
exportsStyle = () ⥤ {return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src } )
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     style
}

Copy the code
						- script

							- const { src, dest } = require('gulp')
Copy the code
exports.script = () ⥤ {
    return src(config.build.paths.scripts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     script
}
Copy the code
						- page

							- const { src, dest } = require('gulp')
Copy the code

const cwd = process.cwd()
let config = {
   // default config
}

try {
   const loadConfg = require(`${cwd}/pages.config.js`)
   config = Object.assign({}, config, loadConfig)
} catch(e) {}

exports.page = () ⥤ {
    return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src } )
        .pipe(plugins.swig({ data: config.data }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}}))module.exports = {
     page
}

Copy the code
						- image/font

							- const { src, dest } = require('gulp')
Copy the code
const imagemin = require('gulp-imagemin')
exports.image = () ⥤ {
    return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src }  )
        .pipe(imagemin())
        .pipe(dest(config.build.dist))
}
exports.font = () ⥤ {
    return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src }  )
        .pipe(imagemin())
        .pipe(dest(config.build.dist))
}

module.exports = {
     image,
     font
}
Copy the code
						- extra

							- const { src, dest } = require('gulp')
Copy the code
exports.extra = () ⥤ {
    return src('* *', { base: config.build.public } )
        .pipe(dest(config.build.dist))
}

module.exports = {
     extra
}

Copy the code
						- serve

							- const { src, dest, parallel, series, watch } = require('gulp')
Copy the code

const browserSync = require('browser-sync')
const bs = browserSync.create()
exportsServe = () ⥤ {watch (config. Build. Paths. Styles, {cwd: config.build.src }, style)
    watch(config.build.paths.scripts, { cwd: config.build.src }, script)
    watch(config.build.paths.pages, { cwd: config.build.src }, page)
Copy the code
// The following listener has no meaning when developing, Need to comment out / / watch (' SRC/assets/images / * *, image) / / watch (' SRC/assets/fonts / * *, the font) / / watch (' public / * *, extra) watch([ config.build.paths.images, config.build.paths.fonts, // 'public/**' ], { cwd: config.build.src }, bs.reload) watch([ '**' ], { cwd: config.build.public }, bs.reload) bs.init({ notify: false, port: 2080, // files: 'dist/**', open: true, server: { baseDir: [config.build.temp, config.build.src, config.build.public], routes: { '/node_modules': 'node_modules' } } }) }Copy the code

const develop = series(compile, serve)

module.exports = {
     clean,
     serve,
     develop
}

Copy the code
						- useref

							- const { src, dest } = require('gulp')
Copy the code
exports.useref = () ⥤ {
    return src(config.build.paths.pages, { base: config.build.temp, cwd: config.build.temp } )
        .pipe(plugins.useref({ searchPath: [config.build.temp, '. ']}))// html,js,css
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
             collapseWhitespace: true.minifyCSS: true.minifyJS: true,
         })))
        .pipe(dest(config.build.dist))
}

module.exports = {
     useref
}

Copy the code
- yarn build-zce-gulp - addpages. Config. js = {Copy the code
  build: {
       src: 'src'.dist: 'release'.temp: '.tmp'.public: 'public'.paths: {
           styles: 'assets/styles/*.scss'.scripts: 'assets/scripts/*.js'.pages: '*.html'.images: 'assets/images/**'.fonts: 'assets/fonts/**'.styles: 'assets/styles/*.scss',}}data: {
         menus: [].pkg: require('package.json'),
         date: new Date()}}Copy the code
- Package Gulp CLI - Delete the gulpfile.js file in zce-gulp-demo. - yarn Gulp - No gulpfile found - yarn Gulp --gulpfile /node_modules/zce-pages/lib/index.js - Task never defined: Default-yarn gulp build --gulpfile./node_modules/zce-pages/lib/index.js - Working directory change to D:\zce\Desktop\zce-gulp-demo\node_modules\zce-pages\lib - yarn gulp build --gulpfile /node_modules/zce-pages/lib/index.js -- cwd. - This file runs normally, but parameter transmission is complicated. - Create the bin/zce-pages file in the zce-pages directory as the CLI entry file. - "bin": "bin/zce-pages. Js "- "bin": {Copy the code
   zp: "zce-pages"
}

Copy the code
- Prone to conflict - content - #! /usr/bin/env nodeCopy the code

console.log("zce/pages") -Copy the code
- 1, yarn unlink - 2, yarn link - You can directly run the command line file bin/zce-pages. Zce /pages - Contents - #! /usr/bin/env nodeCopy the code

require('gulp/bin/gulp') -Copy the code
- Zce-pages - Problem: No gulpfile found - ContentsCopy the code
#! /usr/bin/env node
console.log(process.agv)
require('gulp/bin/gulp')
Copy the code
- Run zce-pages -- SDFS SDFS - Result:Copy the code
[
   'C:\\Develop\\node\\node'.'C:\\Users\\zce\\AppData\\Local\\Yarn\\Data\\link\\zce-pages\\bin\\zce-pages.js'.'--sdfs'.'sdfs'
]
Copy the code
- No gulpfile found - ContentsCopy the code
#! /usr/bin/env node
process.agv.push('--cwd')
process.agv.push(process.cwd())
process.agv.push('--gulpfile')
process.agv.push(require.resolve('.. '))
require('gulp/bin/gulp')
Copy the code
-use -cd.. -cd zce-gulp-demo-zce-pages build-ok ~ -publish and use the module - modify the files properties in package.json in the zce-pages directoryCopy the code
"files": [
    "bin"."lib"
]
Copy the code
- cd .. -cd zce-pages -git add. -git commit -m "feat: update package" -git push-yarn publish - - yarn publish - registry https://registry.yranpkg.com - use - CD.. - mkdir zce-pages-demo - CD zce-pages-demo - Vscode open - code. - Copy of zce - gulp - public/SRC/directory of the demo pages. Config. Js to zce - demo directory - initialization package. Json - yarn init - yes - yarn add zce - pages - the dev - yarn zce-pages build - add scripts to package.json - "scripts": {"clean": "zce-pages clean", "build": "zce-pages build", "develop": "zce-pages develop", }Copy the code

FIS

- Introduction - A build system launched by the front end team. - Initially only for their internal projects. - After open source, it became popular in China. - FIS is more of a bundle than a microkernel-specific build system such as Grunt/Gulp, which integrates as many of the typical requirements in our system as possible internally. - For example, we can easily handle things like resource loading, modular development, code deployment, and even performance optimization in FIS - because it is large and comprehensive, it is popular in many domestic projects. - Basic use of FIS - The core feature of FIS is a high degree of integration. It integrates the common build tasks and debugging tasks in the front-end daily development process internally. - Developers can configure the work we need to do in the build process with a simple configuration file - there are many built-in tasks - built-in Web Server for debugging, - YARN Global add FIS3 - Use Vscode to open the web application prepared in advance - code fis-sample-r-FIS3 release - Automatically build project to temporary directory under current logged-in user of OS :.fis3-temp - Put build result in current directory - fis3 release -d Output - only resource location done - no code conversion done - add fIS-conf.js file - content - fis.match('*.{js, scss, png}', {Copy the code

release: ‘/assets/$0’ })

- fis - special global object - $0 - represents the original directory structure of the current file - compile and compressCopy the code
Copy the code
  • summary

    • If you are a beginner, FIS is more suitable

      • But if your requirements are flexible, Gulp/Grunt is a better choice.
    • Novices need rules, and veterans generally crave freedom.

      • It is for this reason that small but beautiful tools like Grunt/Gulp are popular.