DEV Community

Cover image for Gentle strides towards Webpack
Joe Oketch
Joe Oketch

Posted on

Gentle strides towards Webpack




USING WEBPACK

Gentle strides towards Webpack

Bundling bootstrap and a JS module

by: @JWokiri.


Post Overview

If you are using node to develop websites, and would wish to harness bootstrap functionalities (in somewhat a professional sense) then read this to the end.

If you are wondering what I am talking about then here's a brief description: ""
Bootstrap is an HTML, CSS, and JavaScript framework for developing responsive, mobile-first-design websites. It is completely free to download and use!

Webpack on the other hand is, amongst other things, a module bundler. It reads your html, css and JavaScript code and brings together every asset or module or component that makes your app function; and accordingly incorporates them in the final generated file(s).

I will, in this writeup show you how to use webpack to collect (therefore making them available for offline use) various bootstrap components to make our bootstrap-dependent app function properly. You will also see that a javascript file which is not necessarily part of the app but whose function we would need (therefore termed a module) is brought on board to facilitate a proper working of our very simple app.

I have prepared a github repo that compliments this post. You may give it a look ๐Ÿ‘‰ here.


Concept, Procedure and Requisites

Time to dive in...

1. Ensure you have nodejs installed.

This may be confirmed by verifying the version. Run the following code in your command prompt or powershell-- henceforth I will refer to either as terminal:

node --version
Enter fullscreen mode Exit fullscreen mode

The software is installed in my pc, and infact v14.15.3.

If you do not have node installed, please do so from nodejs official download website.

With node installed, we can then initialize our project (or package). Make and get into a directory of your choice e.g. "webpackbundling" and run the following command in the terminal:

npm init -y
Enter fullscreen mode Exit fullscreen mode

This will create a package.json file into the root of the directory. The -y flag is optional and is here used so that the default package.json file is automatically created, otherwise one would have to give a set of answers to a CLI questionnaire ๐Ÿ˜Ÿ๐Ÿ˜Ÿ.

My generated package.json file looks like this.

{
  "name": "webpackbundling",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Enter fullscreen mode Exit fullscreen mode

Our directory, webpackbundling, is now officially termed a package. Note that the path to every file or directory we create will be referenced from this root folder.

2. Next, we will install webpack and webpack-cli modules.

A module is any file or directory in the node_modules directory that can be loaded by the Node.js require() function.
Every module we install will be 'tracked' by the initially generated package.json. The benefit of this is that our package becomes easy for others to manage and install the very modules we used.

It is important to note that webpack module requires another module called webpack-cli to work properly. Webpack-cli is therefore termed webpack's peer dependency which need to be installed too. Also (optional, but highly recommended) we will install webpack-dev-server so that we may monitor our work progress in realtime.

These three will be installed as development modules by running either of the following command in the terminal:

npm install --save-dev webpack webpack-cli webpack-dev-server
Enter fullscreen mode Exit fullscreen mode

Or...

npm i -D webpack webpack-cli webpack-dev-server
Enter fullscreen mode Exit fullscreen mode

Once successful, open the package.json file to see the alterations that have occured. While at it, we need to make certain additions to help serve our needs.

In the "scripts" key, add the following values:


"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack serve --config ./webpack.config.js --mode=development --open",
    "build": "webpack --config ./webpack.config.js --mode=production"
  },

Enter fullscreen mode Exit fullscreen mode

Look keenly at the pieces of statement we have added; you will see that both 'start' and 'build' script commands are configured with a file called webpack.config.js.

We need to create this file in the root directory and appropriately populate it, but that will wait a bit.

3. We need the services of certain webpack modules.

Remember we are making a web app. Webpack needs to work with either a specified html file template or generate a default. We will explore both starting with the latter, but in anycase we need to install a plugin that is reponsible for handling this part of the business. It is called html-webpack-plugin.

Accordingly,

npm i -D html-webpack-plugin
Enter fullscreen mode Exit fullscreen mode

NOTE: html-webpack-plugin not only generates an HTML but also includes into it script and link tags properly sourcing or linking assets from their right location.

We will now create the webpack.config.js file and populate it in this manner:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: {
    mainApp: "./src/js/app.js",
  },

  output: {
    path: path.resolve(__dirname, "prod"),
    filename: "[name].js",
  },

  devServer: {
    port: 2021,
  },

  plugins: [new HtmlWebpackPlugin()],
};

Enter fullscreen mode Exit fullscreen mode

We are getting close to showing results, hold on just for a moment...

Look keenly at the module.exports json object:- At the entry key-- which is a basic webpack requirement, we named a json key mainApp (or anything you wish) and assigned a value of "./src/js/app.js to it. You know what we need to do, create that file, i.e a src directory, js directory and an app.js file therein.

Log "Webpack worked!" into the app.js file. i.e:

src/js/app.js

console.log("Webpack worked!")
Enter fullscreen mode Exit fullscreen mode

Now run the following into the terminal:

npm start
Enter fullscreen mode Exit fullscreen mode

What happened? Your default browser opened at the address http://localhost:2021/ with a blank page. Now, get over to the console and verify that our "Webpack Worked!" message is logged--- It sure did, at least for me. If yours did not, then re-read the technical procedure of this write-up to confirm that there are no impactful differences that caused the anomaly. Are we cool...?

Good Progress ๐Ÿ‘Œ๐Ÿ’ƒ๐Ÿ’ช

4. Incorporating Bootstrap and extracting css file.

Stop the local server with Ctrl + C and install bootstrap and sass-loader with their respective peer dependencies...

The modules (and some loaders) needed are listed below with their respective roles:

bootstrap: Used for website styling

jquery: Bootstrap peer dependency

popper.js: Bootstrap peer dependency

sass-loader: Used to turn scss into css

node-sass: Sass-loader peer dependency

css-loader: Turns css into common js

mini-css-extract-plugin: Extract css into files

Install them with the command:

npm i -D bootstrap jquery popper.js sass-loader node-sass css-loader mini-css-extract-plugin
Enter fullscreen mode Exit fullscreen mode

Make the folowing two files, then populate as shown:

1=> src/js/bootstrapStyling.js

2=> src/scss/bootstrapStyling.scss

src/js/forbootstrap.js

import "bootstrap"; //Javascript modules
import "../scss/bootstrapStyling.scss"; // scss, css
Enter fullscreen mode Exit fullscreen mode

src/scss/bootstrapStyling.scss

@import "~bootstrap/scss/bootstrap";
Enter fullscreen mode Exit fullscreen mode

Trust me, bootstrap is now ready to use!

Let's be sure about it by deliberatly using a certain bootstrap classes.

Make an HTML file and populate as shown:

src/myApp.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>

<body>
    <div class="container mt-sm-2 p-sm-4">
        <nav class="navbar navbar-expand-sm bg-light navbar-light">
            <span class="navbar-brand tertiaryFont">Distance Converter</span>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation" >
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item">
                        <a class="nav-link text-success font-weight-bolder" href="#">Home</a>
                    </li>
                </ul>
            </div>
        </nav>
    </div>

    <div class="container">
        <div class="container">
            <label for="distanceMiles">Distance in Miles:</label>
            <input type="text" class="form-control" id="distanceMiles" name="distanceMiles">

            <button id="submitID" type="submit" class="btn btn-outline btn-outline-success mt-2">Convert to Kilometers</button>

            <div class="pt-5 pb-5">
                <h5 id="answerID" class="font-weight-bold"></h5>
            </div>
        </div>
    </div>

    <footer class="mt-5">
        <div class="container">
            <div class="jumbotron mb-0">
                <h4 class="font-weight-bold text-center tertiaryFont mt-5">GENTLE STRIDES TOWARDS WEBPACK</h4>
                <h6 class="lead text-center mt-0">Bundling bootstrap and a JS module <small>using webpack</small></h6>
                <h6 class="lead text-center mt-0"><small><a class="nav-link" href="https://twitter.com/JWokiri" title="Connect in Twitter.">myTwitter</a></small></h6>
            </div>
        </div>
</footer>

</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Adjust webpack.config.js so that it is this:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: {
    mainApp: "./src/js/app.js",
    bootstrapStyling: "./src/js/bootstrapStyling.js",
  },

  output: {
    path: path.resolve(__dirname, "prod"),
    filename: "[name].js",
  },

  devServer: {
    port: 2021,
  },

  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          MiniCssExtractPlugin.loader, //Extracts css into files
          "css-loader", //Tuns css into common js
        ],
      },

      {
        //transpiles SCSS to js
        test: /\.s[ac]ss$/i,
        use: [
          MiniCssExtractPlugin.loader, //Extract css into files
          "css-loader", //Turns css into common js
          "sass-loader", //Turns scss into css
        ],
      },
    ],
  },

  plugins: [
    new MiniCssExtractPlugin({ filename: "[name].css" }),
    new HtmlWebpackPlugin({
      title: "My Gentle Webpack App",
      template: "./src/myApp.html",
    }),
  ],
};

Enter fullscreen mode Exit fullscreen mode

Delete the contents of "./src/js/app.js file and adjust it to:

import { miles_KMs, roundoff } from "./calculator";

const userInput = document.querySelector("#distanceMiles");
const submitID = document.querySelector("#submitID");
const answerID = document.querySelector("#answerID");


submitID.addEventListener("click", () => {
  // The value of your input
  let distanceMiles = userInput.value;

  // The results in kilometers after conversion
  let distanceKMs = miles_KMs(distanceMiles);

  // Writing answer into the dom
  let theAnswer = roundoff(distanceKMs, 3);

  if (theAnswer){
      answerID.style.color = "#28a745";
      answerID.innerHTML = `${theAnswer} kilometers`
  }else{
      answerID.style.color = 'red'
      answerID.innerHTML = `${distanceMiles} is not a valid number`;
  }
});

userInput.addEventListener('focus', () => {
    userInput.value = ''
})

Enter fullscreen mode Exit fullscreen mode

What have you noticed in the first line?

You saw that two functions, miles_KMs and roundoff functions are imported from a module called calculator.js.

Let's create this file THEN ENJOY THE FRUITS OF OUR LABOR:-

Create src/js/calculator.js and populate it as shown:

src/js/calculator.js

const miles_KMs = distInMiles => distInMiles / 0.62137;
const roundoff = (num, dp) => Number(Math.round(num + "e" + dp) + "e-" + dp);

module.exports = {
  miles_KMs,
  roundoff,
};
Enter fullscreen mode Exit fullscreen mode

All set. Webpack will now bundle everything together and give us a functioning app.

In the terminal, run

npm run-script build
Enter fullscreen mode Exit fullscreen mode

At the root folder, there is a new directory called prod that is generated. Navigate into it and open the /prod/index.html.

Enjoy a bundled functioning app ๐Ÿ˜œ๐Ÿ‘‹.

Top comments (0)