The Anatomy of Webpack: A Deep Dive Into Its Architecture

Webpack is a powerful tool for building modern JavaScript applications, but its architecture can be complex and daunting for developers who are new to it. In this talk, we will dive into the inner workings of Webpack and explore how its various components work together to create a bundle.

By the end of this talk, you will have a comprehensive understanding of Webpack's architecture and its plugin system. You will be equipped with the knowledge to build complex applications using Webpack confidently.

Rate this content
Bookmark
Watch video on a separate page
Video Summary and Transcription
The video talk dives into the architecture of Webpack, a module bundler that transforms code into browser-compatible formats. It explains the role of the compiler as the central dispatch, managing the dependency graph and the build process. The talk highlights the importance of Webpack's plugin architecture, facilitated by Tappable, which allows developers to tap into hooks like compilation.hooks.SEAL and compilation.hooks.optimized. These hooks notify users of important events, enabling them to run custom code. The resolver in Webpack checks if the required paths exist and applies loaders, such as CSS loaders, to transform non-JavaScript files. The talk also covers how to use Webpack via configuration, command line interface, or Node API, starting with a configuration file to create a dependency graph. Finally, it showcases the creation of a basic plugin using the HelloCompilationPlugin class, illustrating how custom plugins can enhance Webpack's functionality.

This talk has been presented at React Day Berlin 2023, check out the latest edition of this React Conference.

FAQ

The compiler is the top-level central dispatch for Webpack. It starts and stops Webpack processes and is accessed through the Node API. The compiler creates a compilation, which kicks off the process of building the dependency graph and generating the final bundle.

Tappable is a library that creates hooks for plugins in Webpack. It is the backbone of the Webpack plugin system and allows users to get notified of important events and run custom code when those events occur.

Hooks in Webpack allow users to get notified of important events and run custom code. You can create hooks using Tappable and tap into them using the tap method. Hooks are used extensively in Webpack's plugin system.

A Webpack configuration file specifies how Webpack should behave when it runs. It includes options such as entry points, output directory, plugins, loaders, and optimizations.

The compilation object, created by the compiler, is known as the dependency graph. It is where Webpack starts building the graph, seals it, and renders it into bundles. The compilation object manages the entire build process.

The resolver in Webpack checks if the required paths in the codebase exist. It handles resolving paths for import and require statements and ensures that the appropriate loaders are applied for non-JavaScript files.

Loaders in Webpack are used to transform code into different modules. For example, loaders can be used to parse non-JavaScript files like CSS or PNG files.

Plugins in Webpack enhance the functionality of Webpack by allowing users to tap into various hooks. More than 80% of Webpack's codebase is built on its own plugin architecture, which is facilitated by the Tappable library.

Webpack is a module bundler that allows you to write modules that work in the browser. It takes code that is easy for developers to write and converts it into a format that is optimized for browsers to read.

You can use Webpack via configuration by defining a configuration object with entry and output points. It can also be used through its command line interface (CLI) by passing the entry file and output file name. Additionally, Webpack can be used with Webpack server to spin up a local development server or directly via the Node API.

1. Introduction to Webpack#

Short description:

Hello everyone, welcome to my talk on the anatomy of Webpack. Webpack is a module bundler that allows you to write modules for the browser. It takes your code and converts it into a format that browsers can read. You can use Webpack via configuration, command line interface, or the Node API. Webpack starts with a configuration file, reads your entry files, and creates a dependency graph. It then applies loaders to transform the code.

Hello everyone, welcome to my talk, the anatomy of Webpack a deep dive into its architecture. So a little bit about me that I'm a front end engineer at Razorpay and I love open source. I've been involved in open source for almost three years and I've been helping in the maintenance and development of ESLint and Webpack ecosystems. I'm also a big fan of animes particularly One Piece and you can find me on internet as at snitin315.

So let's dive into our talk. So let's start with what is Webpack. So as we all know that Webpack is a module bundler. Another way of explaining Webpack is like it lets you write modules that works in the browser. So what does that mean is we write stuff that is nice for us to write and then Webpack takes all that code and converts into stuff that is nice for browsers to read. So what does that mean? So nice for you to write means easy for developers to read, can be separated into multiple files, multiple repositories. Might be in a language that browsers can't understand, ES6, TypeScript, etc. What would be nice for browsers to read would be ES5, frequent requests, smaller responses.

So how do we use Webpack? So you can use Webpack via configuration. You can define a configuration object with entry and output. And you can also use Webpack via its command line interface. You can just, on CLI, you can just pass Webpack, hyphen, hyphen entry, part to your entry file and then hyphen, hyphen output, hyphen file name, the file name of your bundle. You can also use Webpack server command which will spin up a local development server for you. Or you can directly use the Node API and you can just require Webpack from your Node modules and pass two arguments. First argument is the configuration objects, second is a callback.

So let's see the broad overview of how things work for Webpack over the hood. So we start with a Webpack configuration file. This is where you specify how Webpack should behave when it runs, including options such as entry points, output, directory, plugins, loaders, everything, optimizations, then Webpack read your entry files. And these are the files that Webpack uses to start building your dependency graph. Webpack will analyze the code in these files and follow any dependencies it finds to other files in your applications. Then it creates the dependency graph, which is nothing but just analyzes which module is mapped to another module. Relationships, basically relationships between each modules. Then it applies the loaders and transforms. So Webpack uses loaders to transform the code into each module. For example, there is a non-javascript file which you want to parse through Webpack. You will have to use a loader.

2. Webpack Plugin Architecture and Tappable#

Short description:

Webpack handles compiled output by creating a bundle file. Webpack's plugin architecture, built with Tappable, allows users to tap into hooks that notify and execute code for important events. Hooks can be created with Tappable by importing a sync hook and defining them in the constructor. Tapping into hooks is done using the tap method, with the plugin name and a callback function as arguments.

It could be a CSS file, it could be a PNG file. Then, when everything is compiled, it creates a compiled output. So, after Webpack has processed all the modules, it produces a single file which is called a bundle. And then, as per the output management, we configure how we want Webpack to handle this bundle file. Like where on disk we want to write this file.

So in Webpack, everything is a plugin. So what does that mean is more than 80% of Webpack's codebase is built of its own plugin architecture. But before we learn more about plugins, we need to know about Tappable. So what is Tappable? Tappable is a library that creates hooks for plugins. It is created and maintained by the Webpack team only. And it is the backbone of the Webpack plugin system.

So what are hooks? Hooks allow other users to get notified of important events and run the other user's code when any important event happens. For example, browser exposes many hooks for us to tap into. For example, this is a basic hook, document.addEventListener on click. So whenever a user clicks on the screen, a message is printed to the console. So similarly, Webpack exposes many hooks which you can tap into. And how do we create hooks with Tappable? So you can simply import a sync hook from Tappable and in the constructor of your class, you can define a This.hooks property in which you redefine all the hooks.

So how to create hooks with Tappable? Yeah, so that's how we create a hook. So for example, in this example, we have a class Car in which we have a constructor in where we have defined our hooks via This.hooks. We have two hooks one is CarStarted and radioChanged hook. So whenever we want to call this hook, we can just run its call method. For example, we have a turn on method where we can do This.hooks.carStarted.call and whenever we call the turn on hook, this CarStarted hook will be triggered. Yeah, but how do we tap into hook. So to tap into hook we run its tap method. So for example, in the earlier example, we initialized a new instance of myCar. Now we can do myCar.hooks.CarStarted.tap and the first argument is the name of the plugin and this name is used for debugging purposes. And the second argument is a callback function. This is called when your hook is called. So whenever you will do, you will run myCar.turnOn it will print CarStarted. Similarly you can also pass options to your plugins.

3. Webpack Tappable Instances and Plugins#

Short description:

In this part, we explore the tappable instances of Webpack, such as compiler and compilation. We learn how to tap into hooks like compilation.hooks.SEAL and compilation.hooks.optimized. Additionally, we look at an example of a basic plugin using the HelloCompilationPlugin class. The compiler is the top-level central dispatch for Webpack, while the compilation represents the dependency graph.

So in here you can see myCar.hooks.radioChange.tab a radio plugin and we have passed a radio station option and we are logging the radio change to the radio station. So if you call myCar.setRadioStation with 100.10 it will print radio change to 100.10.

So now let's learn more about the tappable instances of Webpack. So Webpack exposes many tappable instances. For example these are two of the tappable instances. One is compiler and one is compilation. So here the drawing is showing that to tap into the compilation hook we first need to tap into the compiler hook. So we do compiler.hooks.compilation.tap then compilation offers other hooks for us to use for example SEAL. So you will do compilation.hooks.SEAL.tap. These are the hooks which are used by plugins. So SEAL is used when all the compilation is done. Optimize is used for example when the optimization of assets is being started. And you can use just before the hashing is started in Webpack process.

So this is a basic example of a plugin. So we define a class HelloCompilationPlugin which accepts an apply method. Now which has access to the compiler object which with compiler you can access to compilation compiler.hooks.compilation.tab then again you have the plugin name and the callback accepts the compilation argument. Then via compilation, you can access the other hooks like optimize. Now we can type into various hooks available through compilation. So here we are tapping to optimize it compilation.hooks.optimized.tab hello compilation plugin and we are just logging assets are being optimized. So this is a overview of how a basic plugin looks like. So the first typeable instance is compiler. So it's the top level central dispatch for webpack. It basically starts and stop webpack processes and this is what we expose where the node API. So whenever you require a webpack, it gives you access to the compiler. So the first argument is a configuration object. The second argument is a callback. So whatever is returned by this function call is the compiler instance. Then comes the compilation. So compilation is created by compiler only and this is also known as the dependency graph. It's the brain of Webpack where Webpack kicks off building the graph, sealing it and rendering into bundles.

4. Webpack Compilation and Resolver#

Short description:

Inside the compilation object, Webpack uses the resolver to check if required paths exist. The resolver returns an object with details like path and context. If the file is non-JavaScript, Webpack checks for a loader in the configuration. If found, the CSS is passed through the loader and the modified state is returned.

Everything happens inside the compilation object. Then we have the resolver. So whenever we have required any path in the codebase, Webpack checks if that path actually exists or not. So the resolver takes care of the resolving. Here. So whenever we come across any import statement or a required statement, it goes through the resolver. It checks if the file actually exists and then return an object with some details related. Like path, context. And if it is a non-JavaScript file, for example, let's say foo.css. Then it will check your webpack configuration if you have defined a respective loader for the CSS extension. If not, it will throw an error. If there is a loader you have specified, it will pass the CSS through that loader and return the modified state.

Nitin Kumar
Nitin Kumar
15 min
12 Dec, 2023

Comments

Sign in or register to post your comment.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Scaling Up with Remix and Micro Frontends
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
This talk discusses the usage of Microfrontends in Remix and introduces the Tiny Frontend library. Kazoo, a used car buying platform, follows a domain-driven design approach and encountered issues with granular slicing. Tiny Frontend aims to solve the slicing problem and promotes type safety and compatibility of shared dependencies. The speaker demonstrates how Tiny Frontend works with server-side rendering and how Remix can consume and update components without redeploying the app. The talk also explores the usage of micro frontends and the future support for Webpack Module Federation in Remix.
Understanding React’s Fiber Architecture
React Advanced 2022React Advanced 2022
29 min
Understanding React’s Fiber Architecture
Top Content
This Talk explores React's internal jargon, specifically fiber, which is an internal unit of work for rendering and committing. Fibers facilitate efficient updates to elements and play a crucial role in the reconciliation process. The work loop, complete work, and commit phase are essential steps in the rendering process. Understanding React's internals can help with optimizing code and pull request reviews. React 18 introduces the work loop sync and async functions for concurrent features and prioritization. Fiber brings benefits like async rendering and the ability to discard work-in-progress trees, improving user experience.
Full Stack Components
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
RemixConf EU discussed full stack components and their benefits, such as marrying the backend and UI in the same file. The talk demonstrated the implementation of a combo box with search functionality using Remix and the Downshift library. It also highlighted the ease of creating resource routes in Remix and the importance of code organization and maintainability in full stack components. The speaker expressed gratitude towards the audience and discussed the future of Remix, including its acquisition by Shopify and the potential for collaboration with Hydrogen.
The Eternal Sunshine of the Zero Build Pipeline
React Finland 2021React Finland 2021
36 min
The Eternal Sunshine of the Zero Build Pipeline
For many years, we have migrated all our devtools to Node.js for the sake of simplicity: a common language (JS/TS), a large ecosystem (NPM), and a powerful engine. In the meantime, we moved a lot of computation tasks to the client-side thanks to PWA and JavaScript Hegemony.
So we made Webapps for years, developing with awesome reactive frameworks and bundling a lot of dependencies. We progressively moved from our simplicity to complex apps toolchains. We've become the new Java-like ecosystem. It sucks.
It's 2021, we've got a lot of new technologies to sustain our Users eXperience. It's time to have a break and rethink our tools rather than going faster and faster in the same direction. It's time to redesign the Developer eXperience. It's time for a bundle-free dev environment. It's time to embrace a new frontend building philosophy, still with our lovely JavaScript.
Introducing Snowpack, Vite, Astro, and other Bare Modules tools concepts!
Composition vs Configuration: How to Build Flexible, Resilient and Future-proof Components
React Summit 2022React Summit 2022
17 min
Composition vs Configuration: How to Build Flexible, Resilient and Future-proof Components
Top Content
Today's Talk discusses building flexible, resilient, and future-proof React components using composition and configuration approaches. The composition approach allows for flexibility without excessive conditional logic by using multiple components and passing props. The context API can be used for variant styling, allowing for appropriate styling and class specification. Adding variants and icons is made easy by consuming the variant context. The composition and configuration approaches can be combined for the best of both worlds.
Remix Architecture Patterns
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Remix Architecture Patterns
Top Content
This Talk introduces the Remix architecture patterns for web applications, with over 50% of participants using Remix professionally. The migration from single page applications to Remix involves step-by-step refactoring and offers flexibility in deployment options. Scalability can be achieved by distributing the database layer and implementing application caching. The backend for frontend pattern simplifies data fetching, and Remix provides real-time capabilities for collaborative features through WebSocket servers and Server-SendEvents.

Workshops on related topic

AI on Demand: Serverless AI
DevOps.js Conf 2024DevOps.js Conf 2024
163 min
AI on Demand: Serverless AI
Top Content
Featured WorkshopFree
Nathan Disidore
Nathan Disidore
In this workshop, we discuss the merits of serverless architecture and how it can be applied to the AI space. We'll explore options around building serverless RAG applications for a more lambda-esque approach to AI. Next, we'll get hands on and build a sample CRUD app that allows you to store information and query it using an LLM with Workers AI, Vectorize, D1, and Cloudflare Workers.
High-performance Next.js
React Summit 2022React Summit 2022
50 min
High-performance Next.js
Workshop
Michele Riva
Michele Riva
Next.js is a compelling framework that makes many tasks effortless by providing many out-of-the-box solutions. But as soon as our app needs to scale, it is essential to maintain high performance without compromising maintenance and server costs. In this workshop, we will see how to analyze Next.js performances, resources usage, how to scale it, and how to make the right decisions while writing the application architecture.