Skip to content

Working with Babel and Webpack

Webpack is a powerful static module bundler for modern JavaScript applications. It takes modules with dependencies (JavaScript, CSS, images, etc.) and generates optimized static assets. When combined with Babel, Webpack can transpile your modern JavaScript code (ES2015+), including JSX or TypeScript, into a version compatible with older browsers, all as part of its bundling process.

This chapter will guide you through setting up a project using Webpack (version 5+) and Babel (version 7+) to bundle and transpile JavaScript modules.

Create a new project directory and initialize it with npm:

mkdir webpack-babel-project
cd webpack-babel-project
npm init -y

You’ll need Webpack, Webpack CLI, Babel core, babel-loader (to allow Webpack to use Babel), and @babel/preset-env.

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

Optionally, for a development server:

npm install --save-dev webpack-dev-server html-webpack-plugin

html-webpack-plugin simplifies creation of HTML files to serve your bundles.

Your package.json devDependencies will be updated accordingly.

Create a babel.config.json file in your project root:

{
"presets": ["@babel/preset-env"]
}

This tells Babel to use @babel/preset-env for transpiling modern JavaScript.

Create a webpack.config.js file in your project root. This file tells Webpack how to bundle your project.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development', // Or 'production' for optimized builds
entry: './src/index.js', // Your application's entry point
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'), // Output directory
clean: true, // Clean the output directory before each build
},
module: {
rules: [
{
test: /\.js$/i, // Apply this rule to .js files
exclude: /node_modules/, // Don't transpile node_modules
use: {
loader: 'babel-loader', // Use babel-loader for these files
options: {
// Babel options can be here or in babel.config.json
// presets: ['@babel/preset-env'] // Redundant if babel.config.json exists
}
}
}
// You can add more rules here for CSS, images, etc.
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack Babel App',
template: './src/index.html' // Optional: path to your HTML template
})
],
devServer: {
static: './dist', // Serve content from the dist directory
port: 8080,
open: true, // Open the browser automatically
hot: true, // Enable Hot Module Replacement
},
devtool: 'inline-source-map', // For better debugging (development only)
};

Key parts of webpack.config.js:

  • mode: Sets 'development' or 'production'. Production mode enables various optimizations.
  • entry: The main JavaScript file of your application.
  • output: Specifies where to output the bundled file (bundle.js in the dist directory).
  • module.rules: Defines how different types of modules (files) should be processed. The rule for .js files uses babel-loader.
  • plugins: HtmlWebpackPlugin generates an HTML file that includes your bundle.js.
  • devServer: Configures webpack-dev-server for a live-reloading development environment.

5. Create Project Structure and Source Files

Section titled “5. Create Project Structure and Source Files”

Create the following directory structure:

webpack-babel-project/
├── dist/ # Output folder (Webpack will create this)
├── node_modules/
├── src/
│ ├── index.html # HTML template (optional, if using HtmlWebpackPlugin template)
│ ├── index.js # Main application JavaScript (entry point)
│ └── math.js # An example module
├── babel.config.json
├── package.json
└── webpack.config.js

src/index.html (simple template):

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<h1>Hello from Webpack and Babel!</h1>
<div id="app"></div>
</body>
</html>

src/math.js:

export const add = (a, b) => a + b;
export const subtract = (a, b) => {
// Using a class for demonstration
class Calculator {
constructor() {
this.operation = 'subtract';
}
compute(x, y) {
return x - y;
}
}
const calc = new Calculator();
return calc.compute(a, b);
};

src/index.js:

import { add, subtract } from './math.js';
const main = () => {
const num1 = 10;
const num2 = 5;
const appDiv = document.getElementById('app');
if (appDiv) {
appDiv.innerHTML = `
<p>${num1} + ${num2} = ${add(num1, num2)}</p>
<p>${num1} - ${num2} = ${subtract(num1, num2)}</p>
`;
}
console.log(`Addition: ${add(num1, num2)}`);
console.log(`Subtraction: ${subtract(num1, num2)}`);
// Example of a feature that might need polyfilling if targeting old browsers
const arr = [1, 2, 3];
if (arr.includes(2)) {
console.log('Array includes 2!');
}
};
main();

Update the scripts section in your package.json:

"scripts": {
"start": "webpack serve --open",
"build": "webpack --mode production",
"build:dev": "webpack --mode development"
}

To start the development server:

npm start

This will open your application in the browser (usually http://localhost:8080). Webpack will watch for changes and automatically rebundle and reload.

To create an optimized production build:

npm run build

This will generate the bundle.js (and index.html) in the dist folder. The JavaScript will be minified and optimized for production.

If you inspect dist/bundle.js after a build, you’ll see that Webpack has bundled index.js and math.js together. Babel, via babel-loader, will have transpiled modern JavaScript syntax (like arrow functions, classes, template literals) into ES5-compatible code (or as configured by @babel/preset-env targets).

A simplified representation of the transpiled logic within bundle.js might look like this (Webpack adds a lot of boilerplate):

// ... Webpack runtime ...
// Transpiled math.js module content
var add = function add(a, b) { return a + b; };
var subtract = function subtract(a, b) {
var Calculator = /*#__PURE__*/function () { /* ... class transpiled ... */ }();
var calc = new Calculator();
return calc.compute(a, b);
};
// Transpiled index.js module content
var main = function main() {
var num1 = 10;
var num2 = 5;
// ... DOM manipulation and console logs with transpiled syntax ...
console.log("Addition: ".concat(add(num1, num2)));
};
main();
// ... more Webpack boilerplate ...

This setup effectively combines Webpack’s module bundling capabilities with Babel’s transpilation power, creating a robust build process for modern JavaScript applications. For features like Array.prototype.includes, ensure your Babel preset-env is configured for polyfills with core-js if targeting older environments (see other chapters).