Skip to content

Working with BabelJS and Gulp

Gulp is a popular JavaScript task runner that automates repetitive development tasks. This chapter demonstrates how to set up a Gulp build process to transpile modern JavaScript (ES2015+) to ES5 using Babel. We’ll use modern Gulp 4 syntax and current Babel packages.

This setup is useful for projects that already use Gulp for other tasks (like SASS compilation, image optimization) or prefer Gulp’s stream-based approach.

Start by creating a new project directory and initializing it with npm:

mkdir gulp-babel-example
cd gulp-babel-example
npm init -y

This will generate a package.json file.

Install Gulp and the necessary Babel packages as development dependencies:

npm install --save-dev gulp gulp-babel @babel/core @babel/preset-env gulp-connect

Breakdown of these packages:

  • gulp: The Gulp task runner itself.
  • gulp-babel: A Gulp plugin to pipe JavaScript files through Babel.
  • @babel/core: The core Babel transpiler engine.
  • @babel/preset-env: The standard Babel preset for compiling modern JavaScript down to your target environments.
  • gulp-connect: A Gulp plugin to run a local development server with live reload capabilities (optional, but useful).

Your package.json’s devDependencies will now include these packages (versions may vary):

{
// ... other package.json content ...
"devDependencies": {
"@babel/core": "^7.x.x",
"@babel/preset-env": "^7.x.x",
"gulp": "^4.x.x",
"gulp-babel": "^8.x.x",
"gulp-connect": "^5.x.x"
}
}

Create a Babel configuration file, babel.config.json, in your project root. This tells gulp-babel how to transpile the code:

babel.config.json
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": ["> 1%", "last 2 versions", "not dead"]
}
}
]
]
}

This config uses @babel/preset-env to target browsers based on common usage statistics.

Create a gulpfile.js in your project root. This file will define your Gulp tasks.

// gulpfile.js
const gulp = require('gulp');
const babel = require('gulp-babel');
const connect = require('gulp-connect');
// Source and destination paths
const paths = {
scripts: {
src: 'src/**/*.js',
dest: 'dist/js/'
},
html: {
src: 'src/**/*.html',
dest: 'dist/'
}
};
// Transpile JavaScript files
function scripts() {
return gulp.src(paths.scripts.src, { sourcemaps: true }) // Enable source maps
.pipe(babel()) // Uses babel.config.json by default
.on('error', function(err) {
console.error('[Babel Error]', err.toString());
this.emit('end'); // Prevents Gulp from crashing on Babel error
})
.pipe(gulp.dest(paths.scripts.dest))
.pipe(connect.reload()); // Trigger live reload
}
// Copy HTML files
function html() {
return gulp.src(paths.html.src)
.pipe(gulp.dest(paths.html.dest))
.pipe(connect.reload());
}
// Watch for changes in files
function watchFiles() {
gulp.watch(paths.scripts.src, scripts);
gulp.watch(paths.html.src, html);
}
// Start a local development server
function server() {
connect.server({
root: 'dist',
livereload: true,
port: 8080
});
}
// Define complex tasks
const build = gulp.parallel(html, scripts);
const serve = gulp.series(build, gulp.parallel(watchFiles, server));
// Export tasks
exports.scripts = scripts;
exports.html = html;
exports.watch = watchFiles;
exports.build = build;
exports.serve = serve;
exports.default = serve; // Default task when running `gulp`

This gulpfile.js defines several tasks:

  • scripts: Takes .js files from src/, transpiles them using Babel, saves them to dist/js/, and triggers a live reload.
  • html: Copies HTML files from src/ to dist/ and triggers a live reload.
  • watchFiles: Monitors src/ files for changes and re-runs the respective tasks.
  • server: Starts a local web server using gulp-connect serving files from the dist directory.
  • build: A parallel task that runs html and scripts.
  • serve (and default): Runs an initial build, then starts the server and watchFiles tasks concurrently.

Create the src directory. Inside it, create index.html and js/main.js.

src/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gulp Babel Example</title>
</head>
<body>
<h1>Modern JavaScript with Gulp and Babel</h1>
<p id="message"></p>
<script src="js/main.js"></script>
</body>
</html>

src/js/main.js:

src/js/main.js
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
greet() {
const messageElement = document.getElementById('message');
if (messageElement) {
messageElement.textContent = `Hello, ${this.fullName}! Welcome.`;
}
}
}
const person = new Person('Alex', 'Developer');
person.greet();
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(`Sum of numbers: ${sum}`);

Add scripts to your package.json for convenience:

// package.json (scripts section)
"scripts": {
"start": "gulp",
"build": "gulp build"
}

To build the project:

npm run build

This will create a dist folder with the transpiled js/main.js and copied index.html.

Transpiled dist/js/main.js (example snippet):

"use strict";
function _classCallCheck(instance, Constructor) { /* ... */ }
function _defineProperties(target, props) { /* ... */ }
function _createClass(Constructor, protoProps, staticProps) { /* ... */ }
var Person = /*#__PURE__*/function () {
function Person(firstName, lastName) {
_classCallCheck(this, Person);
this.firstName = firstName;
this.lastName = lastName;
}
_createClass(Person, [{
key: "fullName",
get: function get() {
return "".concat(this.firstName, " ").concat(this.lastName);
}
}, {
key: "greet",
value: function greet() {
var messageElement = document.getElementById('message');
if (messageElement) {
messageElement.textContent = "Hello, ".concat(this.fullName, "! Welcome.");
}
}
}]);
return Person;
}();
var person = new Person('Alex', 'Developer');
person.greet();
var numbers = [1, 2, 3, 4, 5];
var sum = numbers.reduce(function (acc, num) {
return acc + num;
}, 0);
console.log("Sum of numbers: ".concat(sum));
//# sourceMappingURL=main.js.map

To start the development server with live reload and file watching:

npm start

Open your browser to http://localhost:8080. You should see the greeting message. If you change src/js/main.js or src/index.html, the browser will automatically reload with the changes.

  • Existing Gulp Projects: If your project already uses Gulp for other build tasks, integrating Babel is straightforward.
  • Stream Processing: If you prefer Gulp’s stream-based philosophy for handling files.
  • Simpler Build Needs: For projects that don’t require the complexity of a full module bundler like Webpack (e.g., not heavily reliant on complex module splitting, tree shaking, or diverse asset management).
  • Server-Side JavaScript: Gulp can be used to transpile Node.js applications for environments that don’t support all modern JS features.

While module bundlers like Webpack or Parcel are often favored for front-end applications due to features like advanced code splitting and dependency management, Gulp remains a powerful and flexible tool for many build automation scenarios, including Babel transpilation.