๐Ÿ“– Setting Up Webpack

As your applications grow in complexity, managing your modules and preparing them for production becomes more challenging. Webpack is a powerful tool that helps bundle your modular code into optimized files, ensuring your projects are both efficient and easy to maintain. In this article, we'll explore how to set up and use Webpack to bundle your JavaScript modules and understand how its structure differs from a typical web project.

Task

Your task is to set up and configure Webpack for a modular JavaScript project. We'll walk through setting up a basic Webpack configuration, organizing your project structure, and understanding how to prepare your code for deployment. Mastering this will allow you to automate the process of combining and optimizing your code.

Core Concepts

What is Webpack?
Webpack is a module bundler that takes your modular code and bundles it into a single (or multiple) file(s) that can be easily deployed to the web. It handles dependencies, optimizes code, and can even bundle assets like stylesheets and images.
File Structure in a Webpack Project
Unlike traditional web projects where all files might be directly in the root folder, a Webpack project organizes source files in a src folder, uses a dist folder for output, and relies heavily on a node_modules directory for dependencies.
Using .gitignore
When using Node.js and Webpack, certain files and directories should not be tracked in your version control. For example, node_modules should be excluded from Git using a .gitignore file to avoid pushing unnecessary dependencies to your repository.

Getting Started

Let's set up for a simple JavaScript project. Before you begin, make sure Node.js and Node Package Manager (npm) are installed on your machine. You can verify your installation by running the following commands in your terminal.

Node.js

Node.js is a runtime environment that allows you to run JavaScript code outside of a web browser, typically on a server. Node.js comes with npm (Node Package Manager), which simplifies package and dependency management, allowing developers to install and share libraries and tools easily.

# Check Node.js version
node -v

Node Package Manager (npm)

Node Package Manager (npm) allows developers to install, manage, and share reusable packages (libraries, tools, frameworks) that can be easily integrated into their projects.

# Check npm version
npm -v
        

If these commands return version numbers, you're ready to go. If not, you'll need to download and install Node.js first.

Project Setup

Initialize npm by running the following command.

# Initialize npm
npm init -y

Running npm init sets up the foundation of a Node.js project by generating a package.json file that stores critical project details, allowing you to manage dependencies, scripts, and configurations.

The -y flag (or --yes) in the npm init command is used to automatically answer "yes" to all prompts when setting up a new package.json file. This means it will skip the interactive questionnaire and create the package.json file with default values. Once the script finishes, you should see the new package.json file in the root directory of your file system.

Install Webpack

Run the npm install webpack command to install webpack and its dependencies.

# Install Webpack and Webpack CLI
npm install webpack webpack-cli --save-dev

The command npm install webpack webpack-cli --save-dev installs Webpack and the Webpack CLI as development dependencies for your project. This will set up Webpack as part of your project's development environment.

Running npm install (including npm install webpack webpack-cli --save-dev) will generate a package-lock.json file if it doesn't already exist in your project. It also installs a new directory named node_modules with files that help the development process.

The package-lock.json file is created by npm to lock the versions of installed dependencies. The package-lock.json file ensures that anyone who installs your project's dependencies gets the exact same versions that you installed, providing consistency across different environments.

Create the webpack.config.js File

Once webpack is installed, create a webpack.config.js file in your project's root directory with the following configuration. This is a basic configuration file which can be customized for specific project needs.

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js', // Entry point: your main JavaScript file
  output: {
    filename: 'bundle.js', // The output file after bundling
    path: path.resolve(__dirname, 'dist'), // The output directory
  },
  mode: 'development', // You can switch to 'production' for optimized builds
};

In this configuration:

entry:
Specifies the main file where Webpack should start bundling.
output:
Defines the output directory and filename for the bundled code.
mode:
Specifies whether to create a development build (unminified, easier to debug) or a production build (optimized, minified).

Organizing Your Project Files

At this stage, we want to set up the project file structure in a way that aligns with how modern modular applications are typically organized. This involves creating the src folder, where all your JavaScript files will reside, along with other key configuration files.

Create a src folder in your project's root directory. You will place all your JavaScript files there, such as your main file (index.js) and any other modules like dataManager.js and uiManager.js. Your file system should look like this at this time.

/my-project
    /node_modules
    /src
    package-lock.json
    package.json
    webpack.config.js

Understanding Your Project

In our project, the index.html file is still the first file the browser loads when a visitor comes to your site. But now, we're introducing a slightly different way of handling the logic behind your application.

In a modular project, the main file (often named index.js) is the entry point for your application. The main file acts as the โ€œcentral hubโ€ for your application and brings together the various modules that make up your application.

Previously, you might have had multiple <script> tags in your HTML, loading various JavaScript files. This can get messy as projects grow. Instead, we're now using a main JavaScript file (called index.js) to pull everything together in one place, and Webpack helps us bundle all that code into a single file when we run the Webpack build process.

Here's how it works.

  1. The browser first loads index.html.
  2. index.html includes a single <script> tag that loads the bundled JavaScript file generated by Webpack.
  3. The bundled file(created from index.js and any other modules) runs the logic for your application.

The index.html File

The index.html page plays a vital role as the entry point that the browser loads when a visitor accesses your site. It gives the basic structure and layout for your web page. Itโ€™s where you define the elements that make up the user interface (like input fields, buttons, and containers). This HTML file is what the browser first loads when a user visits your site.

The index.html file includes a <script> tag that links to the bundled JavaScript file (e.g., /dist/bundle.js) generated by Webpack. This bundled file contains all the logic from your index.js file and any other modules you've created. Here's how it looks in the HTML.

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

    <body>
        <!-- page content goes here... -->
        
        <script src="dist/bundle.js"></script>
    </body>

</html>

Create the index.html file and place it in the root directory of your site files.

The index.js File

It's time to create your main file, index.js, as shown below and place it in the /src directory. Paste the contents below into a file named index.js and place that file in the /src directory. It only contains an event listener at this time, but we will add to it soon.

// src/index.js

document.getElementById('add-note-btn').addEventListener('click', () => {
const noteInput = document.getElementById('note-input');
const note = noteInput.value.trim();
if (note) {
    addNote(note);
    renderNotes();
    noteInput.value = ''; // Clear the input field
}
});

renderNotes(); // Initial render

Setting Up Git Version Control

To keep your project organized and easily track changes, it's a good idea to set up Git for version control. Create a new Git repo using the bash terminal or the GUI in VS Code.

Add a .gitignore File

To avoid tracking unnecessary files in version control, create a .gitignore file in your project's root directory and add the following. make sure the .gitignore file starts with a dot(.). This makes it a hidden file in the file system and it won't work without it!

/node_modules

This ensures that files like /node_modules are not pushed to your repository. Once files are included in a repo, they cannot be ignored. You must ignore files before committing changes.

Stage and Commit Changes

Be sure to stage changes and commit your repo at this time.

Running Webpack

Now that everything is set up, it's time to bundle your code using Webpack. When running Webpack, it will output your bundled code to the /dist directory. With everything in place, you can run Webpack using this command in the terminal.

npx webpack

After running Webpack, a /dist directory will be created in your project root directory with a bundled file named bundle.js in it.

File System

Now that you've created the necessary files and folders, let's take a moment to review the current structure of your project. Your file system should look like this.

/my-project
    /dist
        bundle.js
    /node_modules
    /src
        index.js
    .gitignore
    index.html
    package-lock.json
    package.json
    webpack.config.js

Project Management

Setup a project using Webpack.

Set Up Node.js
Install Node.js. Check for availability to your project.
Install Webpack
Initialize npm, Install Webpack, create Webpack config file.
Organize Your Project
Create your folders and files.
Create a .gitignore file to exclude unnecessary files from version control.
Run Webpack
Generate a bundled output.

Modify the app.

Update app files
Add, replace or update files in an existing project.
Update the App
Run npx webpack
Test the app
Open the app in a browser and test the functionality.
Automate App Updates
You can automatically update the app by running the webpack command when file changes are saved. To automatically update the app when you save changes to your files, run Webpack in watch mode with the following command: npx webpack --watch.

Putting It Into Action

This exercise will help you build a Webpack project, understand its structure and prepare it for production. You can build this from scratch or modify the existing app from above. This process assumes you already have a webpack project initialized with the webpack config file in place.

Organize Your Project

Create the following folder structure.

/testing-project
    /dist
        bundle.js
    /src
        index.js
        noteManager.js
    .gitignore
    index.html
    package-lock.json
    package.json
    webpack.config.js

Create working files.

Create index.html.
This page will be the landing page for the app.
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Testing Project</title>
</head>

<body>
    <h1>Note App</h1>
    <form id="note-form">
        <input type="text" id="note-input" placeholder="Enter a note">
        <button type="submit">Add Note</button>
    </form>
    <ul id="note-list"></ul>

    <script src="dist/bundle.js"></script>
</body>

</html>
Add Logic to index.js.
This index.js file handles the interaction between the form and the note list using the functions from noteManager.js.
// src/index.js

import { addNote } from './noteManager.js';

// Initialize the note list globally
let noteList = [];

document.getElementById('note-form').addEventListener('submit', function (e) {
    e.preventDefault();
    const noteInput = document.getElementById('note-input');
    const note = noteInput.value.trim();

    if (note) {
        addNote(noteList, note);
        renderNotes();
        noteInput.value = '';
    }
});

function renderNotes() {
    const noteListElement = document.getElementById('note-list');
    noteListElement.innerHTML = ''; // Clear current list

    noteList.forEach((note, index) => {
        const listItem = document.createElement('li');
        listItem.textContent = note;
        noteListElement.appendChild(listItem);
    });
}
Add Logic to noteManager.js.
We'll write a simple function in noteManager.js to handle adding notes.
// src/noteManager.js

export function addNote(noteList, note) {
    if (note && note.trim()) {
        noteList.push(note);
        return noteList;
    }
    return noteList;
}

Bundle Your Project

Run Webpack to generate the bundle. If you are running npx webpack --watch this should run automatically.

npx webpack

Deploy the App

Publish changes to GitHub pages.
Follow the instructions for publishing a GitHub repo to GitHub pages.
Test your app on GitHub.

Your project is now bundled and ready for testing!

Challenge

Now it is time to practice. Your challenge is to add a delete button to each item on the note list where clicking the button will delete the related item from the list.

In order to check your learning, you should attempt to create a solution before revealing the provided solution below.

Add Logic to index.js.
// src/index.js
                
import { addNote, deleteNote } from './noteManager.js'; // Add deleteNote to import

function renderNotes() {
    const noteListElement = document.getElementById('note-list');
    noteListElement.innerHTML = '';

    noteList.forEach((note, index) => {
        const listItem = document.createElement('li');
        listItem.textContent = note;
        listItem.appendChild(createDeleteButton(index)); // Add a delete button to the list item
        noteListElement.appendChild(listItem);
    });
}

// Add createDeleteButton() function
function createDeleteButton(index) {
    const deleteButton = document.createElement('button');
    deleteButton.textContent = 'Delete';
    deleteButton.addEventListener('click', function () { // Adds delete note event listener to the delete button
        deleteNote(noteList, index);  // Calls deleteNote function from noteManager.js
        renderNotes();
    });
    return deleteButton;
}                
Add Logic to noteManager.js.
// src/noteManager.js
                
export function deleteNote(noteList, index) {
    if (index >= 0 && index < noteList.length) {
        noteList.splice(index, 1);
        return noteList;
    }
    return noteList;
}
Bundle Your Project

Run Webpack to generate the bundle. If you are running npx webpack --watch this should run automatically.

npx webpack
Deploy the App
Publish changes to GitHub pages.
Follow the instructions for publishing a GitHub repo to GitHub pages.
Test your app on GitHub.

References