Skip to content

Instantly share code, notes, and snippets.

@jeromecoupe
Last active January 21, 2024 16:28
Show Gist options
  • Save jeromecoupe/0b807b0c1050647eb340360902c3203a to your computer and use it in GitHub Desktop.
Save jeromecoupe/0b807b0c1050647eb340360902c3203a to your computer and use it in GitHub Desktop.
Gulp 4 sample gulpfile.js. For a full explanation, have a look at https://www.webstoemp.com/blog/switching-to-gulp4/
"use strict";
// Load plugins
const autoprefixer = require("autoprefixer");
const browsersync = require("browser-sync").create();
const cp = require("child_process");
const cssnano = require("cssnano");
const del = require("del");
const eslint = require("gulp-eslint");
const gulp = require("gulp");
const imagemin = require("gulp-imagemin");
const newer = require("gulp-newer");
const plumber = require("gulp-plumber");
const postcss = require("gulp-postcss");
const rename = require("gulp-rename");
const sass = require("gulp-sass");
const webpack = require("webpack");
const webpackconfig = require("./webpack.config.js");
const webpackstream = require("webpack-stream");
// BrowserSync
function browserSync(done) {
browsersync.init({
server: {
baseDir: "./_site/"
},
port: 3000
});
done();
}
// BrowserSync Reload
function browserSyncReload(done) {
browsersync.reload();
done();
}
// Clean assets
function clean() {
return del(["./_site/assets/"]);
}
// Optimize Images
function images() {
return gulp
.src("./assets/img/**/*")
.pipe(newer("./_site/assets/img"))
.pipe(
imagemin([
imagemin.gifsicle({ interlaced: true }),
imagemin.jpegtran({ progressive: true }),
imagemin.optipng({ optimizationLevel: 5 }),
imagemin.svgo({
plugins: [
{
removeViewBox: false,
collapseGroups: true
}
]
})
])
)
.pipe(gulp.dest("./_site/assets/img"));
}
// CSS task
function css() {
return gulp
.src("./assets/scss/**/*.scss")
.pipe(plumber())
.pipe(sass({ outputStyle: "expanded" }))
.pipe(gulp.dest("./_site/assets/css/"))
.pipe(rename({ suffix: ".min" }))
.pipe(postcss([autoprefixer(), cssnano()]))
.pipe(gulp.dest("./_site/assets/css/"))
.pipe(browsersync.stream());
}
// Lint scripts
function scriptsLint() {
return gulp
.src(["./assets/js/**/*", "./gulpfile.js"])
.pipe(plumber())
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
}
// Transpile, concatenate and minify scripts
function scripts() {
return (
gulp
.src(["./assets/js/**/*"])
.pipe(plumber())
.pipe(webpackstream(webpackconfig, webpack))
// folder only, filename is specified in webpack config
.pipe(gulp.dest("./_site/assets/js/"))
.pipe(browsersync.stream())
);
}
// Jekyll
function jekyll() {
return cp.spawn("bundle", ["exec", "jekyll", "build"], { stdio: "inherit" });
}
// Watch files
function watchFiles() {
gulp.watch("./assets/scss/**/*", css);
gulp.watch("./assets/js/**/*", gulp.series(scriptsLint, scripts));
gulp.watch(
[
"./_includes/**/*",
"./_layouts/**/*",
"./_pages/**/*",
"./_posts/**/*",
"./_projects/**/*"
],
gulp.series(jekyll, browserSyncReload)
);
gulp.watch("./assets/img/**/*", images);
}
// define complex tasks
const js = gulp.series(scriptsLint, scripts);
const build = gulp.series(clean, gulp.parallel(css, images, jekyll, js));
const watch = gulp.parallel(watchFiles, browserSync);
// export tasks
exports.images = images;
exports.css = css;
exports.js = js;
exports.jekyll = jekyll;
exports.clean = clean;
exports.build = build;
exports.watch = watch;
exports.default = build;
@hildissent
Copy link

Relatively new to frontend, and extremely new to JavasScript. I was hooked on the potential of Gulp after messing around with it for a bit, and this example was instrumental in helping me get my own gulpfile together. Thank you!

@Andzie-M347
Copy link

Thanks a lot man, I'm new to gulp and the course I'm doing the dude is using gulp v3. This will be helpful.

@espurnes
Copy link

espurnes commented May 14, 2019

I get the following error when I run npm run gulp:

[07:18:36] Using gulpfile /usr/src/app/gulpfile.js
[07:18:36] Starting 'default'...
[07:18:36] Starting 'clean'...
[07:18:36] The following tasks did not complete: default, clean
[07:18:36] Did you forget to signal async completion?
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! jsite@1.0.0 gulp: gulp
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the jsite@1.0.0 gulp script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

I fixed the problem updating the clean function from:

// Clean assets
function clean() {
return del(["./_site/assets/"]);
}

to

// Clean assets
function clean(done) {
del(["./_site/assets/"]);
done()
}

EDITED: It was a problem of my environment. I was using del v1.0.0 instead of del v4.1.1. Updating the version fixed the problem. Now the original code works perfect.

@jeromecoupe
Copy link
Author

jeromecoupe commented May 14, 2019

@espurnes glad it fixed it for you. It sounds a bit strange that this is needed though, last I checked del returns a promise and that should normally be enough to signal async completion.

https://www.npmjs.com/package/del
https://gulpjs.com/docs/en/getting-started/async-completion

@espurnes
Copy link

@jeromecoupe I'm reading the gulp 4 guide to better understand what is happening. No one have argued about your code, so probably is a misconfiguration of my environment.

Thank you for the links. I'll take a look to them.
I'll post again if I get a clean execution with your code.

@espurnes
Copy link

@jeromecoupe I found the problem. I was using del version 1.0.0 instead of v4.1.1 ...
Now npm run gulp clean works as spected and with no errors.

Thank you

@tanmoythander
Copy link

Great sample. It helped me to upgrade my v3 gulpfile to v4 entirely. Thank you...

@rmfranciacastillo
Copy link

Awesome Post! I had a hard time updating my files from 3.9 to 4.0. Thanks for sharing!!

@jeromecoupe
Copy link
Author

@zdimaz your code looks like it is missing a few things. Most of your named functions should return streams. If you are not familiar with Gulp and working with files, the official "Getting started" doc is a good start, here is the page on working with files

@zdimaz
Copy link

zdimaz commented Jun 5, 2019

@jeromecoupe
No !
I use gulp 3 > awesome works
I triyed update to new all tasks, but no create build folder (build task) ((
Sorry for my ENGLISH)

@yoanmalie
Copy link

@jeromecoupe Hey thanks for your help!
How to use exports.taskname with tasks named like styles:build, styles:lint… ?

@jeromecoupe
Copy link
Author

jeromecoupe commented Jul 10, 2019

@yoanmalie short answer, use camelCase instead to name your functions and then compose main tasks using parallel or series. I basically try to follow what the documentation recommends

@gabriel-lima96
Copy link

Thank you a lot for sharing! This helped me so much, specially your article "Switching to Gulp 4".

@Inlesco
Copy link

Inlesco commented Aug 8, 2019

Great article, thanks for putting it all into a single place and written in a easy-to-navigate manner.

@kennblvnp
Copy link

Hi Mr. Jérôme Coupé

This gulpfile.js template is what Im looking for. I have been struggling to install gulp in my existing react 16.9 project.

Can I see your package.json?

@jeromecoupe
Copy link
Author

jeromecoupe commented Sep 16, 2019

@kennblvnp Thanks for the kind words. All required packages are listed at the top of the gulpfile. Both the old version of my site (where this came from originally) and the new one are publicly available on Github so that might help too. V1 is on the v1-backup branch.
https://github.com/jeromecoupe/webstoemp/blob/v1-backup/gulpfile.js

@NorthaHuang
Copy link

thank you so mush!
It's help a lot!

@shirblc
Copy link

shirblc commented Oct 26, 2019

Thank you so much for this! I spent so long trying to figure out Gulp 4 after Gulp 3.9 but this made it so much clearer.

@myquery
Copy link

myquery commented Oct 27, 2019

Am new to gulp, but am just curious, where do you import or use the exported functions. Thanks for sharing

@jeromecoupe
Copy link
Author

jeromecoupe commented Oct 31, 2019

@myquery The short answer is that you don't import when using a singe file. CommonJS exports are just Gulp4's way to expose tasks to the CLI to make them public. Non exported tasks are considered private (used only as subtasks) https://gulpjs.com/docs/en/getting-started/creating-tasks#exporting

That being said, you can require / alias them in your main file if your main file is becoming too big / complex. You can have a look at the code of my own site for an example https://github.com/jeromecoupe/webstoemp/blob/master/gulpfile.js

@raugustin93
Copy link

Thank you, this is a perfect reference point.

@fayazrehmani
Copy link

Thanks, but I have a suggestion that it would really help if you can add sample folder structure and text file with commands so it can we started by anyone.

@GV94
Copy link

GV94 commented Dec 3, 2019

Thanks a lot for this, tremendous help when going from v.3.9.1 to v4.x of gulp!

@linorallo
Copy link

It finally worked, thanks a lot!

@poanchen
Copy link

Thanks a lot. Helped me to upgrade to v4 of gulp

@bangsite
Copy link

Thank you a lot for sharing! This helped me so much.

@evasoek
Copy link

evasoek commented Nov 20, 2020

I'm getting the error:
imagemin.jpegtran is not a function

Any idea?

@jeromecoupe
Copy link
Author

jeromecoupe commented Nov 24, 2020

@evasoek yes. imagemin stopped using jpegtran a while ago in favour of mozjpeg.

This is an old Gist and you might want to look at the doc of the various plugins used.

// Optimize Images
function images() {
  return gulp
    .src("./assets/img/**/*")
    .pipe(newer("./_site/assets/img"))
    .pipe(
      imagemin([
        imagemin.gifsicle({ interlaced: true }),
        // the line below is the one that you likely have to change
        imagemin.mozjpeg({ quality: 75, progressive: true }),
        imagemin.optipng({ optimizationLevel: 5 }),
        imagemin.svgo({
          plugins: [
            {
              removeViewBox: false,
              collapseGroups: true
            }
          ]
        })
      ])
    )
    .pipe(gulp.dest("./_site/assets/img"));
}

Despite that, basic principles for Gulp 4 have stayed the same so this is still quite relevant. I ams till using Gulp (in combination with Webpack fr JS) on my personal site, which is available on Github if you are interested.

@evasoek
Copy link

evasoek commented Nov 24, 2020

@evasoek yes. imagemin stopped using jpegtran a while ago in favour of mozjpeg.

This is an old Gist and you might want to look at the doc of the various plugins used.

// Optimize Images
function images() {
  return gulp
    .src("./assets/img/**/*")
    .pipe(newer("./_site/assets/img"))
    .pipe(
      imagemin([
        imagemin.gifsicle({ interlaced: true }),
        // the line below is the one that you likely have to change
        imagemin.mozjpeg({ quality: 75, progressive: true }),
        imagemin.optipng({ optimizationLevel: 5 }),
        imagemin.svgo({
          plugins: [
            {
              removeViewBox: false,
              collapseGroups: true
            }
          ]
        })
      ])
    )
    .pipe(gulp.dest("./_site/assets/img"));
}

Despite that, basic principles for Gulp 4 have stayed the same so this is still quite relevant. I ams till using Gulp (in combination with Webpack fr JS) on my personal site, which is available on Github if you are interested.

Yes I figured, thanks! I got it to work eventually, so it's fine. 😊

@LoesterFranco
Copy link

thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment