Installing Webpack & Bundling JS Files
Install Webpack and its CLI, then create your first bundle — combining multiple JavaScript modules into a single output file.
Installing Webpack & Bundling JS Files
Now that the project is set up, it is time to install Webpack and create your first bundle. In this episode you will install Webpack, run it from the command line, and see how it resolves import/export statements to produce a single output file.
Step 1: Install Webpack
npm install webpack webpack-cli --save-dev
| Package | Purpose |
|---|---|
webpack | The core bundler engine |
webpack-cli | Command-line interface — lets you run webpack in the terminal |
Both are installed as devDependencies because they are build tools only needed during development.
Step 2: Add an npm Script
Open package.json and add a build script:
{
"scripts": {
"build": "webpack"
}
}
Running npm run build will execute the locally installed Webpack. You can also run it directly with npx webpack, but npm scripts are the standard approach.
Step 3: Run Webpack
npm run build
Without any configuration file, Webpack uses sensible defaults:
| Default | Value |
|---|---|
| Entry point | ./src/index.js |
| Output file | ./dist/main.js |
| Mode | production (minified output) |
Webpack reads src/index.js, discovers that it imports from utils.js and dom.js, and bundles everything into dist/main.js.
Understanding the Output
npm run build
asset main.js 1.2 KiB [emitted] [minimized] (name: main)
./src/index.js 189 bytes [built] [code generated]
./src/utils.js 167 bytes [built] [code generated]
./src/dom.js 198 bytes [built] [code generated]
webpack compiled successfully
The output tells you:
- One asset was created:
main.jsat 1.2 KiB - Three modules were processed:
index.js,utils.js, anddom.js - The output is minimized (production mode default)
Updating index.html
Since the default output is main.js (not bundle.js), update the script tag in dist/index.html:
<script src="main.js"></script>
Open dist/index.html in a browser and you should see "Hello, Webpack!" rendered on the page.
Development vs Production Mode
# Production mode (minified, optimized) — default
npx webpack --mode production
# Development mode (readable, with comments)
npx webpack --mode development
| Mode | Output | Source Maps | Optimizations |
|---|---|---|---|
production | Minified, mangled | None by default | Tree shaking, dead code removal |
development | Readable, with comments | eval source maps | Faster rebuilds, no minification |
How Webpack Resolves Modules
// In src/index.js:
import { greet, VERSION } from './utils';
// Webpack resolves this to:
// 1. Look for ./utils.js in the same directory
// 2. If not found, look for ./utils/index.js
// 3. If not found, look in node_modules/utils
Webpack follows a resolution algorithm similar to Node.js. It checks file extensions (.js, .json), index files, and node_modules automatically. You do not need to write ./utils.js — just ./utils is enough.
Tree Shaking
In production mode, Webpack performs tree shaking — it removes unused exports from the bundle.
// src/utils.js exports: greet, capitalize, VERSION
// src/index.js imports: greet, VERSION
// capitalize is NOT imported
// In production mode, Webpack removes capitalize from the bundle
// because it is never used — this reduces bundle size
Tree shaking works with ES module syntax (import/export) but not CommonJS (require/module.exports). This is one reason why ES modules are preferred.
Watching for Changes
npx webpack --watch
The --watch flag tells Webpack to monitor your source files and automatically rebuild when any file changes. This saves you from manually running the build command after every edit.
{
"scripts": {
"build": "webpack",
"watch": "webpack --watch"
}
}
What Happens Inside the Bundle
If you build in development mode and open the output file, you will see that Webpack wraps each module in a function and creates a module registry. Each import is replaced with a call to Webpack's internal __webpack_require__ function:
// Simplified view of what Webpack generates:
var modules = {
"./src/utils.js": function(module, exports) {
// utils.js code here
},
"./src/dom.js": function(module, exports) {
// dom.js code here
},
"./src/index.js": function(module, exports, require) {
var utils = require("./src/utils.js");
var dom = require("./src/dom.js");
// index.js code here
}
};
// Start execution from the entry point
modules["./src/index.js"]();
In production mode, all of this is minified and optimized — but the concept is the same.
Key Takeaways
- Install
webpackandwebpack-clias dev dependencies - Without a config file, Webpack defaults to
./src/index.jsas entry and./dist/main.jsas output - Production mode minifies and tree-shakes; development mode produces readable output
- Webpack follows
importstatements to discover and bundle all dependencies automatically - Tree shaking removes unused exports — only code that is actually imported ends up in the bundle
- Use
--watchto automatically rebuild on file changes