I. Automated builds

1. Introduction

  • Automate the conversion of development source code to production code

  • Enabling automated builds

    • npm scripts

      • package.json

        {" name ":" my - auto - build1 ", "version" : "1.0.0", "description" : "my - auto - build1", "main" : "index. Js", "scripts" : { "build": "sass ./scss/main.scss ./css/style.css --watch", "serve": "Browser-sync. --files./ SCSS /main. SCSS ", "start": "run-p build serve"}, "author":" comfort-source ", "license": "MIT", "dependencies" : {" browser - sync ":" ^ 2.26.13 ", "NPM - run - all" : "^ 4.1.5", "sass" : "^ 1.29.0"}}Copy the code

2. Common automated build tools

  • grunt

    • The earliest front-end build system

    • Implemented based on temporary files

    • The basic use

      • Initialization package. Json

      • Install grunt, yarn add grunt –dev

        /** * The Grunt entry file is used to define tasks that need to be performed automatically by Grunt * a function needs to be exported * the function takes a formal parameter of Grunt, // module.exports = grunt => {// register a task // first argument is the name of the task // second argument is the program that executes the task grunt. RegisterTask ('foo', () => {console.log('hello grunt')}) // If the second argument is a string, Grunt. RegisterTask ('bar', 'task description ', () => {console.log('other task')}) // If the task name is default, the task will be called the default task, // grunt. RegisterTask ('default', () => {// console.log('default task') //}) // map other tasks, pass the second argument to an array, Grunt. RegisterTask ('default', ['foo', 'bar']) // support for asynchronous tasks // Async () grunt. RegisterTask ('async-task', function() { const done = this.async() setTimeout(() => { console.log('async task') done() }, 2000) }) }Copy the code
    • Mark failure to let the task

      /** * The Grunt entry file is used to define tasks that need to be performed automatically by Grunt * a function needs to be exported * the function takes a formal parameter of Grunt, // module.exports = grunt => {// exports failed. // --force can skip the failed task grunt. RegisterTask ('fail-task', () => {console.log('fail Task ') return false}) // Give the done method a false argument to mark the task failed grunt.registerTask('fail-async-task', function(){ const done = this.async() setTimeout(() => { console.log('fail async task') done(false) }, 2000) }) }Copy the code
    • Grunt configuration method

      Module.exports = grunt => {// this method accepts an object as an argument // the object property name is the same as the task name // the property value can be any type of data grunt. InitConfig ({// foo: 'bar' foo: { bar: 123}}) // grunt. Config () gets the configuration grunt. RegisterTask ('foo', () => { // console.log(grunt.config('foo')) // bar console.log(grunt.config('foo.bar')) // 123 }) }Copy the code
    • Multiobjective mission

      Module.exports = grunt => {// set task target through initConfig // Target must be an object // Run the specified target build: CSS // in initConfig all properties are targets, Grunt. InitConfig ({build: {// as the configuration option for the task options: {foo: 'bar'}, CSS: '1', js: '2'}}) // Define multi-objective tasks with grunt. ResgisterMultiTask () // Multi-objective tasks need to be configured with different objectives // Receive two parameters // the first parameter: task name // the second parameter: Grunt. RegisterMultiTask ('build', function () {console.log(' target: ${this.target}, data: ${this.data}`) }) }Copy the code
    • Use of plug-ins

      • Use process

        • Install the plug-in through NPM

        • Load the plug-in in gruntfile

        • Use the plug-in according to its configuration documentation

          /** * grunt-contrib-clean */ module.exports = grunt => {grunt. InitConfig ({clean: {// temp: contrib-clean */ module.exports = grunt => {grunt. 'temp/app.js' temp: 'temp/*.txt'}}) // grunt. LoadNpmTasks () Loads tasks provided by the plugin grunt. LoadNpmTasks ('grunt-contrib-clean')}Copy the code
    • Common plug-ins

    • To install grunt-sass, run yarn add grunt-sass sass –dev

    • To install grunt-babel, yarn add grunt-babel@babel/core@babel /preset-env –dev

    • Install the load-grunt- Tasks module to reduce the use of grunt. LoadNpmTasks ()

    • Install the grunt-contrib-watch module and yarn add grunt-contrib-watch –dev, which monitors file modifications and automatically compilers

      const sass = require('sass') const loadGruntTasks = require('load-grunt-tasks') module.exports = grunt => { grunt.initConfig({ 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/js/*.js'], tasks: ['babel'] }, css: { files: ['./src/scss/*.scss'], tasks: Grunt. RegisterTask ('default', ['sass', 'Babel ', 'watch'])}Copy the code
  • gulp

    • Memory-based implementation

    • The basic use

      • Initialize package.json, yarn init

      • To install gulp, run yarn add gulp –dev

      • Gulp defines tasks by exporting function members

        Done => {console.log('foo task') done()} // If the exported task is default, Exports.default = done => {console.log('default task') done()}Copy the code
    • Combination of task

      • Series a serial

      • The parallel parallel

        const { series, parallel } = require('gulp') const task1 = done => { setTimeout(() => { console.log('task1') done() }, 1000) } const task2 = done => { setTimeout(() => { console.log('task2') done() }, 1000) } const task3 = done => { setTimeout(() => { console.log('task3') done() }, } // serial tasks exports.foo = series(task1, task2, task3) // parallel tasks exports.bar = parallel(task1, task2, task3)Copy the code
      • Asynchronous tasks

        Callback = done => {console.log('callback') done()} // error task // gulp // If the gulp task fails, Exports. callback_error = done => {console.log('callback_error') done(new Error('task failed'))} // returns Promise = () => {console.log('promise task') // resolve Resolve ()} // returns failed Promise exports.promise_error = () => {console.log('promise_error ') Task ') return promise.reject (new Error('task failed'))} const timeout = time => {return new Promise(resolve) => { setTimeout(resolve, Async = async () => {await timeout(1000) console.log('async task')} // Exports.stream = () => {const readStream = fs.createreadStream ('package.json') const writeStream = fs.createWriteStream('temp.txt') readStream.pipe(writeStream) return readStream }Copy the code
      • Build the core working principles of the process

        Const fs = require('fs') const {Transform} = require('stream') exports. Default = () => {// file read stream const read = Fs.createreadstream ('normalize.css') // File write to stream const Write = fs.createWritestream ('normalize.min.css') // File conversion stream const transform = new Transform({ transform: (chunk, encoding, Callback) => {// core conversion process // chunk => what is read in the stream (buffer) const input = chunk.tostring () const output = input.replace(/\s+/g, '').replace(/\/\*.+?\*\//g, '') callback(null, Output)}}) // Write the read stream to normalize.min.css read. Pipe (transform) // convert. Pipe (write) // write return read}Copy the code
      • File manipulation API

        const { src, dest } = require('gulp') const cleanCss = require('gulp-clean-css') const rename = require('gulp-rename') Exports.default = () => {return SRC ('./ SRC /*.css') // read stream.pipe (cleanCss()) // zip css.pipe (rename({extname: '.min.css'})).pipe(dest('dist'))Copy the code
      • case

        • Install the module

          • To install gulp, run yarn add gulp –dev

          • To install gulp-sass, run yarn add gulp-sass –dev

          • Install gulp-babel, and yarn add gulp-babel@babel/core@babel /preset-env –dev

          • To install gulp-swig, run yarn add gulp-swig –dev

          • Install gulp-imagemin, yarn add gulp-imagemin –dev

          • Install gulp-load-plugins and yarn add gulp-load-plugins –dev

          • Install del, yarn add del –dev

          • Install browser-sync, yarn add browser-sync –dev

          • To install gulp-useref, run yarn add gulp-useref –dev

          • Install gulp-if, and yarn add gulp-if –dev

          • To install gulp-clean-css, run yarn add gulp-clean-css –dev

          • To install gulp-uglify, yarn add gulp-uglify –dev

          • Install gulp-htmlmin, yarn add gulp-htmlmin –dev

            const { src, dest, series, parallel, watch, Tree} = require('gulp') // remove file const del = require('del') // // Development server const browserSync = require('browser-sync') const bs = browsersync.create () // // SCSS conversion plugin // const sass = require('gulp-sass') // // es6 conversion plugin // const Babel = require('gulp-babel') // // // const imagemin = require('gulp-imagemin') const data = {{menus: [ { name: 'Home', icon: 'aperture', link: 'index.html' }, { name: 'Features', link: 'features.html' }, { name: 'About', link: 'about.html' }, { name: 'Contact', link: '#', children: [ { name: 'Twitter', link: 'https://twitter.com/w_zce' }, { name: 'About', link: 'https://weibo.com/zceme' }, { name: 'divider' }, { name: 'About', link: 'https://github.com/zce' } ] } ], pkg: require('./package.json'), date: New Date()} const clean = () => {return del(['dist', 'temp'])} const style = () => { Return SRC ('./ SRC /assets/styles/*. SCSS ', {base: // Specify {outputStyle: expanded}. Pipe (plugins.sass({outputStyle: expanded}). 'expanded'}). Pipe (dest('temp')) // Specify {stream: true} to push to the browser as a stream. Pipe (bs.reload({stream: True}))} const script = () => {return SRC ('./ SRC /assets/scripts/*.js', {base: 'SRC'}) ['@babel/preset-env']} Conversion plugins.babel({presets: presets: preset) ['@babel/preset-env'] })) .pipe(dest('temp')) .pipe(bs.reload({ stream: true })) } const page = () => { return src('./src/*.html', { base: 'src' }) .pipe(plugins.swig({ data, defaults: Pipe (dest('temp')).pipe(bs.reload({stream: true })) } const image = () => { return src('./src/assets/images/**', { base: 'src' }) .pipe(plugins.imagemin()) .pipe(dest('dist')) } const font = () => { return src('./src/assets/fonts/**', { base: 'src' }) .pipe(plugins.imagemin()) .pipe(dest('dist')) } const extra = () => { return src('./public/**', { base: 'public' }) .pipe(dest('dist')) } const serve = () => { watch('./src/assets/styles/*.scss', style) watch('./src/assets/scripts/*.js', script) watch('./src/*.html', page) // watch('./src/assets/images/**', image) // watch('./src/assets/fonts/**', font) // watch('./public/**', Extra) / / bs. Reload refresh service watch (['. / SRC/assets/images / * * ', '. / SRC/assets/fonts / * * 'and'.. / public / * *]. Bs.reload) // Initialize development server configuration bs.init({// turn off browser-sync nitify: false, // set port prot: // files: './dist/**', server: {// specify the site root directory baseDir: ['temp', 'SRC ', 'public'], // routes: {'/node_modules': Const useref = () => {return SRC ('./temp/*.html', {base: 'temp' }) .pipe(plugins.useref({ searchPath: [' temp ', '. ']})) / / file compression pipe (plugins. If ($/ / \. Js, plugins. Uglify ())), pipe (plugins. If ($/, / \. CSS Plugins.cleancss ())).pipe(plugins.if(/\.html$/, plugins.htmlmin({// collapseWhitespace: True, // Compress style minifyCSS: true, // compress script minifyJS: true }))) .pipe(dest('dist')) } const compile = parallel(style, script, page) const build = series(clean, parallel(series(compile, useref), image, font, extra)) const develop = series(compile, serve) module.exports = { clean, build, develop }Copy the code
    • Encapsulating workflow

      • Build workflow = gulpfile + gulp