๐ก Hands-On Practice
Bundler configurations require a local development environment. To practice:
npm init -ynpm create vite@latest for the easiest startMaster the tools that power modern JavaScript development. Learn bundling, code splitting, tree shaking, HMR, and production optimization across Webpack, Vite, and Parcel.
Modern apps use ES modules, TypeScript, JSX, SCSS, and hundreds of dependencies. Browsers can't handle all of this natively. Bundlers transform your development code into optimized, browser-ready production builds.
Webpack is the most flexible bundler with a massive plugin ecosystem. It requires configuration but gives you complete control over every aspect of your build.
Explore basic Webpack configuration patterns
// webpack.config.js - Basic Webpack Configuration
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// Entry point - where bundler starts
entry: "./src/index.js",
// Output configuration
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true // Clean /dist folder before each build
},
// Development or prod
...๐ก Key Concepts: Entry points define where bundling starts. Loaders transform files (babel-loader, css-loader). Plugins extend functionality (HtmlWebpackPlugin, MiniCssExtractPlugin).
Production builds require aggressive optimization: minification, code splitting, tree shaking, and vendor chunking for optimal caching.
Advanced production optimization patterns
// webpack.config.js - Production Optimization
const TerserPlugin = require("terser-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
module.exports = {
mode: "production",
// Multiple entry points for large apps
entry: {
main: "./src/main.js",
admin: "./src/admin.js",
analytics: "./src/analytics.js"
},
output: {
filename: "[name].[contenthash].js",
path: __
...Vite uses native ES modules during development for instant server start and updates. It's the fastest development experience available and the modern default choice.
Modern Vite bundler configuration
// vite.config.js - Vite Configuration
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { resolve } from "path";
export default defineConfig({
// Plugins
plugins: [react()],
// Path aliases
resolve: {
alias: {
"@": resolve(__dirname, "src"),
"@components": resolve(__dirname, "src/components"),
"@utils": resolve(__dirname, "src/utils")
}
},
// Development server
server: {
port: 3000,
open: true,
// Proxy A
...โ Why Vite is Fast: During development, Vite serves raw ES modules to the browser โ no bundling required! For production, it uses Rollup with ESBuild for lightning-fast builds.
Vite plugins follow Rollup's plugin interface with additional Vite-specific hooks. You can transform code, inject scripts, and customize the build process.
Custom Vite plugin development
// Writing a Custom Vite Plugin
function myVitePlugin() {
return {
name: "my-vite-plugin",
// Runs during config resolution
config(config, { command }) {
console.log("Building for:", command);
},
// Transform source code
transform(code, id) {
// Convert .txt files to JS modules
if (id.endsWith(".txt")) {
return {
code: `export default ${JSON.stringify(code)}`,
map: null
};
}
},
// Modify the HTML
...Code splitting creates separate chunks that load on demand, dramatically improving initial load times. Use dynamic imports to load routes, features, and heavy libraries only when needed.
Dynamic imports and lazy loading patterns
// Code Splitting with Dynamic Imports
// 1. Route-based code splitting
const routes = [
{
path: "/",
// Lazy load the home page
component: () => import("./pages/Home.js")
},
{
path: "/dashboard",
// Lazy load dashboard (admin only)
component: () => import("./pages/Dashboard.js")
},
{
path: "/settings",
component: () => import("./pages/Settings.js")
}
];
// 2. Feature-based code splitting
async function loadChartLibrary() {
// Only load heavy libra
...Tree shaking eliminates unused code from your final bundle. It works best with ES modules and side-effect-free code.
Dead code elimination techniques
// Tree Shaking - Dead Code Elimination
// โ BAD: Imports entire library (no tree shaking)
import _ from "lodash";
const result = _.map([1, 2, 3], x => x * 2);
// โ
GOOD: Import only what you need (tree shakeable)
import { map } from "lodash-es";
const result = map([1, 2, 3], x => x * 2);
// โ BAD: Side effects prevent tree shaking
export function usefulFunction() {
return "I am useful";
}
export function unusedFunction() {
return "I am never used";
}
// Side effect - runs when module
...HMR updates modules in the browser without a full page refresh, preserving application state. Vite provides instant HMR out of the box.
HMR implementation patterns
// Hot Module Replacement (HMR)
// How HMR works internally:
// 1. You edit a file
// 2. Bundler compiles JUST that file
// 3. Sends update via WebSocket
// 4. Browser replaces the module
// 5. State is preserved (no page refresh!)
// Vite - HMR is automatic for most files
// For custom HMR handling:
if (import.meta.hot) {
// Accept updates for this module
import.meta.hot.accept((newModule) => {
console.log("Module updated!", newModule);
});
// Clean up before module is replaced
...Bundlers inject environment-specific variables at build time, allowing different configurations for development, staging, and production.
Managing environment-specific configurations
// Environment Variables in Bundlers
// Vite - Uses import.meta.env
// .env file:
// VITE_API_URL=https://api.example.com
// VITE_DEBUG=true
// Access in code:
console.log(import.meta.env.VITE_API_URL);
console.log(import.meta.env.VITE_DEBUG);
console.log(import.meta.env.MODE); // "development" or "production"
console.log(import.meta.env.DEV); // true in dev
console.log(import.meta.env.PROD); // true in production
// Webpack - Uses DefinePlugin
// webpack.config.js
const webpack = require("
...Webpack Module Federation allows separate applications to share code at runtime โ the foundation of microfrontend architecture used by Amazon, Netflix, and Shopify.
Microfrontend architecture patterns
// Webpack Module Federation (Microfrontends)
// Host Application - webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "host",
// Import modules from remote apps
remotes: {
// "internal name": "remote_name@URL"
headerApp: "header@http://localhost:3001/remoteEntry.js",
productApp: "products@http://localhost:3002/remoteEntr
...SSR requires bundling both client and server code. Vite has built-in SSR support with separate entry points for server rendering and client hydration.
SSR build configuration patterns
// Server-Side Rendering (SSR) Build Configuration
// Vite SSR - vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
build: {
// SSR entry point
ssr: true,
rollupOptions: {
input: "./src/entry-server.js"
}
},
ssr: {
// Don't bundle these (use Node.js require)
noExternal: ["some-package-to-bundle"]
}
});
// entry-server.js - Server entry point
import { renderToString } from "react-dom/server";
import App from "./App";
expo
...Parcel automatically detects and handles all file types without configuration. Perfect for prototypes, learning, and simple projects.
Zero-configuration bundler setup
// Parcel - Zero Configuration Bundler
// No config file needed! Just run:
// npx parcel index.html
// Parcel automatically detects and handles:
// - JavaScript/TypeScript
// - JSX/TSX
// - CSS/SCSS/LESS
// - Images and fonts
// - HTML
// Optional .parcelrc for customization
{
"extends": "@parcel/config-default",
"transformers": {
"*.svg": ["@parcel/transformer-svg-react"]
},
"optimizers": {
"*.js": ["@parcel/optimizer-terser"]
}
}
// package.json scripts
{
"scripts": {
...Each bundler excels in different scenarios. Choose based on your project's needs, team experience, and long-term requirements.
Comparing Webpack, Vite, and Parcel
// Bundler Feature Comparison
/*
โโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ Feature โ Webpack โ Vite โ Parcel โ
โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ Configuration โ Complex โ Minimal โ Zero-config โ
โ Dev Server โ Slow โ FASTEST โ Fast โ
โ Build Speed โ Slow โ Fast โ Fast โ
โ HMR โ Config req. โ Instant โ Built-in โ
โ Code Spli
...Sign up for free to track which lessons you've completed and get learning reminders.