Develop scaffolding and encapsulate automated build workflows

I front-end small white a, just sort out their own learning process, the first time in nuggets published their own article, any questions welcome to point out in time

Definition of front-end engineering

Front-end engineering is a means of improving efficiency through tools that follow certain standards and specifications

Problem solved: Disadvantages of traditional languages or syntactically unable to use modular/componentized repetitive rote working code with uniform style, quality-dependent back-end service interfaces support overall dependency on back-end projectsCopy the code

engineering

All means aimed at improving efficiency, reducing cost and ensuring quality belong to engineering

Engineering ≠ toolsCopy the code

Engineering mainly includes the following contents:

· Scaffolding tool development

· Automated build systems

· Modular packaging

· Project code standardization

· Automated deployment

The scaffold

Resolve some of the complexities of creating front-end projects

The same organizational structure the same development paradigm the same modules rely on the same tools to configure the same code baseCopy the code

Scaffolding action

Commonly used scaffolding tools

Common scaffolding tools are frame-based, such as vuE-CLI for vUE projects

Yeoman: General purpose scaffolding tool

How to use Yeoman

Plop: Create specific types of files during development

How to use plop

General purpose scaffold tool analysis

The workflow of scaffolding is as follows: 1. Ask user questions through command line interaction; 2. Generate file 3 based on user feedback. Generate files based on the answers. 4. Export all files in the template to the target directory 5. 6. Write the result to the destination file pathCopy the code

Automated build tool

Grunt

One of the earliest automated build tools, less used today

Single objective mission

The entry configuration file of grunt is gruntfile.js, and the task is executed by creating registerTask. The default task name is default, and the task can be executed together. You can use YARN grunt –force to perform asynchronous tasks

//Grunt entry file
// Used to define tasks that need to be performed automatically by Grunt
// We need to export a function that takes a grunt argument

module.exports = grunt= > {
	// To create a task, run NPM run/yarn grunt foo
    grunt.registerTask('foo'.() = > {
        console.log("hello grunt")
        // Flag task failure by return false, which blocks subsequent composite tasks
        // You can run the --force command to ignore the failure without affecting subsequent combined tasks
        return false
    })
    // Default task
	grunt.registerTask('default'."Mission Description".() = > {
    	console.log("hello default grunt")})// Combine tasks
    grunt.registerTask("default"["foo"."bar"])
    // Asynchronous tasks
    grunt.registerTask("async-task".function(){
        const done = this.async()
        setTimeout(() = >{
            console.log("async...")
            // Flag the task as failed by calling the done method and passing false
            done(false)},1000)})}Copy the code

Multiobjective mission

Multi-objective tasks require registerMultiTask for task registration and grunt. InitConfig for multi-objective tasks

module.exports = grunt= > {
    grunt.initConfig({
        build: {
            //options as the configuration options of the task
            options: {foo:"bar"
            },
            css: {
                options: {foo:"baz"  // Overrides options in the task}},js: "2"
        }
    })

    grunt.registerMultiTask('build'.function () {
        console.log(this.options())
        console.log(`target:The ${this.target},data:The ${this.data}`)})}Copy the code

The above tasks are performed through grunt custom tasks. On the Official Grunt website, there are some commonly used grunt plug-ins www.gruntjs.net/plugins

Grunt -sass is used as an example. Grunt -sass relies on Sass to work, so you need to install both grunt-sass and sass when installing the dependency.

// Import plug-ins
const sass = require("sass")
/ / use
module.exports = grunt= > {
    grunt.initConfig({
        // Sass converts to CSS functionality
        sass: {
            options: {
                sourceMap: true.implementation: sass
            },
            main: {
                files: {
                    'dist/css/main.css': 'src/scss/main.scss'}}}})}// Method in grunt's official API to load grunt encapsulated plug-ins by loadNpmTasks
  // With this method, a registerTask can be executed without the need for registerTask
  grunt.loadNpmTasks('grunt-sass')
  
  / / execution
  yarn grunt sass
Copy the code

Of course, this loadNpmTasks approach requires a separate reference for each plug-in. We can use grunt plug-ins to reference all plug-ins, and initConfig the plug-ins that need to be used separately

/ / installation
yarn add load-grunt-tasks --dev
/ / use
const loadGruntTasks = require("load-grunt-tasks")
// Automatically loads all grunt plug-ins
loadGruntTasks(grunt) 
Copy the code

gulp

A flow-based build approach

The difference between gulp and Grunt is easy to use: using code over configuration policies, gulp makes simple things simple and complex tasks manageable. Efficient: Build faster by taking advantage of Node.js' powerful streams and eliminating the need to write intermediate files to disk. High quality: Gulp's strict plug-in guidelines ensure that plug-ins are simple and work the way you expect them to. Easy to learn: By keeping the API to a minimum, you can learn Gulp in a very short time. The build is just what you would expect: a series of flow pipes.Copy the code

The basic task

// The pass parameter in the arrow function is a callback function used to distinguish synchronous and asynchronous tasks
// New Error('task_error') can also be passed in done to mark an Error
exports.foo = done= > {
    console.log("foo task")
    done() // Indicate that the task is complete
    done(new Error('task_error')) // Indicates that the task failed
}
// You can also create tasks using task. It is not recommended
const gulp = require('gulp')
gulp.task('bar'.done= > {
    console.log("bar task")
    done()
})
Copy the code

Combined task: serial task series; Parallel task

// The difference between parallel tasks and serial tasks is that parallel tasks can be built at the same time without affecting each other, which improves the construction efficiency
// Serial tasks are tasks that need to be executed after the first task is completed
const { series, parallel, task } = require("gulp")
exports.task1 = series(foo, bar)  / / serial
exports.task2 = parallel(foo, bar)  / / parallel
/ / test
yarn gulp task1
yarn gulp task2
Copy the code

These are the basic concepts of GULP and are briefly summarized here

The pipe method performs file operations in turn, retrieves the desired file path from SRC in gulp, and returns the stream to the corresponding path through destCopy the code

The following is their own demo, with notes can view learning

Demo

// Gulp basic API
// SRC: the path of the file to be built
// dest: indicates the file path after the successful construction
// parallel: parallel task
// series: serial tasks
// watch: listening task
const { src, dest, parallel, series, watch } = require('gulp')
// Clear the target file
const del = require('del')
// Generate a browser server plug-in
const browserSync = require('browser-sync')
// Gulp plugin loads the library, similar to load-grunt-tasks
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
// Create browser server
const bs = browserSync.create()
// Target file root path
const cwd = process.cwd()

let config = {
    // Define some basic path variables
    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/**'}}}// By introducing gulp-load-plugins, we don't need to introduce them again
// sass == plugins.sass, so replace the following tasks with plugins.sass, and so on
// const sass = require('gulp-sass')
// const babel = require('gulp-babel')
// const swig = require('gulp-swig')
// const imagemin = require('gulp-imagemin')

// Define a variable
const data = {
    menus: [].pkg: require('./package.json'),
    data: new Date()}// Clean to clean the files in the target path
const clean = () = > {
    return del([config.build.dist, config.build.temp])
}
// sass to CSS
const style = () = > {
    return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })
    	// outputStyle This attribute is the default CSS built to be fully expanded, without closing braces at the end of the last attribute
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}}))/ / js compilation
const 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}}))/ / HTML compilation
const page = () = > {
    return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.swig({ data }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true}}))// Image compression
const image = () = > {
    return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
}
// Compress the font file
const font = () = > {
    return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
}
// Other path files compiled
const extra = () = > {
    return src('* *', { base: config.build.public, cwd: config.build.public })
        .pipe(dest(config.build.dist))
}
// Browser services
const serve = () = > {
	// Listen for the corresponding file modification, and then execute the following task
    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)
	// bs.reload automatically refreshes the browser after listening for the corresponding file changes
    watch([
        config.build.paths.images, 
        config.build.paths.fonts
    ], { cwd: config.build.src }, bs.reload)

    
    watch('* *', { cwd: config.build.public }, bs.reload)
    

    bs.init({
        notify: false.// Whether to display in the upper right corner
        port: 8000.// Set the port to 3000 by default
        // open: false, // Whether to automatically open the browser
        // files: 'dist/**',
        server: {
            // As an array, the image font page is only used to compress the volume during construction
            // Has no effect on the build test phase and only reduces the build efficiency
            If there is no file in dist folder, look down SRC to improve build efficiency
            // Build when it comes online
            baseDir: [config.build.temp, config.build.src, config.build.public],
            routes: {
                '/node_modules' : 'node_modules'}}})}// File compression
const useref = () = > {
    return src('temp/*.html', { base: 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('dist'))}// Combine tasks
const compile = parallel(style, script, page)

const build = series(clean, parallel(series(compile, useref), image, font, extra))

const develop = series(build, serve)

// Export tasks to be executed
module.exports = {
    clean,
    develop,
    compile,
    build
}
Copy the code

The above is my basic understanding of automated construction, if there is any mistake, I hope you put forward, learn and progress together