An Introduction to Webpack
How to optimize our JavaScript code for production using a module bundler
Hello! This is part one of a series of articles covering the basics of Webpack. I will go over the basic use of the Webpack compiler and how to leverage code optimization through the creation of bundles. This step is crucial in the web development process as it is the point where we define our dependency graphs, entry points for our files, destinations for generated chunk files, plugins for modularization of non-JavaScript, and non-JSON files like CSS or even image files, and more. Okay, enough dilly-dallying, let’s jump right in!
Webpack Configuration
Webpack is a JavaScript compiler that converts JS into modularized bundles in preparation for production. We can use Webpack to define entry points for our frontend code as well as convert other files to readable JavaScript and provide the bundle’s path as an output. The example below is a basic implementation of a `config` object that defines an entry point at `index.js` in the `src` folder of a web application.
It isn’t required that the entry property in our webpack configuration file be an object. The syntax in the example to the left is primarily used when defining more than one entry point. We can also define the path to the entry point as the value of the entry property if it’s the only one.
When it comes to our config module’s `output`, despite an entry’s capability to hold multiple points of entry, only one output path can be defined. The output property is used to define a destination path for the newly created JavaScript bundle files as well as a file name. In other words, it defines how and where to store our compiled code. We can implement this using the Node.js `path` module.
The example below imports the path module as well as store the created `bundle.js` file to the `dist` folder:
Here we import the path module which will help define a file path for our compiled code. Using the `resolve()` method exposed by the imported module, we assign the bundle file to the current directory using the `__dirname` global object as well as a name for the file by passing a string of the file’s absolute path to `resolve()`.
When building our Webpack compiler we must also define any loaders and plugins that are required. The loader property is used to convert any non-JavaScript files (TypeScript, JSON, CSS, etc.) into readable, compiled JavaScript. A different loader is used per file type (i.e. `css-loader` is used for CSS files, style-loader can handle SCSS, file-loader for handling JSON data, etc.). They are converted into modules that are added to a dependency graph generated by Webpack. The example below shows a simple implementation of the loader property:
The module object in the example above defines the loaders to use to convert code into JavaScript modules. These are executed from right to left, or rather, from the bottom to the top, with the last loader expected to output a JavaScript code. As you can see, different file types require different loaders. You can even use `module.rules` to chain multiple loaders to a single file-type if needed:
Apart from an input, output, and loaders, webpack also uses plugins for a wide range of functionalities that aren’t already doable by a loader. It can log the compiling of our code to the console, it can build an HTML file along with your bundle, or store environment variables to call with `process.env`, write commented-out banners at the top of your bundle files, etc. The example below demonstrates a configuration file where we import the `HTMLWebpack` plugin via NPM:
That's it for part 1! Stay tuned for part 2 where I will dive deeper into webpack plugins and explore the variety of tasks that can be executed using webpack. Until next time!
Ps. The Webpack docs provide a list of all plugins available here.
Sources Cited
“Webpack.” Webpack, http://webpack.js.org. Accessed 10 July 2021.