Use Gulp and Webpack together for you asset bundling needs

There is a GitHub Repo with the files of this article.

I love Webpack! It allows me to bundle scripts in just one file. And if you pair it with babel you can use next generation javascript syntax and still make your scripts compatible with older browsers.

The fact of the matter is that if you are going to create a full stack javascript project, you HAVE TO use webpack…

But there is a problem… Webpack is not design for task automation, even tough it can do them.

For tasks automation, I still think there is no better tool than gulp. Specially when we want to compile SASS files, create zip archives, or deploy code on remote servers.

So here, I’m going to show you have to use gulp with webpack for task automation with the following tasks:

I’m not going to cover how to do complex things like deployment or clean up since I just want to show you how to make this 2 tools work together.

TOC

Project setup.

First lets create a project directory with some sub directories:

mkdir gulp-webpack-integration
cd gulp-webpack-integration
mkdir -p src/{js,scss}
tree

You should have then the following structure:

.
└── src
    ├── js
    └── scss

3 directories, 0 files

Dev environment structure creation

Now lets create some test CSS and JS files so we have something to test with:

Create src/scss/main.scss with the following contents:

// src/scss/main.scss

$background-color: #4b16ff;
$foreground-color: #ffffff;

body {
  background-color: $background-color;
  color: $foreground-color;
}

Now create src/js/hola-mundo.js With the following contents:

// src/js/hola-mundo.js

export default HolaMundo = name => {
  console.log(`Hello ${name} from hola-mundo.js`)
}

And finally create src/js/main.js with

// src/js/main.js

import HolaMundo from "./hola-mundo.js"

HolaMundo("Mario")

As you can see, this are very basic files, but enough for testing our setup.

Now that we have our test files, we can start the configuration. This are the steps we are going to follow:

Create package.json

So lets create our npm’s package.json file by issuing:

npm init -y

This will create a very basic file:

{
  "name": "gulp-webpack-integration",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

That was easy… Lets continue by installing and configuring Gulp.

Install Gulp

Now install gulp as a dev dependency by executing:

npm install --save-dev gulp

And create a gulpfile.js with just this code:

// gulpfile.js

const gulp = require("gulp")

Just for testing: execute node_modules/.bin/gulp --tasks to find out if all is good.

Output of gulp tasks

Install and configure a sass compiler

For compiling scss files, we’re going to use node-sass.

But we also need the package gulp-sass to make that bridge between the gulp and the compiler. So execute the following to install both packages.

npm install --save-dev gulp-sass node-sass

Now that we have installed both packages, make the following changes to gulpfile.js adding a task to compile scss files into css:

// gulpfile.js

const gulp = require("gulp")
const sass = require("gulp-sass")

sass.compiler = require("node-sass")

function styles() {
  return gulp
    .src("src/scss/*.scss")
    .pipe(sass())
    .pipe(gulp.dest("css/"))
}

exports.build = styles

And finally (for this step) change package.json to access this new task with just npm run build by creating a new script entry:

// package.json
{
  "name": "gulp-webpack-integration",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "gulp build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-sass": "^4.0.2",
    "node-sass": "^4.13.0"
  }
}

With this 3 steps you can now compile scss files and have them stored in the css/ directory:

Image of gulp compiling scss

Install and configure Webpack

This step can be kind of cumbersome since there are a lot of sub-steps required, but is well worth it.

First lest install webpack with npm:

npm install --save-dev webpack webpack-cli

Then create a basic webpack.config.js file to instruct webpack where are the js files and where to store the output:

// webpack.config.js

const path = require("path")

module.exports = {
  entry: {
    main: "./src/js/main.js",
  },
  output: {
    filename: "[name].min.js",
    path: path.resolve(__dirname, "js"),
  },
}

This will instruct webpack to compile the file src/js/main.js into js/main.min.js.

And finally, change the package.json to add a script that executes webpack in development mode for us:

// package.json
{
  ...
  "scripts": {
    "build": "gulp build",
    "webpack": "webpack --mode=development"
  },
  ...
}

Now you can compile scripts with webpack…

Image of webpack compiling scripts

But we’re not done yet with webpack. We need to instruct webpack to convert the compiled javascript into something that old browsers can understand.

Adding babel to webpack

As always, it all starts with some packages installation. We have to install Webpack’s babel-loader and all the Babel required files for converting code.

npm install --save-dev babel-loader @babel/core @babel/cli @babel/preset-env

Then, we have to modify webpack.config.js so any js file is converted to old javascript versions after compiling:

// webpack.config.js

const path = require("path")

module.exports = {
  entry: {
    main: "./src/js/main.js",
  },
  output: {
    filename: "[name].min.js",
    path: path.resolve(__dirname, "js"),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          presets: ["@babel/preset-env"],
        },
      },
    ],
  },
}

The output of npm run webpack should’t change, since we just told it to convert old format javascript. But we also should not get any errors.

Configure webpack in Gulp

We’re almost finished!

We just need to add a task in gulpfile.js that instructs gulp to calls webpack for compiling javascript files.

So again, open up the terminal and execute the following command to install the bridge between gulp and webpack:

npm install --save-dev webpack-stream

Then make the following changes to the gulpfile.js

// gulpfile.js

const gulp = require("gulp")
const sass = require("gulp-sass")
const webpack = require("webpack-stream")

sass.compiler = require("node-sass")

function styles() {
  return gulp
    .src("src/scss/*.scss")
    .pipe(sass())
    .pipe(gulp.dest("css/"))
}

function scripts() {
  return gulp
    .src(".")
    .pipe(webpack(require("./webpack.config.js")))
    .pipe(gulp.dest("js/"))
}

exports.build = gulp.parallel(styles, scripts)

And test it out:

Building scss and js files with gulp

Awesome… We’re done

Some cleanup

If you looked closely on the previous image, you can see that webpack is complaining about not having a “mode” seated up. And its right! (you can read about what that means here).

So lets fix that by adding a node env variable the script build on the file package.json. And also adding a new script called dev:

// package.json
{
  ...
  "scripts": {
    "build": "NODE_ENV=production gulp build",
    "dev": "gulp build",
    "webpack": "webpack --mode=development"
  },
  ...
}

Next we need to modify webpack.config.js to be aware of this new variable:

// webpack.config.js

const path = require("path")

module.exports = {
  entry: {
    main: "./src/js/main.js",
  },
  output: {
    filename: "[name].min.js",
    path: path.resolve(__dirname, "js"),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          presets: ["@babel/preset-env"],
        },
      },
    ],
  },
  mode: process.env.NODE_ENV == "production" ? "production" : "development",
}

And verify that there aren’t any complaints.

Npm run build without any warning

Perfect.

Missing steps

So here I showed you how to make gulp and webpack play nice together. What is missing from this article is how to configure a watch task for automatic compiling of js and sass files.

The short answer is… There is no difference!. You create watch tasks in gulp (not in webpack) as you’ve always have.