Working with Gulp
Gulp is a "Task runner" served as a Frontend tool. It is capable of executing chunks of code and save you huge amounts of time. What gulp can do is very vast :
- Simple operations like CSS and Javascript minification / concatenation
- Directory creation or deletion, project creation from scratch
- Image optimization and compression
- Deploying a local server to run tests
- Ghost browser simulation to test display regressions etc ...
To stay simple, Gulp will help you save tremendous amounts of time by handling recurring and automated tasks. You can then focus on your real work : produce clear and concise code, and get a coffee from time to time ! If you want to install Gulp globally on your machine, meaning that you will have access to its commands everywhere, follow the following steps. Otherwise jump to the next section.
To work properly, it relies on 2 files that you can find at the root of the project :
package.json
gulpfile.js
The package.json
file lists all your project's development and production dependencies installed via pnpm
, an effective way to manage your project's assets consistently. The gulpfile.js
file contains all the task that Gulp will perform once launched.
Available modules
Let's review the modules used by our gulpfile :
const {src, dest, watch, series, parallel } = require('gulp');
const log = require('fancy-log');
const colors = require('ansi-colors');
const browserSync = require('browser-sync').create();
const sass = require('gulp-sass');
const bourbon = require('node-bourbon').includePaths;
const rename = require('gulp-rename');
const concat = require('gulp-concat');
const del = require('del');
const panini = require('panini');
const uglify = require('gulp-uglify-es').default;
const sourcemaps = require('gulp-sourcemaps');
const imagemin = require('gulp-imagemin');
const removeCode = require('gulp-remove-code');
const removeLog = require('gulp-remove-logging');
const prettyHtml = require('gulp-pretty-html');
const sassLint = require('gulp-sass-lint');
const htmllint = require('gulp-htmllint');
const jshint = require('gulp-jshint');
const htmlreplace = require('gulp-html-replace');
const newer = require('gulp-newer');
const autoprefixer = require('gulp-autoprefixer');
const accessibility = require('gulp-accessibility');
const babel = require('gulp-babel');
const nodepath = 'node_modules/';
const assetspath = 'assets/';
Gulp Plugins
- gulp-autoprefixer
- gulp-compile-handlebars
- gulp-concat
- gulp-html-replace
- gulp-htmllint
- gulp-pretty-html
- gulp-remove-code
- gulp-remove-logging
- gulp-rename
- gulp-sass
- node-bourbon
- gulp-sass-lint
- gulp-sourcemaps
- gulp-uglify
- gulp-newer
- gulp-accessibility
- gulp-jshint
- gulp-gulp-gh-pages
- gulp-babel
- panini
- run-sequence
- ansi-colors
- fancy-log
There are two additional variables that we define at the top of the file. We will need them to continue :
nodepath
: a shortcut to get stuff from the/node-modules
folder (created by pnpm), so we don't expose our internal paths.
Gulp tasks
We prepared a certain number of predefined tasks that will help you during all the development process. We will go through the gulpfile.js
file to detail each one of this tasks.
Server task
function browserSyncInit(done) {
browserSync.init({
server: './dist'
});
return done();
}
Gulp uses this task to create a browser-sync
instance. It creates a local development server and automatically opens a browser window showing index.html
.
Watch task
function watchFiles() {
watch('src/**/*.html', compileHTML);
watch(['src/assets/scss/**/*', 'src/assets/scss/*'] , compileSCSS);
watch('src/assets/js/*.js', compileJS);
watch('src/assets/img/**/*', copyImages);
}
Gulp uses this task to watch any change you make to the HTML and Sass files. When it detects changes, it triggers other tasks that handle Sass and HTML compilation.
Clean task
function cleanDist(done) {
del.sync('dist');
return done();
}
Gulp uses this task to clean the dist
folder, which is the result of the project build. At the moment you should not see any dist
folder because you didn't build the project yet. This task is also used at the beginning of the build process, to clean the folder before compiling the assets again.
Bulma task
function setupBulma() {
return src([nodepath + 'bulma/*.sass', nodepath + 'bulma/**/*.sass'])
.pipe(dest('src/assets/sass/'));
}
gulp uses this task to copy the Bulma source file from their location in the _node-modules
folder to the sass/
folder. As these assets are already copied in the project, you shouldn't need this task right now.
Plugins task
function concatPlugins() {
return src([
nodepath + 'jquery/dist/jquery.min.js',
nodepath + 'feather-icons/dist/feather.min.js',
nodepath + 'typed.js/lib/typed.min.js',
nodepath + 'easy-autocomplete/dist/jquery.easy-autocomplete.min.js',
nodepath + 'alertifyjs/build/alertify.min.js',
nodepath + 'scrollreveal/dist/scrollreveal.min.js',
nodepath + 'ocanvas/build/dist/latest/ocanvas.min.js',
nodepath + 'slick-carousel/slick/slick.min.js',
nodepath + 'croppie/croppie.min.js',
nodepath + '@fengyuanchen/datepicker/dist/datepicker.min.js',
nodepath + 'chosen-js/chosen.jquery.min.js',
nodepath + 'izitoast/dist/js/iziToast.min.js',
nodepath + 'webui-popover/dist/jquery.webui-popover.min.js',
nodepath + 'zoom-vanilla.js/dist/zoom-vanilla.min.js',
nodepath + 'scrollreveal/dist/scrollreveal.min.js',
nodepath + 'card/dist/jquery.card.js',
'src/assets/vendor/js/*',
])
.pipe(sourcemaps.init())
.pipe(concat('app.js'))
.pipe(sourcemaps.write('./'))
.pipe(dest('dist/assets/js'))
.pipe(browserSync.stream());
}
Gulp uses this task to concatenate all the required plugins into a single file which gets pushed to dist/assets/js/
folder. You can then access those plugins from there in your web pages.
Assets tasks
function copyImages() {
return src('src/assets/img/**/*.+(png|jpg|jpeg|gif|svg)')
.pipe(newer('dist/assets/img/'))
.pipe(imagemin())
.pipe(dest('dist/assets/img/'))
.pipe(browserSync.stream());
}
function copyFont() {
return src([
'src/assets/font/*',
])
.pipe(dest('dist/assets/fonts'))
.pipe(browserSync.stream());
}
function copyData() {
return src([
'src/data/**/*',
])
.pipe(dest('dist/assets/data'))
.pipe(browserSync.stream());
}
function jsVendor() {
return src([
'src/assets/vendor/js/*',
])
.pipe(dest('dist/assets/vendor/js'))
.pipe(browserSync.stream());
}
function cssVendor() {
return src([
'src/assets/vendor/css/*',
])
.pipe(dest('dist/assets/vendor/css'))
.pipe(browserSync.stream());
}
gulp uses those tasks to copy all external assets and dependencies into the corresponding sub-folder of the dist/assets/
folder of the production site.
Compile Sass task
function compileSASS() {
return src(['src/assets/sass/bulma.sass'])
.pipe(sass({
outputStyle: 'compressed',
sourceComments: 'map',
sourceMap: 'sass',
includePaths: bourbon
}).on('error', sass.logError))
.pipe(autoprefixer('last 2 versions'))
.pipe(dest('dist/assets/css'))
.pipe(browserSync.stream());
}
Gulp uses this task to compile the Bulma source files into a single CSS file. it then copies this file in dist/assets/css/
.
Compile SCSS task
function compileSCSS() {
return src(['src/assets/scss/main.scss', 'src/assets/scss/demo.scss'])
.pipe(sass({
outputStyle: 'compressed',
sourceComments: 'map',
sourceMap: 'scss',
includePaths: bourbon
}).on('error', sass.logError))
.pipe(autoprefixer('last 2 versions'))
.pipe(dest('dist/assets/css'))
.pipe(browserSync.stream());
}
Gulp uses this task to compile the Huro SCSS source files into a single CSS file (main.css
). it then copies this file in dist/assets/css/
.
Compile HTML task
function compileHTML() {
panini.refresh();
return src('src/pages/**/*.html')
.pipe(panini({
root: 'src/pages/',
layouts: 'src/layouts/',
partials: 'src/partials/',
helpers: 'src/helpers/',
data: 'src/data/'
}))
.pipe(dest('dist'))
.pipe(browserSync.stream());
}
Gulp uses this task to compile all the changes you make to the template HTML files. It triggers a refresh from Panini to update your templates before rendering.
Compile JS task
function compileJS() {
return src([
'src/assets/js/_data-wishlist.js',
'src/assets/js/_data-addresses.js',
'src/assets/js/_data-orders.js',
'src/assets/js/functions.js',
'src/assets/js/Huro.js',
'src/assets/js/authentication.js',
'src/assets/js/cart.js',
'src/assets/js/account.js',
'src/assets/js/wishlist.js',
'src/assets/js/product.js',
'src/assets/js/orders.js',
'src/assets/js/order.js',
'src/assets/js/checkout.js',
'src/assets/js/search.js',
'src/assets/js/demo.js',
'src/assets/js/elements.js',
])
.pipe(babel())
.pipe(dest('dist/assets/js/'))
.pipe(browserSync.stream());
}
Gulp uses this task to copy all your custom javascript to the distribution folder.
Gulp commands
We have now seen that there are a lot of ready to use tasks for gulp. While you can run some of the above tasks individually, let's now see the available commands that make use of multiple tasks at once.
gulp dev
Builds the project and runs a dev server. It runs several tasks that we defined above. Run it by typing this command in your terminal window, at the root of the project :
gulp dev
Here is what happens when you run gulp dev
:
- Gulp deletes the
dist
folder - Then, gulp executes all assets copying and compilation tasks :
series(cleanDist, copyFont, copyData, jsVendor, cssVendor, copyImages, compileHTML, concatPlugins, concatCssPlugins, compileJS, resetPages, prettyHTML, compileSASS, compileSCSS, browserSyncInit, watchFiles);