๐ 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
srcfolder, uses adistfolder for output, and relies heavily on anode_modulesdirectory 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_modulesshould be excluded from Git using a.gitignorefile 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.
- The browser first loads
index.html. index.htmlincludes a single<script>tag that loads the bundled JavaScript file generated by Webpack.- The bundled file(created from
index.jsand 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
.gitignorefile 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.jsfile handles the interaction between the form and the note list using the functions fromnoteManager.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.jsto 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.