DEV Community

Muhamad Ilyas Mustafa
Muhamad Ilyas Mustafa

Posted on

Brief Explanation of Javascript Module Bundler

The Javascript ecosystem is a wild-wild world. Every time humans breathe, a javascript library is released to the world. Of course, this is an exaggeration, but you can almost literally type random English words and add “JS” behind them, most likely You will find a javascript library with that term. That shows how popular Javascript is.

On the one hand, this means Javascript has a vast ecosystem. Every problem that you face, you can easily find the answer, or at least you can ask easily. But on the other hand, it is so huge, that no mortal can understand all of them. This is becoming a huge headache especially when you are comparing similar libraries.

This also applies to Javascript Module Bundler, as so many bundlers out there, with their own configuration, with their own term. Not many of us touch bundler configuration regularly (including me), and it can be quite intimidating to set up your own bundle configuration from scratch. Here is my brief understanding of the Javascript Module Bundler.

What is Module Bundler

The art of modular programming is splitting your application code into small independent interchangeable units called modules. It is extremely useful, by following this paradigm, as the codebase grows, we can just create separate functions, and/or files rather than adding more lines of code into an already crowded file.

Take a look at the code below

<html>
    <head></head>
    <body>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script type="text/javascript" src="./components/a.js"></script>
        <script type="text/javascript" src="./components/b.js"></script>
        <script type="text/javascript" src="./main.js"></script>

    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

In the past, it is really painful to manage projects. As you can see above, when we want to add a new file, we also need to update the HTML script. This also applies when we want to update the dependency, remove files, etc. We also have to be mindful about many things (i.e. the order of the script, naming collision), and as the code grows bigger, it becomes tedious to manage all of this. This is one of the cases in which a module bundler might be helpful.

Module bundler is a development tool that processes your code into one bundle of code. It traverses your code from the provided entry point(s), builds a dependency graph, and produces the output files based on the configuration. So essentially just transform your application code into another form.

module bundler flow

There are at least two processes involved which are dependency resolution and packing. Dependency resolution is a process to create a relationship graph between each module/file called a dependency graph. The dependency graph is useful to identify the module retrieval order and to eliminate unreachable modules/files. Packing is a process of bundling everything based on the created dependency graph and the specified configuration into something that is executable by the browser. In the above case, out of all files in the above codebase, the module bundler produces only one file. And then later we can just insert main.js into the HTML.

<html>
    <head></head>
    <body>
        <script type="text/javascript" src="./main.js"></script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

One of the questions that might come to mind after seeing the above codes is “How do we debug this code in the browser if all the codes merged into one?”. The answer is a source map. A source map is a type of file that can help tools (i.e. browser) to reconstruct a minified code. Along with the executable code, a module bundler can also produce a source map. With a source map, we can debug the code in the browser like the code's original structure. Of course, we can disable it, if we don’t want our user to be able to read our code.

Things to pay attention

As we discussed earlier, Javascript has a lot of module bundlers. Each module bundler has its own unique configuration and terms. But they have a pattern and here are several configurations that you need to pay attention to.

Entry Point(s)

The entry point(s) indicates where the bundler should start traversing your code to create a dependency graph. You can specify one or multiple entry points. This is extremely useful when you are building a library, for example, a component library, as it doesn’t have a specific entry point.

// webpack.config.js
module.exports = {
  entry: './path/to/my/entry/file.js',
};

// rollup.config.js
export default {
  input: {
    a: 'src/main-a.js',
    'b/index': 'src/main-b.js'
  }
};
Enter fullscreen mode Exit fullscreen mode

Output

Output specifies where and how the bundled code should be placed after being processed. Naming, file splitting, and format are some examples that can be determined here.

// webpack.config.js
module.exports = {
    ...
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
};

// rollup.config.js
...
export default {
    ...,
    output: [
        {
            file: 'bundle.js',
            format: 'es'
        },
        {
            file: 'bundle.min.js',
            format: 'es',
            plugins: [terser()]
        }
    ]
};
Enter fullscreen mode Exit fullscreen mode

Plugin System

The great thing about module bundlers is a plugin system. A module bundler's main function is just well bundling. If we want to have some advanced functionality like a dev server, transform SCSS into CSS, polyfill new javascript functionality, uglifying code, etc., we need to add that functionality by inserting the appropriate plugin into the module bundler’s plugin system.

// webpack.config.js
...
module.exports = {
  ...,
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
      },
    ],
  },
  plugins: [
    new webpack.ProgressPlugin(),
    new HtmlWebpackPlugin({ template: './src/index.html' }),
  ],
};
// rollup.config.js
...
export default {
  ...,
  plugins: [graphql()]
};
Enter fullscreen mode Exit fullscreen mode

Quirk

Anything else is bundle-specific and advances features. Some bundlers are very opinionated (i.e. parcel, vite), and the others are like a blank canvas, you need to configure it yourselves (i.e. webpack). The best way to learn this is to read the official documentation.

Closing Thoughts

Nowadays, module bundler is very essential for application development. Understanding basic behavior is encouraged, but no need to understand everything. Of course, it is good to understand deeply, but for starters, just start coding and ask along the way.

If you have any comments or feedback, feel free to leave a comment below. Will be happy to discuss this with you all. Cheers!

Further Reading

Top comments (0)