I have been getting back into doing a lot more JavaScript recently and every blog post that I read or video that I watched talked about Webpack. But I had one question – Why do you need Webpack?
The answer is
Just kidding. But JavaScript ecosystem is notorious for ephemeral solutions that seem to come and go every week. So, I spent some time trying to understand where Webpack fits in and it was fascinating. Here is my attempt at trying to explain why you need webpack or any other module bundler.
Origins of Javascript
Let’s go back to the dark times before we had all the funny memes and GIFs. Back in the 1990s, the web was mostly static boring content. There was very little of anything else. Definitely no GIFs.
The year was 1995. Netscape Communications had built and released an awesome browser called Netscape Navigator. Users can use it browse the boring static web sites. Marc Andreessen, the chief of Netscape communications, wanted to create a little less boring web by allowing some dynamic content like adding animations or other small interactions to the mostly static documents. So, he hired Brandon Eich and told him to come up with a scripting language for the web. But there was a catch – he only had 10 days to come up with this new scripting language and the language had to look like Java because Java was the hot new thing back then and Netscape wanted to ride the Java hype to profit. So based on the instructions that were given to him, he designed a Java like language that can add small amounts of interactivity to static documents. Thus, JavaScript was born.
No one could have really envisioned what happened next.
Gmail
Year is now 2001. Paul Buchheit wanted to bring web based email to the masses. But he had one big problem. HTML was designed for static documents. But the email client that he was building needed to be able to show dynamic content. So, he and his team turned to the one thing that made static web documents interactive – JavaScript. He and his team used a revolutionary approach that eventually came to be called as AJAX and JavaScript (lots and lots of JavaScript) to build a web-based email application.
Prior to Gmail, most applications sent network request to the server and the server produced an HTML file that the browser was able to render. But the Gmail team used JavaScript (again lots and lots of JavaScript) to get around this problem.
The success of the Gmail team in using JavaScript to build a full fledged application in JavaScript inspired so many other application builders. But most of these application builders ran into a problem.
How to manage boat loads of JavaScript code?
You suddenly had lots of people with boat loads of JavaScript code. But JavaScript as a language was not designed for writing full fledged applications. Instead it was designed to add little bits of interactivity to a mostly static document. So, they were all scrambling for solutions.
Allowing developers to manage huge codebases is an already solved problem in many programming languages. For example: Java allows you to segment code into packages and namespaces. C# does something similar.
But JavaScript as a language did not have any such capability (again going back JavaScript’s origin story of a language to add little bits of interactivity to static documents).
By this time, Netscape had gone bust and donated all the code to the Mozilla foundation which created the Firefox browser. JavaScript got standardized through ECMA and got a name change to ECMAScript (to get around trademark issues). So, a bunch of companies got together tried to come up with a solution for the growing pains of using the JavaScript language. They proposed adding packages, namespaces and other things that would have allowed developers to manage boat loads of JavaScript code they were writing. But, ECMAScript 4 was abandoned because the people on the committee couldn’t agree.
But this didn’t stop people from writing boatloads of JavaScript. One of the common approaches people followed is to break up JavaScript code into multiple files and load them through script tag in the HTML document. But this had one major problem.
Dependency Issues
Let us say that you have a square function defined in one part of JavaScript file and another function that consumes the square function like printData.
function square(inputNumber) {
return inputNumber*inputNumber;
}
// Assume that there is a million lines of code in between
function printData() {
console.log(square(5));
}
Because there is a lot of JavaScript code in here, you break it up into multiple JavaScript files and you try to load it. Since printData function has a dependency on the square function, the file that contains the square function has to be loaded before the file that contains the printData function or your entire app will crash. So, the ordering of the files was super important and it caused a major headache.
Bundle
To avoid all the dependency issues, developers started shipping a single (often massive) JavaScript file that came to be known as the bundle. All the code for the application will be contained in the bundle. As long all the code that depends on one another is in the bundle, there will be no dependency issues.
But these bundles did not solve the problem of maintaining large JavaScript code bases. Something else had to pop up to tackle that problem.
Node.js and CommonJS Module System
Node.js entered the JavaScript ecosystem in 2009. It used the powerful V8 engine to allow for JavaScript to be used outside of the browser in things like server applications. It was a big game changer.
But the part that is exciting for JavaScript developers was the module system that came with Node.js – CommonJS. Finally, there was a way to organize the boatloads of JavaScript code into modules that can be consumed. But the catch was CommonJS was written with Node.js in mind. So, there was no way to use it for JavaScript code on the browser.
AMD
Even though CommonJS was not written with the browser in mind, it didn’t stop people from trying to bring a module system based on CommonJS to the browser JavaScript code. A successful proposal emerged known as the Asynchronous Module Definition (AMD). It proposed a similar interface to that of CommonJS and it was very successful.
Unlike Node.js which had native support for CommonJS modules, browsers had no clue about AMD modules. So, you needed to use a special piece of software called a loader that understood AMD modules to import it and use it inside the browser. You might already be familiar with some of the most common loaders – RequireJS and Browserify.
We finally have some way to modularize JavaScript code and we have a way to import modules through loaders. Mission accomplished?
Modules and Bundle
Remember the bundle? It turns out that modules and bundles do not go well together. Module loaders like RequireJS were designed with loading JavaScript modules from the network. But most people were used to putting all the JavaScript code together into a single JavaScript bundle and using a script tag to load it into the HTML page. So if your team tried to adopt modules, you will have to somehow load the module from the network and this brings us back to the world of dependency issues again.
So, you needed a way to allow developers to modularize the code but still allow them to import them without making a network call or breaking the bundle and causing dependency issues.
Enter Module Bundler
Module bundler is a tool that takes code from different modules and allow you to create a bundle with all that code. Let’s take a quick example. Let’s assume that there is a module named square in a file called square.js
export function square(inputNumber) {
return inputNumber * inputNumber;
}
Let’s assume that there is a module named printData in a file called printData.js which consumes the square module by importing it
import { square } from "./square.js"
function printData() {
console.log(square(5));
}
If we run a module bundler on these files, the module bundler might generate a file like this
function square(inputNumber) {
return inputNumber * inputNumber;
}
function printData() {
console.log(square(5));
}
Webpack is an example of a module bundler. It takes one or more modules and creates a bundle for you. It also does a lot more. But all of its other features will be covered in future posts.
But wait a minute, if the module bundler takes code from modules and puts them in a random order, don’t we have dependency issues again? For example, if the module bundler is not careful, it might output something like this which will crash the app
function printData() {
console.log(square(5));
}
function square(inputNumber) {
return inputNumber * inputNumber;
}
Dependency Aware Module Bundler
In order to create a valid bundle, the module bundler has to be aware of which dependencies are being used and need to position them in the right place.
Module bundlers like webpack are dependency aware. They usually maintain a dependency graph. This allows them to place the code loaded in from a module in the right place.
Conclusion
- The primary goal of using a tool like webpack or any other module bundler is to make it easy for developers to modularize their JavaScript code and make it easy to work with large JavaScript codebases.
- Module bundlers like webpack take in one or more modules as input and produce a single file known as a bundle as the output.
- Dependency aware module bundlers maintain a dependency graph of which modules depend on which other modules and this allows them to position the code from the modules in the right place so that the dependencies are satisfied.
- ECMAScript 6 has native support for JavaScript modules. All major browsers support it as well. But there is still a large amount of legacy JavaScript code out there. So, we will be using module bundlers for a long time to come.
References
- You can read more about the history of JavaScript at https://auth0.com/blog/a-brief-history-of-javascript/
- You can read more about the history of Gmail at https://en.wikipedia.org/wiki/History_of_Gmail
- You can read the full story of ECMAScript 4 at https://auth0.com/blog/the-real-story-behind-es4/

Leave a comment