Webpack module bundler
Tags: javascript, webpack, typescript
Published: 2022-03-15 11:42:32

# Overview

In this blog post, we will show you, what developers are facing problems earlier with libraries and frameworks, how the webpack bundle is solving the problem, and use case of the webpack bundle for typescript base applications.

Also, we will show you, core concepts with help of examples and functions of webpack bundle.

# What was the Problem before webpack.

<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_bundler_01.jpg"
  alt="A image to visualize, what happened when so many frameworks and libraries are involved in project." 
  width=800>
</figure>

We are as JS developers, have a huge dev community, involved in the constant quest of improving the overall user and developer experience around using and building JavaScript/web applications, therefore we are creating new libraries and frameworks.

A few design patterns also evolved to give developers a better, more powerful yet very simple way of writing complex JavaScript applications. 

Gradually, they started getting bulky, with the introduction of JavaScript modules, eventually, all of this led to a situation where we had 4x or 5x files in the overall application package.

So, the overall size of the application is a challenge. Now, question is, how to manage the dependencies and size of the application.



# What is Webpack Module Bundler?

<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_bundler_02.png"
  alt="A image to visualize, what is webpack module bundler." 
  width=800>
</figure>

Webpack is a JavaScript library, built and maintained by **Tobias Koppers and the team**. It is an aggressive and powerful module bundler for JavaScript applications.

It packages all the modules (files like CSS, HTML, Typescript, .env, etc..) in your application into one or more bundles (often, just one file, main.js or index.js or index.html(browser)).

Webpack is taking the help of **loaders** and **plugins**, then, it can **transform**, **minify** and **optimize** all types of files before serving them as one bundle to the browser or server.

# How webpack is worked internally ?

<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_bundler_03.png"
  alt="A image to visualize, how webpack is worked internally"  
  width=800>
</figure>
 
In brief, Webpack goes through your package and creates what it calls a **dependency graph** which consists of various modules which your application/project would require to function as expected.
 
Depending on this graph, it creates a new package which consists of the very bare minimum number of files required, often just a single bundle.js or index.js file which can be plugged into the HTML file (if react Application) or main.js (Server-side application) easily and used for the application.



# Core concepts

* Entry
* Output
* Loaders
* Plugins
* Mode


## Entry

> The entry object is where webpack looks to **start building the bundle**. The context is an absolute string to the directory that contains the entry files.

_single entry file_

```
module.exports = {
  entry:'./src/index.js'
}
```

_multiple entry file_

```
module.exports = {
  entry: ['./src/file_1.js', './src/file_2.js'],
}
```

## Output

> Configuring the output configuration options tells webpack **how to write the compiled files to disk**. Note that, while there can be multiple entry points, only **one output** configuration is specified.

```
module.exports = {
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, 'dist'),
    filename: 'main.js'
  }
}
```

Some `libraryTarget` options, which version of ECMAScript you want to output.

1. libraryTarget: "umd", // enum
2. libraryTarget: "umd-module", // ES2015 module wrapped in UMD
3. libraryTarget: "commonjs-module", // ES2015 module wrapped in CommonJS
4. libraryTarget: "commonjs2", // exported with module.exports
5. libraryTarget: "commonjs", // exported as properties to exports
6. libraryTarget: "amd", // defined with AMD defined method
7. libraryTarget: "this", // property set on this
8. libraryTarget: "var", // variable defined in root scope

# Loaders

> Loaders are **transformations** that are applied to the source code of a module. They allow you to pre-process files as you import or “load” them.

> Loaders can transform files from a different language (like TypeScript) to JavaScript or load inline images as data URLs. Loaders even allow you to do things like import CSS files directly from your JavaScript modules!

```
module.exports = {
  /*...*/
  module: {
    rules: [
      {
        test: /\.css$/,
        use:
          [
            'style-loader',
            'css-loader',
          ]
      }
    ]
  }
  /*...*/
}
```

Few examples of Loaders,

1. **sass-loader**: Loads a SASS/SCSS file and compiles it to CSS. It requires node- sass to work.
2. **node-sass**: This library allows you to natively compile .scss files to CSS at incredible speed and automatically via a connect middleware.
3. **css-loader**: The css-loader interprets @import and url() like import/require() and resolves them.
4. **style-loader**: Add CSS to the DOM.
5. **file-loader**: Instructs webpack to emit the required object as a file and to return its public URL.
6. **image-webpack-loader**: Minify PNG, JPEG, GIF, and SVG images with imagemin.


# **Plugins**

> Webpack contains default behaviors to bundle most types of resources. When loaders are not enough, we can use plugins to **modify** or **add capabilities** to Webpack.

> Plugins are like loaders but on steroids. They can do things that loaders can’t do, and they are the main building block of webpack.

```
module.exports = {
  /*...*/
  plugins: [
    new HTMLWebpackPlugin(),
    new CleanWebpackPlugin(['dist']),
  ]
  /*...*/
}
```

**HTMLWebpackPlugin** plugin has the job of automatically creating an HTML file, adding the output JS bundle path, so the JavaScript is ready to be served.

**CleanWebpackPlugin** can be used to clear the dist/ folder before creating any output, so you don’t leave files around when you change the name of the output file.


# Mode 

> This mode (introduced in webpack 4) sets the **environment** on which webpack works. It can be set to **development** or **production** (defaults to production, so you only set it when moving to development)

**Production**

<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_production.png"
  alt="describe the production build file webpack bundle"  
  width=800>
</figure>
 
**Development**
<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_development.png"
  alt="describe the development build file webpack bundle"  
  width=800>
</figure>

#Installing webpack

###Global install

with Yarn:

`yarn global add webpack webpack-cli`

with npm:

`npm i -g webpack webpack-cli`

Once this is done, you should be able to run `webpack-cli` in cmd and add this to your `package.json` file:

```
{
  //...
  "scripts": {
    "build": "webpack --config webpack.prod.js"
  }
}
```

then run `npm run build`

## Example

_Console output_

<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_example.png"
  alt="describe the development build file webpack bundle"  
  width=800>
</figure>

JFrog deployed npm package: 

<figure align="center">
  <img
  src="https://cdn.svc.oneadvanced.com/engineering-blogs/webpack-module-bundler/webpack_module_npm_package.png"
  alt="describe the development build file webpack bundle"  
  width=800>
</figure>