Webpack: Zero To Production (Part 1)

Vinod Chauhan
Dec 26, 2019 · 9 min read
Webpack Image

Webpack: Getting Started

The way we write JavaScript today is different from the code that the browser can execute. We frequently rely on other types of resources, transpiled languages, and experimental features which are yet to be supported in modern browsers. Webpack is a module bundler for JavaScript that can bridge this gap and produce cross browser–compatible code at no expense when it comes to developer experience.

Before we get started, you should keep in mind that all code presented in this Webpack tutorial is also available in the form of a complete Webpack example configuration file on GitHub. Please feel free to refer to it there and come back to this article if you have any questions.

I have made several commits in the repo for understanding webpack step by step. You can see particular on this link. And checkout to those commit e.g:

Please go through repo for understanding of the below examples link.

git checkout 89637f7ed458d8280c4542a2a87a6b2397594e7d

GitHub Webpack tutorial commits

First Commit : Simple App

=> git checkout 89637f7ed458d8280c4542a2a87a6b2397594e7d

I have made a simple application which takes username and userId from end-user and prints it on screen. It also have some validation for name and userId and gives error to end user. Also there is an image of webpack logo which we will optimize using webpack in further commits.

WebPack Tutorial Example
Index.html

https://gist.github.com/vinodchauhan7/497643664382ace761034ee6ae080afe

Open index.html file.

Second Commit : Broke Js code into 6 files

=> git checkout 1ca9ee0e85566146f477c530f4d4114f5e22372f

In this commit, I have divided the js code into 6 files so that we can simulate to a large example which will have many js files and can be used to make a single bundle file with webpack.

=> git checkout b9e7eb70469d5f6bd11c64cd54ba8a94532fb8a2

In this commit, I have added a package.json file and then added webpack. For package.json : npm init -y and then add : npm install — save -dev webpack webpack-cli. To start our application with webpack we have add a script in package.json file :

“scripts”: { “start”: “webpack” }

When we hit a command on npm start on terminal. It will give us error that we need to include ‘src/index.js’ file for webpack to work. On successful working of the npm start, a newFolder with dist including main.js will be there. We can include that main.js in our index.html. It will be working and webpack is handling our application. Open index.html to see on browser.

=> git checkout a08072f552066e02859a21c170ae243112bbcb0d

In this commit, We have used Import/Export for injecting the dependencies from one file to another and also remove <script> tags from html.

Fifth Commit : Add webpack config file

=> git checkout 194985095f6e24628a8c69e05f2d586bea96634c

In this commit, we have added our own webpack.config.js file for doing configurations.

  1. Path module is used to get the path of the system, so that we can dynamically get the path of the user system without any confusion. It is given to us by npm.
  2. module.exports is the configuration which webpack will look for.
  3. mode : There can be two value “development” & “production”. We are using “development” for now, to make the things working without any complexity.
  4. entry : It is the entry file to where webpack have to look for.
  5. output.path : It will tell webpack where to create the output folder. __dirname is something which will get the current path where your project is currently on your system. You can give any name to your ouput folder. I have given ‘dist’.
  6. output.filename : Here we will telling webpack, what our output file name will be.

Also we are updating package.json

“scripts”: {“start”: “webpack — config webpack.config.js”}

Sixth Commit : Add Loader to handle css

=> git checkout b296566130db6559264bda7e7423f2feab64a782

In this commit, we are introducing loaders.

webpack only understands JavaScript and JSON files. Loaders allow webpack to process other types of files and convert them into valid modules that can be consumed by your application and added to the dependency graph.

We are adding a new css file ‘index.css’ in which we are changing background & foreground color of the webpage and including it in our index.js file. And to load it in our webpack we need to use some loaders which can be found on webpack website. We are using “css-loader”,”style-loader”.

npm install — save-dev css-loader style-loader

css-loader : It will convert css into commonJs.

style-loader : It will inject js into dom.

Include below code in package.json

module: {
rules: [
{
test: /\.css$/,
use: [“style-loader”, // Inject commonjs into dom
“css-loader” //convert css into commonJs
]
}
]
}

In module tag, include rules tag.

  1. test : Here we need to add the extension of those files on which we need to add loader for webpack to build its dependency graph.
  2. use : It is dependency array where we need to add all our loaders. Note : We need to add loader in a proper order for them to work.

=> git checkout 33df9811e8ba4cc2e886d3ea3e4aa3d2c9b27bf8

In this commit, We are convering sass styles and also adding sass-loader in our webpack configuration to handle .scss file extension. For supporting sass in our webpack, we need to download two loader.

npm install — save-dev sass-loader node-sass

Update webpack.config.js’s rule set :

{ test: /\.scss$/, use: [“style-loader”, “css-loader”, “sass-loader”] }


=> git checkout a6e4b0746b85d63ff1d82d99867e09645222ab69

Cache Busting : When a static file gets cached it can be stored for very long periods of time before it ends up expiring. This can be an annoyance in the event that you make an update to a site however, since the cached version of the file is stored in your visitors’ browsers, they may be unable to see the changes made. This is due to the fact that a visitor’s browser will locally store a cached copy of your static assets given that your website is configured to leverage browser caching.

Cache busting solves the browser caching issue by using a unique file version identifier to tell the browser that a new version of the file is available. Therefore the browser doesn’t retrieve the old file from cache but rather makes a request to the origin server for the new file.

To implement cache-busting in webpack we will include ‘contentHashing’ in the name of our files, so that it will give new name everytime when we rebuild our application. It help us to achieve caching in browser and updation of files whenever there is a change in the files of application.

Output.filename : “main.[contentHash].js”

Till now we are using index.html to see our results in browser. But now we want webpack to dynamically create index.html in the dist folder so that it can dynamically include our main.[contentHash].js, without need to manually do it. For this we are creating a index.html in our src file in which we are not including <script src=’index.js’/> so that webpack will do it by itself.

For creating a new file we are using HtmlWebpackPlugin. and updating our webpack.config.js.

plugins: [ new HtmlWebpackPlugin({ template: “./src/index.html” }) ],

Nineth Commit : Add prod and dev configs, dev-server

=> git checkout 070366f8f133e50ffa5cbc1bad6cd049be5b6858

Till now, We are using webpack with ‘development’ mode. And if you got a chance to look at the main.js file in dist folder, its not minified and can be easily readable. Thats because we are not using ‘production’ mode.

In this commit, we are separating our production and development file and configuration which are common for both are in webpack.common.js. We are using webpack-merge package for merging webpack files.

Also we are including ‘webpack-dev-server’ for development so that we need not to manually reload the file.

npm install — save-dev webpack-dev-server webpack-merge

Tenth commit : Add html-loader, file-loader, and clean-webpack-plugin

=> git checkout 1f5ce61e7493ed020c0d67ed48f7f9762dcbe94c

Till now you have seen we are giving path of our svg image. But in this commit, we will dynamically set path of the images with webpack.

  1. We will remove image src from index.html
  2. We update our webpack.common.js with below command in the rules tag.

{ test: /\.html$/, use: [“html-loader”] },

{ test: /\.(svg|png|jpg|jpeg|gif)$/, use: { loader: “file-loader”, options: { esModule: false, name: “[name].[hash].[ext]”, outputPath: “imgs” } }

In the file-loader, we are giving options of the images and also setting name for the image with extension using hash coding. The output files will be in the “imgs” folder.

Next we are using, CleanWebpackPlugin() in the webpack.prod.js so that we need not to manually delete dist folder everytime for our new build.

Example app

Eleventh Commit : Add entrypoint for vendor js file, add bootstrap js

=> git checkout 6f4a5afc2fa1894b7737020007cb7c7aeba1157f

Suppose we have some third vendor libraries which are not changing frequently in the near future. To make them available as a part of cache, so that end user store them in their browser and performance of the application will improve. We need to give a new entrypoint in our webpack where it can be named as vendor as per example and we can include bootstrap there. To make it useful we are adding <nav> from bootstrap which needs jquery and popper.js in our application. As these are third party we dont need them to be rebuild and downloaded by user again & again. To fullfill this requirement, we need to make an entry in webpack.common.js

entry: { main: “./src/index.js”, vendor: “./src/vendor.js” },

And Output.filename : filename: “[name].[contentHash].bundle.js”

so that it can be loaded dynamically.

Twelveth Commit : Minify JS, CSS, and HTML in production.

=> git checkout 5f87d427df21d045cfe0965b2ff803dd97360a80

As we have seen we are including css in js and loading it when our JS is injected to DOM. This may cause styling issue to the user who has low internet connectivity. If you do the reload, you may see the flicker where css is not loaded will be seen. To extract css independentally and to minify the css, we need mini-css-extract-plugin & optimize-css-assets-webpack-plugin.

In webpack.prod.js

prod.js

If you check above snapshot, we are using optimization field to optimize & minify our css code using optimize-css-assets-webpack-plugin. As well as to optimize our js code we are using new TerserPlugin(), which is already in present in our node modules given by webpack. Here are using it because we are changing default implementation of the webpack configuration.

Also we are optimizing our html file with HtmlWebpackPlugin with remove whitespaces and comments etc.

Thirteenth Commit : Add Image optimization.

=> git checkout dff7ab12dad31e14c2ef75e48587ccf5af7a52f9

In this part, we are optimizing our images in our application because half of the performance of the application is degraded if our images are not optimized correctly. In this we are using image-webpack-loader & svg-url-loader.

We are setting the size of images upto 20 kb, so that they can be compressed and used as URL encoding.

Till now, I have covered all the general basics of the webpack, in part-2 I will cover webpack-react.

JavaScript in Plain English

Learn the web's most important programming language.

Vinod Chauhan

Written by

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade