Essential Tooling for Javascript Developers: Webpack In-Depth.

Alok Sharma
Level Up Coding
Published in
10 min readMay 19, 2020

--

In this series, We will be discussing and understanding all the essential tools that are an integral part of any Javascript Developers Life. We will be learning tools and technologies like Command-Line Interface, NPM, Git and GitHub, Webpack and Babel, etc. along with understanding the purpose and needs of each one of them.

Topics Covered in the Series—

  1. Command Line Interface.
  2. NPM.
  3. Git and Github.
  4. Webpack and Babel.

I will be splitting webpack into a series as it can’t be covered in just one article. This article will cover What, Why, and How of Webpack (Basic to Intermediate). And the upcoming articles will take you through Advanced Webpack concepts.

What is Webpack?

Webpack is an open-source Javascript module/assets bundler.

Open Source

A Software is said to be open source if it is publicly accessible i.e. Users can use, share as well as suggest improvements to such software. ExamplesNode.js, Bootstrap, Webpack, Linux, etc

What is a Module bundler?

In order to write more Readable, Scalable, and Maintainable code, We as developers make use of ‘Architectures andDesign Patternsto split our application into multiple smaller components (known as modules).

Module bundler is simply a tool that analyzes connections between different modules and bundles all these different modules together to form one file of each type.

Webpack Overview

Webpack is one such module bundler. As you can see in the image above Webpack takes different modules(files like .scss, .js,.jpg,.png) and combines them together to form one single file of each type (.js,.css, etc). It also performs all kinds of optimizations like Tree shaking, Transpilation, Polyfilling, Compressing, Minification, etc.

Now, To understand Why do we need Webpack, We need to understand the difference between Development and Production code.

Development Vs Production?

Development code is simply the code with which the developers and programmers work with.

  • While working on a project if developers only use one ‘style.css’ or ‘index.js’ file with thousands of lines of code then our code will get easily overcrowded and unmanageable.
  • So, depending upon the size and the scope of the project different setups are used to split the application into smaller components, which when combined together forms the complete application. This makes our code more Readable, Scalable, and Manageable.

For Example — The development project structure i.e. source code (src)of this tutorial looks like —

Development setup

As you can see there are multiple .scss, .js files present in our source code. All these files are interconnected. I have imported all my sass partial files (files starting with _) into the ‘main.scss’ and all my .js files like feature1,feature2… etc in the ‘index.js’. ‘index.js’ will look like this

index.js

Production code refers to the final code that will be live on the servers i.e. the code that the users will be interacting with. For the users, it doesn’t matter how the codebase is split up and developed behind the scenes as they don’t have to work with the code, what matters to them is if that application works or not and that too efficiently.

So, with the help of using module bundler, our final production setup will look like —

As you can see there is only one ‘bundle.js’ file in the ‘dist’ folder within the ‘js’ folder. Also, there are no style files present in the ‘dist’ folder but still, all the styles will be working. (Although I will show you, how you can also extract your CSS file separately.)

Note — ‘dist’ stands for ‘distribution’. It is simply a standard name that is used for production code. Also if I will look into the bundle.js it will look something like this —

bundle.js

Complete Gibberish!!. But all of this code works. It simply looks like this due to the optimizations so that the final bundled file is minified, compressed, and smaller in size.

Conclusion — Webpack will apply some transformations on our source/development code i.e. ‘src’ folder and will provide us with the final optimized production code i.e. a ‘dist’ folder.

To understand how ‘webpack’ is configured Let's create a Project

Project Starter —

Project Starter

I have created a Project Folder named — Webpack-In-Depth (choose whatever name you want.)

  • At the root level, it contains an index.html file and an src folder. (you can even use index.html within your src folder but I prefer using it this way.)
  • src folder further contains three subfolders — assets (all images), js, and sass.

Installing Webpack —

To install Webpack we need to install 2 packages. Open the terminal and write command —

npm install webpack webpack-cli --save-dev
  • webpack — The package that contains all the ‘webpack’ functionalities.
  • webpack-cli — The package that allows us to use ‘webpack’ functionalities. Earlier it was part of the ‘webpack’ package itself but with ‘webpack4’ it was separated into its own package.

Configuring Webpack —

In order to configure ‘webpack’, we need to create a ‘webpack.config.js’ file at the root level of the project.

webpack.config.js

Within webpack.config.js we need to write our project configuration and export it.

Configuring Webpack Step by Step —

Webpack uses Common Js Modules

Webpack uses Node.js behind the scenes and Node.js uses Common JS modules as standard instead of ES6 modules, which is why to export the configuration we need to use module.exports instead of export default and require instead of import, to import a module.

module.exports = {}

entry

  • entry point simply refers to the starting point from where ‘webpack’ should start bundling the modules i.e. the main javascript file ‘index.js’ (In my case)
entry: "./src/js/index.js"

Note — If you have created a different project structure choose the path accordingly.

output

  • output simply refers to where the final bundled file should be present i.e. Within the ‘dist’ folder.
  • output property is an object which further consists of properties path and filename.
  • path refers to the absolute path of the final bundled file.
  • In order to construct the absolute path, we need to make use of Node.js inbuilt ‘path’ package.

To import the path package —

const path = require("path");

To construct the absolute path —

path: path.resolve(__dirnanme,"dist")
  • path.resolve simply helps us to resolve a path into an absolute path. __dirname refers to the current working project folder Webpack-In-Depth (In my case). So, path.resolve(__dirname) will construct the absolute path of our current working folder.
  • Within my current working folder, I want my final bundled file to be present in the ‘dist’ folder.
  • filename refers to the name of the final bundled file. bundle.js is a standard name that is used. (you can choose whatever name you want)
  • I want ‘bundle.js’ to be present in a ‘js’ folder within dist folder that's why —
filename: "js/bundle.js"
  • If you don't want to create another ‘js’ folder within ‘dist’ replace js/bundle.js by bundle.js only —
filename: "bundle.js"

Loaders

Webpack is a javascript module bundler but it can still bundle and process other kinds of modules like .css, .scss, .jpg, .png, etc with the help of loaders.

  • Loaders simply apply some kind of transformations on a per-file basis.
  • To use loaders we need to first install them. (doesn't come along with webpack)
  • To configure loaders we need to specify the module property.
  • module property is an object that further consists of the rules array.
  • rules array contains the set of rules that how certain types of files should be handled.
module : { 
rules: []
}

Handling Styles (.css, .scss files) — In order to handle styles, we need to install some loaders —

npm install style-loader css-loader sass-loader node-sass --save-dev
  • sass-loader — It makes use of the node-sass package to convert SASS code into equivalent CSS code
  • css-loader — It converts CSS code into that of equivalent Javascript code.
  • style-loader — Attaches that equivalent javascript code to that of the DOM.

Specifying the rule

rules: [ 
{
test: /\.scss$/',
use: ['style-loader','css-loader', 'sass-loader']
}
]
  • test property is a regular expression.

Note — You don't need to learn regular expressions to work with loaders just remember the above pattern. But if you want to go in-depth you can check my article about Demystifying RegEx.

  • use property specifies that which loaders should be used to handle files. (It doesn’t have to be an array it can also be an object if we want to pass some extra configuration.)

The above rule simply states — All those files that end with the .scss extension should be handled by these loaders — style-loader, css-loader, sass-loader

Note — Make sure the sequence is the same as it evaluates from right to left. Also if you are not using sass no need to use sass-loader simply omit it.

Plugins

  • Plugins allow us to perform transformations on the final bundled file like ‘bundle.js’
  • To use Plugins we need to first install and import them.

html-webpack-plugin — It creates a new index.html file in the ‘dist’ folder and will automatically inject our bundle.js into it. To install

npm install html-webpack-plugin --save-dev

To import —

const HtmlWebpackPlugin = require('html-webpack-plugin');

To configure plugin — We need to create and configure an instance using the new keyword which will be passed an object as configuration.

plugins: [  new HtmlWebpackPlugin({   filename: "index.html",   template: "./index.html",  }),]
  • filename — refers to the name of the new Html file that you want to create in the ‘dist’ folder. (index.html is the standard name, you can choose whatever name you want).
  • template — refers to the file from where the content should be copied to the newly created file.

So the above plugin will — Create a new ‘index.html’ file in the ‘dist’ folder after copying all the content from the template file and will inject the bundle.js file into it.

Note — Because my index.html file was present at the root level that's why —

template: './index.html'

If your index.html was present in the src folder then you again need to create an absolute path as —

template: __dirname + './src/index.html'

But only this setup won’t work properly as there is a major problem.

Problem

  • Suppose there are some images that we have used in our index.html file. All images require an src attribute. And the value of each src attribute in index.html is written relative to the assets folder like—
Path relative to assets folder

But as html-webpack-plugin will create a new index.html file in the ‘dist’ folder, So this path will become invalid for the ‘dist’ ‘index.html’ as there is no ‘src’ folder present within the ‘dist’ folder. So to make these paths dynamic we need to make use of some Loaders.

Handling Image Files (.svg, .jpg, .png, .gif) — In order to handle images, we need to use html-loader and file-loader.

npm install html-loader file-loader --save-dev

Configuring html and file loader —

{ test: /\.html$/, use: ["html-loader"] },{   test: /\.(svg|png|jpg|gif)$/,   use: {     loader: "file-loader",     options: {       name: "[name].[ext]",       outputPath: "img",       },   },},

file-loader rule simply states — All those files that end with the .svg, .jpg .png, .gif extension should be handled by file-loader.

  • file-loader will copy all the image files that were encountered in the ‘index.html’ in ‘src’ into the ‘dist’ folder.
  • For the example above — It will copy the webpack-banner.png file from the assets folder into an ‘img’ folder as webpack-banner.png ([name].[ext]) within the ‘dist’ folder.

‘html-loader’ will then automatically determine its absolute path and will inject it in the newly created ‘index.html’ in the ‘dist’ folder. So the final index.html file will be like —

Running Webpack

Simply create new npm scripts in your ‘package.json’ and pass ‘webpack config.js’ as configuration to it.

npm scripts

mode development — development bundle is comparatively larger in size with very little optimization.

mode production — production bundle is very small in size with all kinds of optimizations.

simply run these scripts in the terminal as npm run build or npm run dev and see the webpack’s magic.

That’s it for this article. Other Advanced Webpack Concepts will be discussed in the upcoming articles. If you find this article helpful just do let me know. Stay Tuned!!!

--

--