Gulp.js
It's open source JavaScript toolkit and task runner (build system) that utilizes Node.js.
Automating Repetitive Tasks
- Compressing images
- Generating HTML from templates and content files
- Compiling Sass to CSS
- Removing unwanted development related statements from scripts
- Transpiling latest versions of JavaScript to cross-browser-compatible version
- Code testing, linting, and validation
- Concatenation and minifying of scripts, styles, and other files
- Cache busting (Letting browser know new version of cache is available)
- Creating local development servers
- Deploying files to various servers
How Gulp works
- Built on node streams. Which is piping output from one task as an input to the next.
- It reads a file once, process it through multiple times, and then writes the final output file.
- Pipeline/
.pipe()
operator is used. - Files not affected until all plugins are processed.
- Single purpose plugins.
- Gulp makes use of call-back functions to run tasks.
- It is faster as it dose not create and read intermediary files on hard drive.
Gulp vs Grunt
- Gulp is code over configuration, Grunt is the opposite.
- Gulp is easier to read than Grunt.
- Gulp is based on streams, Grunt is based on files.
Instruction
First install Node.js which will install npm (node package manager) along with it. In latest versions
npx
as well is installed.Install
gulp-cli
globally, it helps to maintain different versions of gulp.js.bashnpm install gulp-cli -g
In the current project directory create
package.js
file (it's like a manifest file for node based projects) with the help ofnpm
(node package manager).bashnpm init
Then install
gulp.js
locally in each project as a development dependency package.bashnpm install gulp --save-dev
Now install the required Gulp plugins that perform tasks.
Create a
gulpfile.js
file where all the tasks are written.Run
gulp
in command line to execute the tasks.
Structure of Gulp File
Structure of Gulp file can be divided into 4 parts as shown below.
Required modules (plugins).
javascript// import gulp const gulp = require("gulp"); // import gulp plugins const autoprefixer = require("gulp-autoprefixer");
Create tasks using the plugins.
javascript// create tasks gulp.task("css-prefix", () => gulp .src("css/*.css") .pipe( autoprefixer({ cascade: false, }), ) .pipe(gulp.dest("dist/")), );
Automate tasks by watching for changes in files and run tasks accordingly.
javascriptgulp.task("watch", () => gulp.watch("src/js/*.js", ["scripts"]));
Create a default task that run when we run
gulp
.javascript// run task in series or parallel gulp.task("default", gulp.series("scripts", "watch"));
NOTE
All sample codes are working in gulp -v
= 4.0.2
Functions
There different levels for functions.
Top level functions
gulp.task
- Defines tasks.gulp.src
- Defines path to the input files.gulp.dest
- Defines path to the output directory.gulp.watch
- Watch files and folders for changes and run tasks accordingly.
Streams
- Streams allows us to pass X data through a number of small useful functions.
- Once the data is processed by a function, it is passed on to the next function.
- When the last functions finishes data processing it outputs the final processed data.
- Streams are asynchronous, they use callbacks to interact with other functions.
Streams separate concerns because they restrict the implementation surface area into a consistent interface which could be reused.
.pipe()
is a mere function that takes a readable source stream src:
and hooks the output to a destination writeable stream dst:
.
Pipes can be chained together: one.pipe(two).pipe(three).pipe(four)
Types of steams:
- Readable
- Writeable
- Transform
- Duplex
- Classic
Plugins
JavaScript File Plugins:
gulp-concat - Concatenate files into one single file:
javascriptconst concat = require("gulp-concat"); gulp.task("scripts", () => gulp .src("./lib/*.js") .pipe(concat("all.js")) .pipe(gulp.dest("./dist/")), );
gulp-useref - Concatenate JS files. Better at concatenating files present in different directories than gulp-concat:
javascriptconst useref = require("gulp-useref"); gulp.task("useref", () => gulp.src("app/*.html").pipe(useref()).pipe(gulp.dest("dist")), );
gulp-uglify - JavaScript parser, minifies, compressor and beautifier:
javascriptconst uglify = require("gulp-uglify"); const gulpIf = require("gulp-if"); gulp.task("useref", () => gulp .src("app/*.html") // Minifies only if it's a JavaScript file .pipe(gulpIf("*.js", uglify())) .pipe(gulp.dest("dist")), );
gulp-babel - Gulp plugin for Babel:
javascriptconst gulp = require("gulp"); const babel = require("gulp-babel"); gulp.task("default", () => gulp .src("src/app.js") .pipe( babel({ presets: ["@babel/preset-env"], }), ) .pipe(gulp.dest("dist")), );
CSS File Plugins:
gulp-clean-css - Minify CSS:
javascriptconst cleanCSS = require("gulp-clean-css"); gulp.task("css", () => gulp .src("css/*.css") .pipe(cleanCSS({ compatibility: "ie8" })) .pipe(gulp.dest("./dist/")), );
gulp-autoprefixer - Auto prefixes vendor prefixes for CSS. You can use editor plugin for this like, Sublime Text:
javascriptconst autoprefixer = require("gulp-autoprefixer"); // Set the browser that you want to support const AUTOPREFIXER_BROWSERS = [ "ie >= 10", "ie_mob >= 10", "ff >= 30", "chrome >= 34", "safari >= 7", "opera >= 23", "ios >= 7", "android >= 4.4", "bb >= 10", ]; gulp.task("css-prefix", () => gulp .src("css/*.css") .pipe( autoprefixer({ cascade: false, }), ) .pipe(gulp.dest("dist/")), );
gulp-sass - Generate CSS from Sass files:
javascriptconst sass = require("gulp-sass"); gulp.task("sass", () => gulp .src("source-files") .pipe(sass()) // Using gulp-sass .pipe(gulp.dest("destination")), );
gulp-csso - Minify CSS, alternative to gulp-cssnano:
javascriptconst csso = require("gulp-csso"); gulp.task("default", () => gulp.src("./main.css").pipe(csso()).pipe(gulp.dest("./out")), ); gulp.task("development", () => gulp .src("./main.css") .pipe( csso({ restructure: false, sourceMap: true, debug: true, }), ) .pipe(gulp.dest("./out")), );
Image File Plugins:
gulp-imagemin - Minify and optimize images:
javascriptconst imagemin = require("gulp-imagemin"); gulp.task("images", () => gulp .src("app/images/**/*.+(png|jpg|jpeg|gif|svg)") .pipe( imagemin({ // Setting interlaced to true interlaced: true, }), ) .pipe(gulp.dest("dist/images")), );
sharp - Resize images:
HTML File Plugins:
gulp-htmlmin - Minify HTML:
javascriptconst htmlmin = require("gulp-htmlmin"); gulp.task("pages", () => gulp .src(["./*.html"]) .pipe( htmlmin({ collapseWhitespace: true, removeComments: true, }), ) .pipe(gulp.dest("./dist/")), );
Font Plugins:
gulp-iconfont - Create SVG/TTF/EOT/WOFF/WOFF2 fonts from several SVG icons.
javascriptconst iconfont = require("gulp-iconfont"); const runTimestamp = Math.round(Date.now() / 1000); gulp.task("Iconfont", () => gulp .src(["assets/icons/*.svg"]) .pipe( iconfont({ fontName: "myFont", // required prependUnicode: true, // recommended option formats: ["ttf", "eot", "woff"], // default, 'woff2' and 'svg' are available timestamp: runTimestamp, // recommended to get consistent builds when watching files }), ) .on("glyphs", (glyphs, options) => console.log(glyphs, options)) .pipe(gulp.dest("www/fonts/")), );
Local Server Plugins:
browser-sync - Keep multiple browsers & devices in sync when building websites.
javascriptconst gulp = require("gulp"); const browserSync = require("browser-sync").create(); // Static server gulp.task("browser-sync", () => { browserSync.init({ server: { baseDir: "./", }, }); }); // or... gulp.task("browser-sync", () => { browserSync.init({ proxy: "yourLocal.dev", }); });
Other Plugins:
gulp-changed - Only pass through changed files:
javascriptconst changed = require("gulp-changed"); const SOURCE = "src/*.js"; const DESTINATION = "dist"; exports.default = () => gulp .src(SOURCE) .pipe(changed(DESTINATION)) // `plugin1` will only get the files that // changed since the last time it was run .pipe(plugin1()) .pipe(gulp.dest(DESTINATION));
gulp-cache - A cache proxy task for Gulp. Optimizing images however, is an extremely slow process that you'd not want to repeat unless necessary. To do so, we can use this plugin.
javascriptconst imagemin = require("gulp-imagemin"); const cache = require("gulp-cache"); gulp.task("images", () => gulp .src("app/images/**/*.+(png|jpg|jpeg|gif|svg)") // Caching images that ran through imagemin .pipe( cache( imagemin({ interlaced: true, }), ), ) .pipe(gulp.dest("dist/images")), );
gulp-cached - A simple in-memory file cache for gulp. Alternative to gulp-cache:
javascriptconst cache = require("gulp-cached"); gulp.task("lint", () => gulp .src("files/*.js") .pipe(cache("linting")) .pipe(jshint()) .pipe(jshint.reporter()), ); gulp.task("watch", () => gulp.watch("files/*.js", ["lint"])); gulp.task("default", ["watch", "lint"]);
gulp-newer - Pass through newer source files only:
javascriptconst newer = require("gulp-newer"); const imagemin = require("gulp-imagemin"); const imgSrc = "src/img/**"; const imgDest = "build/img"; // Minify any new images gulp.task("images", () => gulp .src(imgSrc) .pipe(newer(imgDest)) // Add the newer pipe to pass through newer images only .pipe(imagemin()) .pipe(gulp.dest(imgDest)), ); gulp.task("default", () => gulp.watch(imgSrc, ["images"]));
gulp-load-plugins - Loads gulp plugins from package dependencies and attaches them to an object of your choice. We can use packages in our
package.json
file as plugins:javascript// load all devDependencies const $ = require("gulp-load-plugins")({ pattern: ["*"], scope: ["devDependencies"], }); const sass = require("gulp-sass"); gulp.task("sass", () => gulp.src("source-files").pipe($.sass()).pipe(gulp.dest("destination")), );
gulp-sourcemaps - Generate source maps:
javascriptconst plugin1 = require("gulp-plugin1"); const plugin2 = require("gulp-plugin2"); const sourcemaps = require("gulp-sourcemaps"); gulp.task("javascript", () => gulp .src("src/**/*.js") .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest("dist")), );
gulp-plumber - Prevent pipe breaking caused by errors from plugins:
javascriptconst plumber = require("gulp-plumber"); gulp.task("javascript", () => gulp .src("./src/*.ext") .pipe(plumber()) .pipe(plugin1()) .pipe(gulp.dest("./dist")), );
gulp-size - Display the size of your project:
javascriptconst size = require("gulp-size"); exports.default = () => gulp.src("fixture.js").pipe(size()).pipe(gulp.dest("dist"));