What is WebPack and What are Modules?

What is WebPack and What are Modules?

Why WebPack?🕸️

What problem does it solve?🧐

In its broadest definition: WebPack is a bundler, a module bundler. 😼

What it basically does is bundles all assets and files. 💪

To understand why WebPack is necessary, it is important to know How was Javascript used on the web before bundlers were a thing. 😶‍🌫️

So the question is what is a bundler? 🤨

Why can’t I just use script files, drop a script, and be done? 😜

We can use a script file, in fact using a <script> tag is the most basic way in which we all started using JavaScript.

*If an application is small say 500 lines of code, Great to use a script tag, and Voila Done. 🤩*

But then your code expands and new functionalities are added but say that your code is not just mere 500 lines.

However, say you have 20k lines of javascript code what would you do then? 🥲

Managing so much code all in one file is a herculean task and doing this alongside other collaborators will be a developer's nightmare. It will create problems in scope, size, readability, and maintainability. 🙄

So the solution is to split the single code file and break it into say 10 or 15 smaller files and insert 15 script tags on our page. So it’s over na? Finally. But wait here is a catch!

It is needed to see the ordering of all the script tags, making sure that the utility function is available before using it in another file. Also, the problem with global scoping is still relevant.

So we see neither splitting the file nor concatenating them is working. 😬

Now, this idea of using modularity and creating modules that can be imported or exported between different JavaScript files introduced the need to have local modules with local variables and bundling them together to give a single output file using a Bundler 🤠

Three options rose in this scenario in order to maintain modularity and enable creating a true dependency graph. 🤩

IIFE function :

Definition and Usage and pros over normal script tags

  • Anonymous function expressions that enable modularity in code by providing an anonymous function that makes sure that scoping of large projects are solved.
  • We avoid dumping everything onto the global namespace.
  • When script files are wrapped by an IIFE, one can safely concatenate or safely combine files without worrying about scope collision.

Problems with IIFE function :

  • Changing one file means one has to rebuild the whole thing.
  • Build optimization is difficult.
  • Order of <script> tag still matters.
  • Tree Shaking or removing redundant code is tough.

IIFE functions gave us a few ideas about modularity in Javascript. Utilizing this CommonJS was introduced which was popularized with the advent of NodeJS.

Common JS :

Definition and Usage

  • It defines a module format to solve scoping issues of JavaScript and by making sure that each module is exported and imported (using require() keyword ) in a certain way.
  • It forces modules to export variables they would want other JavaScript files to access. And also defining all modules which are required to run a file properly.

Cons: Problems with CommonJS

  • Cannot run in the browser. A problem with CommonJS is it loads modules synchronously. That's great for the server but not for the browser.
  • This makes case for using external tools bundlers like Browserify, Brunch, etc.

So then we moved on to ES Modules which encompasses the pros of CommonJS and removes the cons.

ES6 Modules

Definition and Usage

  • It is a JavaScript writing format that can also run on browsers because they're now native to JavaScript, modern browsers support them without using a bundler. Thus it is CommonJS but also runs in the browser.
  • It handles all the issues of scope, maintainability, and upgrading and can also be supported in the browser.
  • Because ES Modules force you to declare your import statements at the top of your module, the bundler can quickly understand your dependency tree. and thus enabling Tree Shaking or Dead Code Elimination.

Cons: Problems with ES6 Modules

  • It is not in common use because not many browsers have migrated and upgraded to ES6 standards.

Bundles enabled us to introduce modularity in Javascript and get best practices in Javascript but what next ?

Now that we have understood the problem, solutions, and options we have let’s come back to the question :

What is WebPack? 😍

These are bundlers which not just work for JavaScript files but for any file type. 😳

This means that by using WebPack and thus this distinguishes them from common bundlers like browserify is that WebPack creates dependency graph/tree for any file type and thus enables modularity not just across JavaScript files but say also across CSS files and assets files. 🥳

WebPacks not only let us write modules but also support any module format (at least until we get to ESM) and handle resources and assets at the same time.

This is why WebPack exists. It's a tool that lets one bundle JavaScript applications (supporting both ESM and CommonJS), and it can be extended to support many different assets such as images, fonts, and stylesheets. 🤗

In plain simple words, Webpack lets you use require()on local "static assets," meaning non-Javascript files. Webpack is a module bundler for all types of files and assets. When one runs Webpack, it searches through all of your code for require()calls and then creates a dependency tree. Enabling us to not only have no issues with the handling of Javascript files functions and utilities but also assist us to import images and CSS.

To understand 😌

How WebPack works it is important to understand some terminologies 😎

Entry :

It is the starting node in a graph or say an entry point that WebPack uses to start drawing out its internal dependency tree.

WebPack figures out the other modules that depend upon the entry point whether directly or indirectly.

By default, it starts from ./src/index.js, but it can be changed to any file of choice.

Output :

Say that WebPack has created a bundle file with Javascript modules and assets. Now where to put these bundles?

The main output file is written as ./dist/main.js and other generated files can be added to the ./dist directory

We can also define the output path and output filename for the location of our output.

Loaders:

According to the official documentation, Loaders are transformations that are applied to the source code of a module.

Bundlers can only handle Javascript files and can only create dependency trees/graphs for these files but as WebPack enables us to generate dependencies for assets also it needs to preprocess non- Javascript files also.

And loaders are the large variety of formats that allow us to transform files from one language to javascript like reading image paths as URLs or importing CSS directly from Javascript.

It gives WebPack the ability to import .css, .svg, and other files and process them- which starts with downloading loaders. For example, to import .css and .svg files, we’ll install cssloader and svg-inline-loader respectively -

We add them as rules to our webpack.config.js

Loaders, basically, have two properties in the configuration, that are -

  • Test: The test property determines which file(s) should be transformed.
  • Use: The use property specifies which loader will be used for that particular file.

Plugins:

Plugins are used to handle asset management, bundle optimization, and usage of environment variables alongside a bundle.

Plugins perform operations after the generation of bundlers.

webpack.config.js

const path = require("path");
const webpack = require("webpack");

module.exports = {
  entry: { app: "./entry.js" }, // Start bundling
  output: {
    path: path.join(__dirname, "dist"), // Output to dist directory
    filename: "[name].js", // Emit app.js by capturing entry name
  },
  // Resolve encountered imports
  module: {
    rules: [
      { test: /\.css$/, use: ["style-loader", "css-loader"] },
      { test: /\.js$/, use: "swc-loader", exclude: /node_modules/ },
    ],
  },
  // Perform additional processing
  plugins: [new webpack.DefinePlugin({ HELLO: "hello" })],
  // Adjust module resolution algorithm
  resolve: { alias: { react: "preact-compat" } },
};

Here we can see the configuration of a WebPack .

We see

  • Entry point for generating dependencies
  • Output filename and pathname.
  • Rules for loaders with test and use properties to use specific loaders
  • Additional plugins that can be used after bundling is done.

Summarizing flow of working of WebPack? 🤔

webpackFlow.png

  • Webpack goes through the dependencies of each file recursively and resolves every dependency until the traversal has been completed.
  • The resolver first verifies if the respective files for all the dependencies are present. If they are, it transforms every file in a module and creates a dependency graph of all the modules.
  • Then it bundles all of this in one file ( specified as the ‘output’ file in the configuration).
  • It maintains a registry of all the modules, so they can be correctly called/executed whenever they are required.

Pros of WebPack 😎

  • Dead asset elimination
  • Easier code splitting
  • Features like Hot Page Reloading and CSS management.
  • The biggest testimony to WebPack is that Create React App which provides setup and bundles for running React from scratch in browser uses WebPack.

Cons of WebPack 😒

  • Configuring WebPack is steep learning.
  • Small Community

To summarize 😌

  • Webpack is a module bundler, but you can also use it to run tasks as well.
  • Webpack relies on a dependency graph underneath. Webpack traverses through the source to construct the graph, and it uses this information and configuration to generate bundles.
  • Webpack relies on loaders and plugins. Loaders operate on a module level, while plugins rely on hooks provided by WebPack and have the best access to its execution process.
  • Webpack's configuration describes how to transform assets of the graphs and what kind of output it should generate. Part of this information can be included in the source itself if features like code splitting are used.

These can be overwhelming because WebPack comes with its own boilerplate code and has a steep learning curve. But it is worth investing time in it. Considering it solves the most important aspects of coding i.e Modularity and optimization with tones of additional features all within itself without much effort and time. 💪