1. Basic use
As the most popular front-end construction system at present, gulP is characterized by high efficiency and easy use. The process of using gulp is very simple. The general process is to install gulp dependencies in your project and then create gulpfile to configure gulp.
npm init
npm install gulp --save
Copy the code
gulpfile.js
exports.foo = () = > {
console.log('foo');
}
Copy the code
This creates a gulp task for foo, and you can run gulp foo.
npx gulp foo
Copy the code
All tasks in gulp are asynchronous tasks and need to be marked as completed. You can receive a function in a function and call this function to indicate completion.
exports.foo = (done) = > {
console.log('foo');
done(); // End identifier
}
Copy the code
If the exported default task is displayed as the default task of gulp, you can run gulp without specifying the task name. Registering gulp tasks prior to gulp4.x required the Task method, which is no longer recommended.
const gulp = require('gulp');
gulp.task('foo'.done= > {
console.log('task')
done();
})
Copy the code
2. Group tasks
Series and Parallel combined tasks can be provided through the GULP module. Series is a function that can take any number of arguments, each of which is a task, and series automatically executes those tasks in sequence.
const { series } = require('gulp');
const t1 = done= > {
console.log('task 1')
done();
}
const t2 = done= > {
console.log('task 2')
done();
}
const t3 = done= > {
console.log('task 3')
done();
}
exports.foo = series(t1, t2, t3);
Copy the code
npx gulp foo
Copy the code
Series combines tasks in sequence. If you want to combine parallel tasks, you can use parallel. Task combinations are also useful, such as compiling JS and CSS, which can be compiled separately in parallel.
3. Asynchronous tasks
When an asynchronous task is called, it is not clear whether the task is finished or not. It is usually resolved by the callback function. Asynchronous tasks can be handled in GLUP via callback functions, known as done functions. You can pass an error message to the done function to prevent subsequent tasks from executing.
exports.foo = (done) = > {
console.log('foo');
done(new Error('Failed'); // End identifier
}
Copy the code
Gulp also supports promises by returning a Promise in a task, either resolve or Reject.
exports.foo = () = > {
console.log('foo');
return Promise.resolve()
}
Copy the code
Of course async and await are also possible, and functions whose tasks are defined as async type can use await.
exports.foo = async() = > {// await ....
console.log('foo');
return Promise.resolve()
}
Copy the code
If you can read a file using stream, return stream.
exports.foo = () = > {
console.log('foo');
const readStream = fs.createReadStream('a.json');
const writeStream = fs.createWriteStream('b.json');
readStream.pipe(writeStream);
return readStream; // Register the end event to call done
}
Copy the code
4. Core principles
The build process is basically reading out the file and converting it and writing it to the appropriate location, which was done manually in the old days and with gulp it can be done automatically in the code.
const fs = require('fs');
const { Transform } = require('stream');
exports.default = () = > {
// Create a file read stream
const read = fs.createReadStream('a.css');
// Write the file to the stream
const write = fs.createWriteStream('b.css');
// File conversion
const transform = new Transform({
transform: (chunk, encoding, callback) = > {
// chunk is read content, i.e. stream
// Delete comments with re delete Spaces
const input = chunk.toString();
const output = input.replace(/\s+/g.' ').replace(/ / \ \ *. +? \*\//g.' '); callback(output); }})// The read file is written to the corresponding file
read.pipe(transform).pipe(write);
return read;
}
Copy the code
Gulp is officially defined as a stream-based build system. Gulp implements the concept of a pipeline.
5. File operations
Gulp has its own read and write streams, which are much more useful than Node.
const { src, dest } = require('gulp');
const cleanCss = require('gulp-clean-css');
const rename = require('gulp-rename');
export.default = () = > {
return src('src/a.css').pipe(cleanCss()).pipe(rename({ extname: '.min.css'})).pipe(dest('dist'));
}
Copy the code
This will write the SRC/A.css file to the dist folder.
const { src, dest } = require('gulp');
const cleanCss = require('gulp-clean-css')
export.default = () = > {
return src('src/*.css').pipe(cleanCss()).pipe(rename({ extname: '.min.css'})).pipe(dest('dist'));
}
Copy the code
6. Style compilation
const { src, dest } = require('gulp');
const sass = require('gulp-sass');
const style = () = > {
return src('src/*.css', { base: 'src'}).pipe(sass({outputStyle: 'expanded'})).pipe(dest('dist'));
}
module.exports = {
style
}
Copy the code
7. Script compilation
const { src, dest, parallel, series } = require('gulp');
const del = require('del');
const sass = require('gulp-sass');
const babel = require('gulp-babel');
const swig = require('gulp-swig');
const imagemin = require('gulp-imagemin');
/ / delete the dist
const clean = () = > {
return del(['dist']);
}
/ / style
const style = () = > {
return src('src/*.css', { base: 'src'}).pipe(sass({outputStyle: 'expanded'})).pipe(dest('dist'));
}
// js
const script = () = > {
return src('src/*.js', { base: 'src'}).pipe(babel({presets: ['@babel/preset-env']})).pipe(dest('dist'));
}
// You can use the parameters passed in to HTML swig
const page = () = > {
return src('src/*.html', { base: 'src'}).pipe(swig({data: { date: new Date()})).pipe(dest('dist'));
}
// image
const image = () = > {
return src('src/images/**', { base: 'src'}).pipe(imagemin({})).pipe(dest('dist'));
}
// font
const font = () = > {
return src('src/fonts/**', { base: 'src'}).pipe(imagemin({})).pipe(dest('dist'));
}
// extra copy public file
const extra = () = > {
return src('public/**', { base: 'public'}).pipe(dest('dist'));
}
const compile = parallel(style, script, page, image, font);
const build = series(clean, parallel(compile, extra));
module.exports = {
build
}
Copy the code
8. Automatically load plug-ins
Manual loading of the plugins require more and more is not conducive to later maintenance, but can be automatically loaded using the plugins provided by gulp-load-plugin.
// Automatically load the plug-in
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();
Copy the code
Gulp-sass can be written as plugins.sass.
const { src, dest, parallel, series } = require('gulp');
const del = require('del');
// Automatically load the plug-in
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();
/ / delete the dist
const clean = () = > {
return del(['dist']);
}
/ / style
const style = () = > {
return src('src/*.css', { base: 'src'}).pipe(plugins.sass({outputStyle: 'expanded'})).pipe(dest('dist'));
}
// js
const script = () = > {
return src('src/*.js', { base: 'src'}).pipe(plugins.babel({presets: ['@babel/preset-env']})).pipe(dest('dist'));
}
// You can use the parameters passed in to HTML swig
const page = () = > {
return src('src/*.html', { base: 'src'}).pipe(plugins.swig({data: { date: new Date()})).pipe(dest('dist'));
}
// image
const image = () = > {
return src('src/images/**', { base: 'src'}).pipe(plugins.imagemin({})).pipe(dest('dist'));
}
// font
const font = () = > {
return src('src/fonts/**', { base: 'src'}).pipe(plugins.imagemin({})).pipe(dest('dist'));
}
// extra copy public file
const extra = () = > {
return src('public/**', { base: 'public'}).pipe(dest('dist'));
}
const compile = parallel(style, script, page, image, font);
const build = series(clean, parallel(compile, extra));
module.exports = {
build
}
Copy the code
9. Development server
The development server can cooperate with the build task to realize automatic update after the code changes, improving the efficiency of the development phase. It relies on the browser-Sync module, which needs to be installed in advance. Support code hot update function. Note that it is not a plugin for GLUP; it is only referenced and managed here.
const browserSync = require('browser-sync');
const bs = browserSync.create();
const serve = () = > {
bs.init({ / / initialization
port: 8080.open: false.files: 'dist/**'.server: {
baseDir: 'dist'.routes: {
'/node_modules': 'node_modules',}}}); }module.exports = {
serve
}
Copy the code
Routes forwards the request to the corresponding location, taking precedence over baseDir. BaseDir is routed only if it does not exist.
Init can be configured with many parameters, such as port, notify, open, files, etc. Files is the listening wildcard, specifying which files are thinner for rerendering to occur.
10. Monitor change build optimization
To recompile file changes in the SRC directory, use the Watch functionality provided by GLup. He monitors the wildcard of a path and then performs a task based on file changes, simply monitoring the path of the build task.
const { src, dest, parallel, series, watch } = require('gulp');
// Automatically load the plug-in
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();
/ / style
const style = () = > {
return src('src/*.css', { base: 'src'}).pipe(plugins.sass({outputStyle: 'expanded'})).pipe(dest('dist'));
}
const serve = () = > {
watch('src/*.css', style);
}
Copy the code
With Watch, you can trigger source code changes to be automatically compiled into Dist, and dist changes to be re-rendered in the browser.
Generally speaking, there is no need to compress image files during the development phase. You only need to do it once before launching. Therefore, images, public and other files can be directly specified.
const { src, dest, parallel, series, watch } = require('gulp');
// Automatically load the plug-in
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();
const browserSync = require('browser-sync');
const bs = browserSync.create();
/ / style
const style = () = > {
return src('src/*.css', { base: 'src'}).pipe(plugins.sass({outputStyle: 'expanded'})).pipe(dest('dist'));
}
const serve = () = > {
watch('src/*.css', style); / / build
watch('src/images/**'.'public/**', bs.reload); // Change updates
bs.init({ / / initialization
port: 8080.open: false.files: 'dist/**'.server: {
baseDir: ['dist'.'src'.'public'].routes: {
'/node_modules': 'node_modules',}}}); }module.exports = {
serve
}
Copy the code
11. useref
Assuming we import resources in the node_modules folder in our HTML, the development environment is fine, but the build’s formal environment is. Routes are configured to map node_moudles in the development environment, and some configuration is required in the official environment.
Useref will automatically process the build comments in THE HTML, which means that the files in the following comments can be packaged to the specified location, and if multiple annotations identify the same location, they will be merged.
<! -- build:css dist/a.css -->
<link ref="stylesheet" href="/node_modules/bootstrap/dist/bootstrap.css" />
<! -- endbuild -->
Copy the code
This way, it is much simpler, and compression and merging can be done. The gulp-useref plugin is used to listen for the packaged files.
const useref = () = > {
return src('dist/*.html', {base: 'dist'}).pipe(plugins.useref({searchPath: ['dist'.'. ']})).pipe(dest('dist'));
}
module.exports = {
useref
}
Copy the code
This removes the build comments, merges the contents of the build comments, and replaces references in the HTML.
12. File compression
There are three types of files to compress: HTML, JS, and CSS. They are all created by Useref. So there are three file types in the Useref pipeline that need to be compressed differently.
Gulp-uglify compresses JS, gulp-clean-css compresses CSS, and gulp-htmlnin compresses HTML.
const useref = () = > {
return src('dist/*.html', {base: 'dist'})
.pipe(plugins.useref({searchPath: ['dist'.'. ']}))
.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
13. Redesign the build process
SRC is packaged into the build directory and useref converts the build to the release directory. Build is an intermediary in this case, a temporary directory. I can tidy it up a little bit by replacing the folder name. Change build to temp and release to build.
const { src, dest, parallel, series, watch } = require('gulp');
// Automatically load the plug-in
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();
const browserSync = require('browser-sync');
const bs = browserSync.create();
/ / style
const style = () = > {
return src('src/*.css', { base: 'src'}).pipe(plugins.sass({outputStyle: 'expanded'})).pipe(dest('temp'));
}
const serve = () = > {
watch('src/*.css', style); / / build
watch('src/images/**'.'public/**', bs.reload); // Change updates
bs.init({ / / initialization
port: 8080.open: false.files: 'temp/**'.server: {
baseDir: ['temp'.'src'.'public'].routes: {
'/node_modules': 'node_modules',}}}); }const useref = () = > {
return src('temp/*.html', {base: 'temp'})
.pipe(plugins.useref({searchPath: ['temp'.'. ']}))
.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('build'));
}
module.exports = {
useref,
serve
}
Copy the code