Step by step explain how to use gulp for automatic construction

After the project is developed and launched, a series of preparations need to be made, including but not limited to:

  • Compress CSS, JavaScript and HTML files
  • If SASS or LESS is used, it needs to be compiled, otherwise the whole project cannot run
  • Similarly, if there is a version requirement for JavaScript, you also need to use babel to translate JavaScript, otherwise some functions cannot be realized
  • ...

If all processes are completed manually, it will take time and involve many human errors, so many automatic construction tools came into being.

Gulp is based on node JS is a front-end automated build tool for dealing with the problems listed above.

Basic use of gulp

Learn how to use single task, combined task and asynchronous operation to learn how to use gulp.

gulp's individual tasks

The basic use of gulp. Here, the version of gulp uses v4 For versions after 0, the syntax used is also the syntax of ES6.

  1. Create a new folder and initialize a node project structure

    gulp> mkdir gulp-sample
    gulp> cd .\gulp-sample\
    gulp-sample> yarn init
    
  2. Download and install gulp dependency package

    Because gulp is used to package projects in the development environment, you only need to install it in the development environment

    gulp-sample> yarn add gulp --dev
    
  3. Add a gulpfile in the root directory js

    gulpfile.js is the entry file of gulp, which is required.

    The first step is to try to have output on the command line to see if gulp can run normally

    gulpfile.js contents are as follows:

    // gulp entry file
    
    exports.default = () => {
      console.log('hello world');
    };
    

    v4. After 0, gulp defines a task by exporting a function, so here you can export a function directly through commonJS

    Exporting a function named default indicates that this is the default execution function

    Note: v3 The writing method of 0, that is, the way of passing in the task by calling the task() function, can also be run, but it is easier to use the writing method of arrow function

    const gulp = require('gulp');
    
    gulp.task('default', function () {
      console.log('hello world');
    });
    
  4. Run default function

    Run on terminal:

    gulp-sample> yarn gulp
    yarn run v1.22.10
    $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp
    [04:00:14] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
    [04:00:14] Starting 'default'...
    hello world
    [04:00:14] The following tasks did not complete: default
    [04:00:14] Did you forget to signal async completion?
    error Command failed with exit code 1.
    info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
    

    At [04:00:14] Starting 'default' After that, you can see the output of hello world, which means that there is no problem with the operation of gulp.

    However, an error message appears after the operation, saying:

    The following tasks did not complete: default

    That is, the task of default has not been completed.

  5. Solve the not complete error

    The error message appears because v4 After 0, the synchronous processing mechanism is cancelled, and all functions are treated as asynchronous functions. Therefore, an instruction needs to be passed to inform gulp that the task has been processed

    gulp itself includes this indicator in the function. The calling method is as follows:

    exports.default = (done) => {
      console.log('hello world');
    
      done(); // Indicates that the task is complete
    };
    

    Run again:

    gulp-sample> yarn gulp
     yarn run v1.22.10
     $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp
     [04:19:00] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
     [04:19:00] Starting 'default'...
     hello world
     [04:19:00] Finished 'default' after 2.53 ms
     Done in 1.17s.
    

Combined tasks of gulp

It is mainly completed through two functions provided by gulp. The main code is:

const { series, parallel } = require('gulp');

const task1 = (done) => {
  setTimeout(() => {
    console.log('task1 done');
    done();
  }, 2000);
};

const task2 = (done) => {
  setTimeout(() => {
    console.log('task2 done');
    done();
  }, 1000);
};

const task3 = (done) => {
  setTimeout(() => {
    console.log('task3 done');
    done();
  }, 1000);
};

series

Serial task

Using serial tasks, you must complete the specified task before completing the next task. Application scenarios include: compiling SASS first, and then deploying CSS code

exports.seriesTask = series(task1, task2, task3);

Terminal operation:

  gulp-sample> yarn gulp seriesTask
  yarn run v1.22.10
  $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp seriesTask
  [05:00:42] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
  [05:00:42] Starting 'seriesTask'...
  [05:00:42] Starting 'task1'...
  task1 done
  [05:00:44] Finished 'task1' after 2.02 s
  [05:00:44] Starting 'task2'...
  task2 done
  [05:00:46] Finished 'task2' after 2 s
  [05:00:46] Starting 'task3'...
  task3 done
  [05:00:48] Finished 'task3' after 2.01 s
  [05:00:48] Finished 'seriesTask' after 6.04 s
  Done in 7.22s.

It can be seen that there is a sequence of execution, and although task1 takes more time than others - task1 needs to wait 2 seconds and the other two wait 1 second - task1 is still executed and completed first.

parrllel

Parallel task

Using parallel tasks does not interfere with each other. Application scenarios include: you can compile CSS and JavaScript at the same time

exports.parallelTask = parallel(task1, task2, task3);

Terminal operation:

gulp-sample> yarn gulp parallelTask
  yarn run v1.22.10
  $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp parallelTask
  [05:02:23] Using gulpfile C:\assignmentF\front\gulp\gulp-sample\gulpfile.js
  [05:02:23] Starting 'parallelTask'...
  [05:02:23] Starting 'task1'...
  [05:02:23] Starting 'task2'...
  [05:02:23] Starting 'task3'...
  task2 done
  [05:02:24] Finished 'task2' after 1.02 s
  task3 done
  [05:02:24] Finished 'task3' after 1.02 s
  task1 done
  [05:02:25] Finished 'task1' after 2.01 s
  [05:02:25] Finished 'parallelTask' after 2.01 s
  Done in 3.31s.

In contrast, parallel is different here. task2 and task3 run before task1.

Asynchronous process processing operation of gulp

gulp has been upgraded to v4.0 After 0, each task is called asynchronously in the way of callback function. This makes it a problem to confirm whether the operation is completed. Here are the three most commonly used solutions that use JavaScript native operations.

VC & Delphi

As mentioned above, gulp v4 After 0, the synchronization operation has been cancelled. Instead, it receives the signal that the task has been completed by passing in an indicator - done, a callback function.

Therefore, when an error exception occurs, you can also notify gulp by calling the done() function and throwing an exception in the middle. The specific operation is the same as the callback function of native JavaScript, which is an error first mechanism.

It should be noted that once an exception is thrown, other tasks will be terminated and continue to run.

const { series, parallel } = require('gulp');

const task1 = (done) => {
  setTimeout(() => {
    console.log('task1 done');
    done();
  }, 2000);
};

const task2 = (done) => {
  setTimeout(() => {
    console.log('task2 done');
    // Modified here ↓
    done(new Error('task failed'));
    // Modified here ↑
  }, 1000);
};

const task3 = (done) => {
  setTimeout(() => {
    console.log('task3 done');
    done();
  }, 1000);
};

exports.seriesTask = series(task1, task2, task3);

exports.parallelTask = parallel(task1, task2, task3);

exports.default = (done) => {
  console.log('hello world');

  done(); // Indicates that the task is complete
};

Operation results:

  • series error

    gulp-sample> yarn gulp seriesTask
    yarn run v1.22.10
    $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp seriesTask
    [10:00:12] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
    [10:00:12] Starting 'seriesTask'...
    [10:00:12] Starting 'task1'...
    task1 done
    [10:00:14] Finished 'task1' after 2.01 s
    [10:00:14] Starting 'task2'...
    task2 done
    [10:00:15] 'task2' errored after 1.02 s
    [10:00:15] Error: task failed
        at Timeout._onTimeout (C:\assignment\front\gulp\gulp-sample\gulpfile.js:13:10)
        at listOnTimeout (internal/timers.js:554:17)
        at processTimers (internal/timers.js:497:7)
    [10:00:15] 'seriesTask' errored after 3.03 s
    error Command failed with exit code 1.
    info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
    

    You can see that an exception is thrown in task2 and task3 does not continue to run

  • parallel error

    gulp-sample> yarn gulp parallelTask
    yarn run v1.22.10
    $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp parallelTask
    [10:01:09] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
    [10:01:09] Starting 'parallelTask'...
    [10:01:09] Starting 'task1'...
    [10:01:09] Starting 'task2'...
    [10:01:09] Starting 'task3'...
    task2 done
    [10:01:10] 'task2' errored after 1.02 s
    [10:01:10] Error: task failed
        at Timeout._onTimeout (C:\assignment\front\gulp\gulp-sample\gulpfile.js:13:10)
        at listOnTimeout (internal/timers.js:554:17)
        at processTimers (internal/timers.js:497:7)
    [10:01:10] 'parallelTask' errored after 1.03 s
    error Command failed with exit code 1.
    info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
    

    You can see that task2 threw an exception here, and task1 and task3 did not continue to run

Using promise

Promise can be used to solve the problem that the code is too deeply nested. The specific method is to return promise:

const { series, parallel } = require('gulp');

const task1 = (done) => {
  setTimeout(() => {
    console.log('task1 done');
  }, 2000);
  return Promise.resolve('this will be ignored');
};

const task2 = (done) => {
  setTimeout(() => {
    console.log('task2 done');
  }, 1000);
  return Promise.reject(new Error('task2 failed'));
};

const task3 = (done) => {
  setTimeout(() => {
    console.log('task3 done');
    done();
  }, 1000);
};

exports.seriesTask = series(task1, task2, task3);

exports.parallelTask = parallel(task1, task2, task3);

Operation results:

gulp-sample> yarn gulp seriesTask
yarn run v1.22.10
$ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp seriesTask
[10:07:41] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
[10:07:41] Starting 'seriesTask'...
[10:07:41] Starting 'task1'...
[10:07:41] Finished 'task1' after 1.41 ms
[10:07:41] Starting 'task2'...
[10:07:41] 'task2' errored after 1.03 ms
[10:07:41] Error: task2 failed
    at task2 (C:\assignment\front\gulp\gulp-sample\gulpfile.js:14:25)
    at bound (domain.js:413:15)
    at runBound (domain.js:424:12)
    at asyncRunner (C:\assignment\front\gulp\gulp-sample\node_modules\async-done\index.js:55:18)
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
[10:07:41] 'seriesTask' errored after 6.61 ms
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Using async/await

Since promise can be used, you can also use the syntax sugar provided by ES7: async/await. As long as the node environment is more than 8, you can use async/await. The usage is as follows:

const { series, parallel } = require('gulp');

const timeout = (time) => {
  return new Promise((resolve) => {
    setTimeout(resolve, time);
  });
};

const task1 = async (done) => {
  await timeout(2000);
  console.log('task1 done');
};

const task2 = async (done) => {
  await timeout(1000);
  console.log('task2 done');
};

const task3 = async (done) => {
  await timeout(1000);
  console.log('task3 done');
};

exports.seriesTask = series(task1, task2, task3);

Operation results:

gulp-sample> yarn gulp seriesTask
yarn run v1.22.10
$ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp seriesTask
[10:14:36] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
[10:14:36] Starting 'seriesTask'...
[10:14:36] Starting 'task1'...
task1 done
[10:14:38] Finished 'task1' after 2.02 s
[10:14:38] Starting 'task2'...
task2 done
[10:14:39] Finished 'task2' after 1.01 s
[10:14:39] Starting 'task3'...
task3 done
[10:14:40] Finished 'task3' after 1.01 s
[10:14:40] Finished 'seriesTask' after 4.05 s
Done in 5.20s.

It can be seen that after using the syntax sugar of async/await, the code becomes more concise and readable.

The core of gulp construction process

In fact, the processing of documents is logically common, and the steps are:

  1. Manually copy and paste the file into the compression tool
  2. Get compressed results
  3. Paste the file back into the folder where you want to go online

The principle of using gulp is the same, but the original part of manual operation is transferred to the machine (code), which is faster and has a lower error rate.

Here, we will use node's native API to simulate the internal implementation process of gulp.

  1. The read of the created file is also written to the stream

    This step is the IO of the file, which is not very difficult:

    const fs = require('fs');
    
    exports.default = () => {
      // File read stream
      const read = fs.createReadStream('normalize.css');
      // File write stream
      const write = fs.createWriteStream('normalize.min.css');
    
      // Put the read file into the write stream
      read.pipe(write);
    
      return read;
    };
    

    default is exported here, so the operation mode is still yen gulp

    Operation results:

    gulp-sample> yarn gulp
     yarn run v1.22.10
     $ C:\assignment\front\gulp\gulp-sample\node_modules\.bin\gulp
     [10:32:21] Using gulpfile C:\assignment\front\gulp\gulp-sample\gulpfile.js
     [10:32:21] Starting 'default'...
     [10:32:21] Finished 'default' after 9.68 ms
     Done in 1.53s.
    

    Can see one with normalize The file with the same CSS content is exported.

    Normalize. Net is used here CSS uses Two common methods of CSS initialization For testing purposes, any file can be used.

  2. Compressed file

    This step will be implemented by using stream's API: Transform.

    const fs = require('fs');
    // Add file conversion stream
    const { Transform } = require('stream');
    
    exports.default = () => {
      // File read stream
      const read = fs.createReadStream('normalize.css');
      // File write stream
      const write = fs.createWriteStream('normalize.min.css');
    
      // File conversion stream
      const transform = new Transform({
        transform: (chunk, encoding, callback) => {
          // chunk => buffer
          const input = chunk.toString();
          const output = input
            // Remove all spaces
            .replace(/\s+/g, '')
            // Remove all comments
            .replace(/\/\*.+?\*\//g, '');
          callback(null, output);
        },
      });
    
      // The read file is first compressed and then put into the write stream
      read.pipe(transform).pipe(write);
    
      return read;
    };
    

    If the running command remains the same, the running result will be different:

    At this time, normalize Min.css has been compressed without retaining the original format.

It can be seen that the core of gulp is through file operation.

gulp file operation api

The main use method of gulp is to use the file operation method encapsulated by gulp, together with some plug-ins, and finally realize the processing of project files.

Here we will use some gulp encapsulated APIs for demonstration.

  1. File reading and writing

    const { src, dest } = require('gulp');
    
    exports.default = () => {
      // Create a read stream of files through src
      return src('src/normalize.css').pipe(dest('dist'));
    };
    

    In fact, this is step 1 corresponding to the core construction project, and the file is not compressed. The results after completion are as follows:

    It can be seen that the I/O effect is the same.

  2. Use of wildcards

    Compared with the native API provided by node, the biggest advantage of the API provided by gulp is that it can use wildcards:

    const { src, dest } = require('gulp');
    
    exports.default = () => {
      // Create a read stream of files through src
      // New wildcard
      return src('src/*.css').pipe(dest('dist'));
    };
    

    Then all css files in the src directory will be read and written to the dist folder:

  3. Compression conversion of files

    So far, the I/O of css files has been completed, but the compression has not yet been completed. The compression and conversion of css files can be completed with the help of a very mature plug-in: gulp clean css.

    Plug in installation:

    gulp-sample> yarn add gulp-clean-css --dev
    

    The method of using the plug-in is also very simple. Obtain the function through require, and then add it to the pipeline through pipe:

    const { src, dest } = require('gulp');
    
    const cleanCss = require('gulp-clean-css');
    
    exports.default = () => {
      // Create a read stream of files through src
      return src('src/*.css').pipe(cleanCss()).pipe(dest('dist'));
    };
    

    After you run the script again with yarn gulp, you can see that the compression of CSS is completed:

  4. Add rename plug-in

    The purpose is to rename the compressed file name to file Min.css, following standard naming conventions

    This function needs to be completed with the help of gulp rename plug-in, which is still installed in the development environment:

    gulp-sample> yarn add gulp-rename --dev
    

    Similarly, obtain the plug-in through require, and then add it to the pipeline:

    const { src, dest } = require('gulp');
    const cleanCss = require('gulp-clean-css');
    const rename = require('gulp-rename');
    
    exports.default = () => {
      // Create a read stream of files through src
      return src('src/*.css')
        .pipe(cleanCss())
        .pipe(rename({ extname: '.min.css' }))
        .pipe(dest('dist'));
    };
    

    Note that the use of rename function is different here. It needs to pass in a suffix.

    Results after running yarn gulp:

    You can see that two new files with the suffix min.css have been generated.

The above is the general process of gulp.

Keywords: Javascript Front-end gulp

Added by arya6000 on Sat, 29 Jan 2022 01:00:10 +0200