Getting Started with Webpack in JS Projects

In this tutorial, I am going to show you how you can configure a javascript project using Webpack. For reference you can checkout this github repository for the code https://github.com/sujaykundu777/ts-webpack-boilerplateGithub Commit Ref Follow this change commit.

Create a new project

$ mkdir webpack-boilerplate
$ npm init -y

Now our package.json looks like :

{
  "name": "ts-webpack-boilerplate",
  "version": "1.0.0",
  "description": "A Boilerplate for building webapps using TS",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Create Directories

$ mkdir src public

Create src/index.js

$ cd src
$ touch index.js 

Paste the following code :

// our main file
console.log("hello world");

Create public/index.html

We will try to use Semantic HTML and Accessibility Aria Attributes wherever possible (best practices).


<!DOCTYPE html>
 <html lang="en-US">
  <head>
        <title> Webpack Boilerplate </title>

        <meta name="charset" content="UTF-8" />
        <meta name="description" content="Webpack Boilerplate App" />
        <meta name="keywords" content="javascript, typescript, webpack, boilerplate, webpack-boilerplate" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    </head>
    <body>
        <header> 
            <div id="logo">
                <h1> WEBPACK BOILERPLATE</h1>
            </div>
        </header>

        <main>
            <h1> This is a setup built on Webpack</h1>
        </main>

        <footer>
            <p>© 2023</p>
        </footer>
    </body>
</html>

Create a .gitignore file ( to tell ignore not to commit this extension files)

.cache/
coverage/
dist/*
!dist/index.html
node_modules/
*.log

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

Folder structure :

Now our Project directory structure will look something like this :


webpack-boilerplate/
  ├── dist/
	│   ├──  index.html
  ├── src/
  │   ├── index.js
  │   └── ...
  ├── README.md
  ├── package.json
  ├── package-lock.json
  ├── .gitignore
  └── ...

01 – Setup Webpack

We will use webpack for bundling our assets

npm install --save-dev webpack webpack-cli

Create a file -> webpack.config.js :

const webpack = require("webpack");
const path = require("path");

const config = {
  mode: "development",
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  },
};

module.exports = config;

Add watch script, In our package.json add the following command :

 "scripts": {
    "watch": "webpack --watch" 
  },

Now run watch command to make our dist/bundle.js :

npm run watch 

You can see, webpack generated a bundle.js based on our entry : index.js file inside dist directory.

Your package.json will look like this :

```json 
{
  "name": "ts-webpack-boilerplate",
  "version": "1.0.0",
  "description": "A Boilerplate for building webapps using TS",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "watch": "webpack --watch"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.88.2",
    "webpack-cli": "^5.1.4"
  }
}

```

Github Commit Ref Follow this change commit.

Let’s create a Basic App :

We will create the code with commonjs, but will optimise it later to use ESM.

We will create few pages Home, About, Contact Page

Modify index.html file like this :

  <!DOCTYPE html>
 <html lang="en-US">
  <head>
        <title> TS Webpack Boilerplate </title>

        <meta name="charset" content="UTF-8" />
        <meta name="description" content="TS Webpack Boilerplate App" />
        <meta name="keywords" content="javascript, typescript, webpack, ts-boilerplate, webpack-boilerplate" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    </head>
    <body>
        <header> 
            <div id="logo-container">
                <h1> TS WEBPACK BOILERPLATE</h1>
            </div>
            <div id="nav-container">
                <nav aria-label="Navigation">
                     <ul role="menu" aria-label="menu">
                        <li role="menuitem" aria-label="Home">
                            <a href="/"> Home </a>
                        </li>
                        <li role="menuitem" aria-label="About">
                            <a href="/about"> About </a>
                        </li>
                        <li role="menuitem" aria-label="Contact">
                            <a href="/contact"> Contact </a>
                        </li>
                    </ul>
                </nav>
            </div>

        </header>

        <main>
            <h1> This is a setup built on Webpack, Typescript, SAAS</h1>

            <div id="app"></div>
        </main>

        <footer>
            <p>© 2023</p>
        </footer>
    </body>
</html>

Router

We need a router to show different views on link refs like ‘/‘, ‘/about’, ‘/contact’

Create a components/Router.js

class Router {
  constructor(container) {
    this.routes = {};
    this.container = container;
    this.currentRoute = null;

    // Listen for changes in the URL
    window.addEventListener("popstate", () => {
      this.handleRouteChange(window.location.pathname);
    });
  }

  // Add a route and its corresponding handler
  addRoute(path, handler) {
    this.routes[path] = handler;
  }

  // Handle a route change
  handleRouteChange(path) {
    if (this.routes[path]) {
      // Call the handler for the current route
      this.routes[path]();
      this.currentRoute = path;
    } else {
      // Handle 404 - Route not found
      console.log("Route not found");
    }
  }

  // Initialize the router
  init() {
    // Handle the initial route
    this.handleRouteChange(window.location.pathname);
  }
}
module.exports = Router;

And in our index.js file:

// entry index.js
console.log("hello world");

// import Router
const Router = require("./components/Router");

// Get the container element where you want to render views
const appContainer = document.getElementById("app");

const router = new Router(appContainer);

router.addRoute("/", () => {
  appContainer.innerHTML = "<h1>Welcome to the Home Page</h1>";
});

router.addRoute("/about", () => {
  appContainer.innerHTML = "<h1>About Us</h1><p>This is the about page.</p>";
});

router.addRoute("/contact", () => {
    appContainer.innerHTML = "<h1> Contact Us</h1><p> This is the contact page. </p>"
})

router.init(); // intialize our routes

Now serve the app :

npm run serve

Now you can see a menu with three links, Home, About and Contact. When you go the link it will show the particular view.

Adding Styles

So let’s add some global styling for our app, add a public/styles/global.css file:

body {
  font-family: sans-serif;
}

#main-heading {
  font-size: 40px;
  color: red;
}

And add a heading in our public/index.html

<!DOCTYPE html>
 <html lang="en-US">
  <head>
        <title> TS Webpack Boilerplate </title>

        <meta name="charset" content="UTF-8" />
        <meta name="description" content="TS Webpack Boilerplate App" />
        <meta name="keywords" content="javascript, typescript, webpack, ts-boilerplate, webpack-boilerplate" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />

           <!-- our global styles -->
        <link rel="stylesheet" type="text/css" href="./styles/global.css" />
    </head>
    <body>
        <header> 
            <div id="logo-container">
                <h1> TS WEBPACK BOILERPLATE</h1>
            </div>
            <div id="nav-container">
                <nav aria-label="Navigation">
                     <ul role="menu" aria-label="menu">
                        <li role="menuitem" aria-label="Home">
                            <a href="/"> Home </a>
                        </li>
                        <li role="menuitem" aria-label="About">
                            <a href="/about"> About </a>
                        </li>
                        <li role="menuitem" aria-label="Contact">
                            <a href="/contact"> Contact </a>
                        </li>
                    </ul>
                </nav>
            </div>

        </header>

        <main>
              <!-- add a id main-heading in our heading -->
            <h1 id="main-heading"> This is a setup built on Webpack, Typescript, SAAS</h1>

            <div id="app"></div>
        </main>

        <footer>
            <p>© 2023</p>
        </footer>
    </body>
</html>

Serve the web app:

npm run serve

You should now be able to see the font changed and a red heading

Github Commit Ref Github commit reference for Setup routing and styling

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *