Setup webpack for simple web application.

Setup webpack for simple web application.

Hi everyone lets understand how webpack works and how we can setup webpack for our simple web application. For building our web application we will not use any framework or library like React.JS, Angular or Vue.

First create simple application with HTML, CSS and Javascript. My application is a simple form that consists of two input fields name and age, a submit button that's it.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #simpleForm {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
      }
      #field {
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="simpleForm">
      <div>
        <label for="name">Name</label>
        <input type="text" name="name" />
        <br />
        <label for="age">Age</label>
        <input type="text" name="age" />
        <br />
        <button id="submit">submit</button>
      </div>
    </div>
  </body>
  <script>
    let form = { name: "", age: "" };
    const onChange = (event) => {
      const { name, value } = event.target;
      form[name] = value;
    };
    const formDiv = document.getElementById("simpleForm");
    formDiv.addEventListener("change", onChange);
    const submitButton = document.getElementById("submit");
    const onSubmit = function () {
      console.log({ form });
    };
    submitButton.addEventListener("click", onSubmit);
  </script>
</html>

Open your HTML file in browser and check if it works as expected.

Now lets initialize our project and install webpack where we can run our scripts.

npm init
npm --save-dev webpack webpack-cli

Project structure Selection_001.png

By default webpack tries to find "index.js" file if configuration is not provided. If we run without creating index.js file it will throw error, so create index.js file add console.log("This is index.js")

Before running the script make some changes to package.json, update the scripts to start webpack.

  "scripts": {
    "start": "webpack"
  },

Now run the start script

npm run start

This will create dist folder with main.js file which consists of same content that we have added in index.js file.

Selection_002.png

Now you can remove the javascript code within the script tag in index.html and add it to the index.js file, don't forget to provide location to the file in script tag.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #simpleForm {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
      }
      #field {
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="simpleForm">
      <div>
        <label for="name">Name</label>
        <input type="text" name="name" />
        <br />
        <label for="age">Age</label>
        <input type="text" name="age" />
        <br />
        <button id="submit">submit</button>
      </div>
    </div>
  </body>
  <script src="./index.js"></script>
</html>

Run

npm run start

dist folder is created, check main.js file it will now consist of code that we have added in index.js file

Let's recap what we have learned so far:

  • By default webpack looks for "./src/index.js" file.
  • By default webpack creates "./dist/main.js", just remember dist folder does not consist of any html file as of now.
  • dist folder is of no use to use as it does not include all the files required to run our application, missing files are index.html which consists view of our application.

Let's move to second part how can we override default properties of webpack.

Create webpack.config.js

const path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
};

"entry" key requires file location that can resolve your dependency graph of your project. In our case it is index.js file.

"output" has two properties filename and path where dist folder will be created.

You can use any entry filename, output filename and path as you want.

Now run script "npm run start"

Check the dist folder it consist of "main.js" with minified code, if we don't want the minified code we can use another property "mode" and set its value to "development". Run the script again and check main.js in dist folder this will create unminified code.

const path = require("path");

module.exports = {
  mode: "development",
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
};

Tranformation

For transforming our code we use loaders by default webpack is able to perform transformation on javascript and json files.

In our index.html file we have added css using internal way i.e using style tag but in real world application we have seperate css files and add it to our application using external way i.e using link tag.

We need to setup our code remove the css code in the style tag in index.html and add it to the index.css file, import index.css file in index.js file.

Now our aim is to add css to our main file for that we are going to add another property "module.rules" to the webpack.config.js

const path = require("path");

module.exports = {
  mode: "development",
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [{ test: /\.css$/, use: ["style-loader","css-loader"] }],
  },
};

test: specifies type of file we want to transform use: specifies list of loaders that we want to use to transform Remember the last item in the use array will be the first to be used for transformation i.e. css-loader will be the first, than style-loader will be used.

Now let's install css-loader and style-loader.

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

css-loader will add our CSS from all the files having .css extension to dist/main.js file. style-loader will inject CSS to our index.html file.

Run the start script you can check your CSS in main.js file.

To check if our main file works as expected we can update the script link in the index.html to "../dist/main.js". Open the index.html file in browser we can see that CSS is loaded automatically using internal CSS Selection_003.png

As of now our dist folder only contains main.js file it does not contain html file. So lets try to add it to our dist file for this we will another property called plugins.

Plugins allow us to perform task after the bundle has executed

Install html-webpack-plugin

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

This plugin will add HTML file for us in dist folder and add link to the main.js file in script tag.

Run start script you can now see index.html file in dist folder, it does not contain any child in the body so when we run this index.html file it will show us blank screen and our main.js will not be able to access the required input fields it is trying to.

To overcome this, we can create our own template and lets name this as template.html. Copy paste the code from "src/index.html" to ''src/template.html" remove all the script or style tag from the template.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="simpleForm">
      <div>
        <label for="name">Name</label>
        <input type="text" name="name" />
        <br />
        <label for="age">Age</label>
        <input type="text" name="age" />
        <br />
        <button id="submit">submit</button>
      </div>
    </div>
  </body>
</html>

Run start script and open "/dist/index.html" in browser you can see your html files loads as expected with CSS and main.js

Lets try to create different webpack config for development and production because bundle required for production than development. Create two files with name webpack.dev.js and webpack.prod.js, copy the content in webpack.config.js to the newly created webpack files and delete webpack.config.js file.

Project structure

Selection_004.png

Change mode to production in webpack.prod.js

Now that we have different webpack config for different ENV we can add webpack-dev-server, this will add hot reloading during development env.

npm install --save-dev webpack-dev-server

update the config in package.json file

  "scripts": {
    "start": "webpack-dev-server --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
  }

Run npm run start, hot reloading is enabled.

Now you can run start script for development purpose and build script for production.

You can always read more about webpack from it's official documentation webpack.js.org/concepts

For more configuration settings you can check this link from webpack.js.org/configuration/#use-a-differe..