Webpack
Learning Objectives
- By the end of this lesson, you will be able to:
- - Understand webpack basics
- - Configure webpack
- - Use loaders for different file types
- - Use plugins for additional functionality
- - Implement code splitting
- - Optimize builds
- - Bundle JavaScript applications
Lesson 23.2: Webpack
Learning Objectives
By the end of this lesson, you will be able to:
- Understand webpack basics
- Configure webpack
- Use loaders for different file types
- Use plugins for additional functionality
- Implement code splitting
- Optimize builds
- Bundle JavaScript applications
Introduction to Webpack
Webpack is a module bundler that processes and bundles JavaScript modules and assets.
Why Webpack?
- Bundling: Combines multiple files into bundles
- Transformation: Transpiles and transforms code
- Optimization: Optimizes for production
- Code Splitting: Splits code into chunks
- Asset Management: Handles images, CSS, etc.
- Industry Standard: Widely used in production
Webpack Basics
Installation
# Install webpack
npm install --save-dev webpack webpack-cli
# Or with yarn
yarn add --dev webpack webpack-cli
Basic Setup
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Entry and Output
// Single entry
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
// Multiple entry points
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Configuration
Basic Configuration
// webpack.config.js
const path = require('path');
module.exports = {
mode: 'development', // or 'production'
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true // Clean output directory
},
devtool: 'source-map', // Source maps
target: 'web' // or 'node'
};
Development vs Production
// Development
module.exports = {
mode: 'development',
devtool: 'eval-source-map',
optimization: {
minimize: false
}
};
// Production
module.exports = {
mode: 'production',
devtool: 'source-map',
optimization: {
minimize: true
}
};
Loaders
What are Loaders?
Loaders transform files before bundling.
Common Loaders
// babel-loader: Transpile ES6+
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
};
CSS Loaders
// css-loader and style-loader
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
File Loaders
// file-loader: Handle images, fonts, etc.
module.exports = {
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource'
}
]
}
};
Multiple Loaders
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader', // Injects CSS into DOM
'css-loader', // Resolves CSS imports
'sass-loader' // Compiles Sass to CSS
]
}
]
}
};
Plugins
What are Plugins?
Plugins extend webpack functionality.
Common Plugins
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
})
]
};
HTML Webpack Plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
inject: 'body',
minify: {
removeComments: true,
collapseWhitespace: true
}
})
]
};
Mini CSS Extract Plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles.css'
})
]
};
Code Splitting
Entry Points
// Split by entry points
module.exports = {
entry: {
app: './src/app.js',
vendor: './src/vendor.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
SplitChunks
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
Dynamic Imports
// In your code
async function loadModule() {
let module = await import('./module.js');
module.doSomething();
}
// Webpack automatically splits this
Development Server
Webpack Dev Server
# Install
npm install --save-dev webpack-dev-server
// webpack.config.js
module.exports = {
devServer: {
static: './dist',
port: 3000,
hot: true,
open: true
}
};
// package.json
{
"scripts": {
"dev": "webpack serve --mode development",
"build": "webpack --mode production"
}
}
Practice Exercise
Exercise: Webpack Setup
Objective: Practice setting up webpack, configuring loaders and plugins, and implementing code splitting.
Instructions:
- Install webpack
- Create webpack configuration
- Set up loaders and plugins
- Practice:
- Basic webpack setup
- Using loaders
- Using plugins
- Code splitting
Example Solution:
# 1. Initialize project
npm init -y
# 2. Install webpack
npm install --save-dev webpack webpack-cli
# 3. Install loaders
npm install --save-dev babel-loader @babel/core @babel/preset-env
npm install --save-dev css-loader style-loader
npm install --save-dev file-loader
# 4. Install plugins
npm install --save-dev html-webpack-plugin clean-webpack-plugin
npm install --save-dev webpack-dev-server
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
devtool: 'source-map',
devServer: {
static: './dist',
port: 3000,
hot: true,
open: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
})
],
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
// src/index.js
import './styles.css';
import { add, multiply } from './math';
console.log('Webpack is working!');
console.log('add(2, 3) =', add(2, 3));
console.log('multiply(4, 5) =', multiply(4, 5));
// Dynamic import example
async function loadModule() {
let module = await import('./lazy-module.js');
module.default();
}
// Load on button click
document.getElementById('load-btn').addEventListener('click', loadModule);
// src/math.js
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// src/lazy-module.js
export default function() {
console.log('Lazy module loaded!');
}
/* src/styles.css */
body {
font-family: Arial, sans-serif;
margin: 20px;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
<!-- src/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webpack Practice</title>
</head>
<body>
<h1>Webpack Practice</h1>
<button id="load-btn">Load Lazy Module</button>
<div id="output"></div>
</body>
</html>
// package.json
{
"name": "webpack-practice",
"version": "1.0.0",
"scripts": {
"dev": "webpack serve --mode development",
"build": "webpack --mode production",
"build:dev": "webpack --mode development"
},
"devDependencies": {
"@babel/core": "^7.22.0",
"@babel/preset-env": "^7.22.0",
"babel-loader": "^9.1.0",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.8.0",
"html-webpack-plugin": "^5.5.0",
"style-loader": "^3.3.0",
"webpack": "^5.88.0",
"webpack-cli": "^5.1.0",
"webpack-dev-server": "^4.15.0"
}
}
Expected Output (when running npm run dev):
webpack compiled successfully
Server running on http://localhost:3000
Challenge (Optional):
- Set up a complete webpack project
- Add more loaders (Sass, TypeScript)
- Optimize for production
- Implement advanced code splitting
Common Mistakes
1. Wrong Loader Order
// ❌ Bad: Wrong order
{
test: /\.scss$/,
use: ['sass-loader', 'css-loader', 'style-loader']
}
// ✅ Good: Right order (processes right to left)
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
2. Not Excluding node_modules
// ❌ Bad: Process node_modules
{
test: /\.js$/,
use: 'babel-loader'
}
// ✅ Good: Exclude node_modules
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
3. Missing Output Path
// ❌ Bad: Relative path might not work
output: {
filename: 'bundle.js',
path: 'dist'
}
// ✅ Good: Absolute path
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
Key Takeaways
- Webpack: Module bundler for JavaScript
- Entry: Entry point(s) for bundling
- Output: Where bundles are written
- Loaders: Transform files before bundling
- Plugins: Extend webpack functionality
- Code Splitting: Split code into chunks
- Best Practice: Use appropriate loaders, optimize for production
Quiz: Webpack
Test your understanding with these questions:
-
Webpack is:
- A) Module bundler
- B) Package manager
- C) Both
- D) Neither
-
Loaders:
- A) Transform files
- B) Extend functionality
- C) Both
- D) Neither
-
Plugins:
- A) Transform files
- B) Extend functionality
- C) Both
- D) Neither
-
entry specifies:
- A) Output location
- B) Entry point
- C) Both
- D) Neither
-
Loaders process:
- A) Left to right
- B) Right to left
- C) Random
- D) Never
-
Code splitting:
- A) Splits code into chunks
- B) Combines code
- C) Both
- D) Neither
-
webpack-dev-server:
- A) Development server
- B) Production server
- C) Both
- D) Neither
Answers:
- A) Module bundler
- A) Transform files
- B) Extend functionality
- B) Entry point
- B) Right to left
- A) Splits code into chunks
- A) Development server
Next Steps
Congratulations! You've learned webpack. You now know:
- How to configure webpack
- How to use loaders
- How to use plugins
- How to implement code splitting
What's Next?
- Lesson 23.3: Modern Build Tools
- Learn Vite
- Understand Parcel
- Work with esbuild
Additional Resources
- Webpack Documentation: webpack.js.org
- Webpack Concepts: webpack.js.org/concepts
- Webpack Loaders: webpack.js.org/loaders
Lesson completed! You're ready to move on to the next lesson.
Course Navigation
Build Tools and Bundlers
Build Tools and Bundlers