Introduction
Bunding is the process of transforming source code into files that can be placed on a web server and used by web browsers. To acheive this, a bundler takes HTML, CSS and/or JavaScript files and related files to merge, split or minify(make the files as small as possible) the code into one file that can be easily loaded by browsers.
In the case of JavaScript, bundlers processes the source code from one standard to another. Case in point, modules, introduced in the ES6 standard, allow you to write reusable pieces of code that can be imported/exported to any other files when needed. However, not all browsers support the import
and export
syntax. Bundling can be used to transform ES6 JavaScript into ES5 JavaScript so that the code can run even in old browsers.
Webpack
is one such tool for building and bundling JavaScript applications. There exists othery options to choose from for your bundling needs: Parcel, Vite, Esbuild. This article covers Webpack.
Bundling
When webpack processes your application, it combines all the modules into one or more static bundles, that can be served to the browser as assets. These bundles include all the code needed to run the application, including all its dependencies.
Get Started
create a new directory. Inside of the directory, create subdirectories and files as shown below:
├── build
├── package.json
├── src
│ └── index.js
└── webpack.config.js
the package.json
:
{
"name": "project webpack",
"version": ",
"description": "a webpack project",
}
Step 1. Install webpack:
To use webpack, you’ll first need to install it.
$ npm i -D webpack webpack-cli
Step 2. Add The Configuration
In the webpack.config.js
file in the root folder, add the following code:
const path = require("path")
const config = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "build"),
filename: "main.js",
},
}
module.exports = config
entry
property defines where webpack will start when bundling the app. When webpack bundles the code, it includes all the imported code in the entry point as well as the import’s imports. And since some of the imports are packages, the bundled JavaScript code will also contain the contents of these libraries.output
property defines where the bundled code will be stored. This needs to be an absolute path, which is easy to create with Node’spath.resolve
method.__dirname
is a global variable in Node that returns the absolute path of the current JS file.
To execute the bundling, define an npm script :
package.json
{
...
"scripts": {
"build": "webpack --mode=development"
}
}
The mode
parameter can be set to either development
, production
or none
. It helps to enable webpack’s built-in optimizations for each of the environments.
Step 3. Add an entry point
Webpack builds your application by starting at a single entry point and following the dependencies of that file. In the configuration above, we’ve specified that the entry point is src/index.js
So, you’ll need to create an index.js file in the src directory. This can be an empty file for now.
Step 4. Run Webpack
With the build
script in place, run:
$ npm run build
This should produce a new /build
directory with a main.js
file inside it.
Webpack in React
To convert the above app into a react app, install react:
$ npm i react react-dom
Add The Entry Point
Create an index.js
file. This will be the entry point for your React application, and it should look something like this:
import React from 'react
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
Add an HTML Template file
In the /build
folder, create an index.html
file to serve as the “main page” for the app. The main page loads the JavaScript code through a script tag:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webpack Project</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
Loaders
Bundling the app at this point results in an error. By default, Webpack only knows how to deal with plain JS. React, however, uses a lot of JSX, which might look like JS but isn’t:
src/app.js
const App = () => {
return (
<div>Hello webpack..</div>
)
}
To fix this, we use loaders
to tell Webpack of the files that need “processing” before attempting to bundle them, and what tool to use to process these files.
Babel
is a tool that converts your React’s JSX into JavaScript that Webpack can understand.
$ npm i -D @babel/core babel-loader @babel/preset-react
This will install the necessary Babel packages as dev dependencies for your project.
Update the configuration file webpack.config.js
:
...
const config = {
...
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react']
}
}
]
}
}
The loader
configuration consists of 3 parts:
test
property specifies the type of files the loader is for. In this case, it’s for.js
filesloader
property specifies which loader will process the files that meet the testoptions
property and is used to specify any extra parameters for the loader
The bundling process is now successful when npm run build
is executed. To test the bundled app, open /build/index.html
on the browser.
Transpilers
Transpiling is the process of transforming source code from one language to another. Babel
transforms source code from one form of JavaScript to another. For instance, since most browsers do not support the newer JavaScript standards, ES6, ES7 and so forth, babel can transpile the code into the older ES5 standard.
Babel transpilation is enabled by applying plugins or presets to your configuration file. The [ has excellent coverage of plugins.
In the current config file, we only have one preset, @babel/preset-react
:
Add @babel/preset-env
as well:
$ npm i -D @babel/preset-env
This preset contains everything to transform any new JavaScript features into the old ES5 standard.
Update the babel loader
configuration:
...
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
...
babel’s presets are excuted in a last to first order. This means the react preset is run first, followed by the env preset.
The following result is the of transpiling simple JSX code:
CSS in Webpack
Trying to add CSS to the app and running the npm run build
command results in the loader error:
When using CSS, we need to include a css loader
and a style loader
:
$ npm i -D css-loader style-loader
In the config file’s rules
object, insert the following:
...
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
}
...
css-loader
loads the css files and resolves special css syntax like imports
and url()
.
style-loader
takes the transformed CSS and injects it into the DOM
by adding a <style
>tag in the page's
Now npm run build
works, and the CSS definitions are added to the `main.js“ file together with the JavaScript
To extract the css into a separate file, mini-css-extract-pugin helps with that
Using webpack-dev-server
Currently, any changes to the code warrant a rerun of the npm run build
command and a manual refresh of the page.
Webpack-dev-server
helps to improve your work workflow by providing a web server and the ability to use live reloading. To set it up:
$ npm i -D webpack-dev-server
In the configuration file, add a new property to tell the dev server where to look for files:
const config = {
// ...
devServer: {
static: path.resolve(__dirname, "build"),
compress: true,
port: 3000,
},
// ...
}
Add a script for starting the dev server:
package.json
"scripts": {
//...
"start": "webpack serve --mode=development"
}
npm start
command will start the dev server in the specified port 3000, i.e. http://localhost:3000
Updates to the code causes the browser to autorefresh the page. When the dev server bundles the code, it does not write into the output file main.js
but instead, the bundled results are kept only in memory.
Minification
Minification refers to the optimization process of any source code e.g. by removing unnecessary characters and comments. By running webpack in production mode, you can reduce the size of your main.js file by a significant percentage:
"scripts": {
"build": "webpack --mode=proudction"
// ...
}
This helps to improve the performance of your application by reducing the amount of data that needs to be transmitted over the network and parsed by the browser, i.e. the bundle size.
Summary
React and webpack are powerful tools that can be used together to build and optimize modern JavaScript applications. In this post, we covered how to use webpack to manage your dependencies, and optimize your assets.