← JS Mastery | Module 10: Advanced Patterns Bundling with Vite & Webpack
Module 10

Bundling with Vite & Webpack

⏱ 22 min read ● Advanced 🆓 Free

Why Bundle?

Browsers can load ES modules directly, but bundlers optimize your code for production: combine files, minify code, tree-shake unused code, transpile modern JS for older browsers, and handle non-JS assets like CSS and images.

Vite — The Modern Choice

// npm create vite@latest my-app -- --template vanilla
// npm install
// npm run dev      → dev server with HMR
// npm run build    → production build

// vite.config.js:
import { defineConfig } from "vite";
export default defineConfig({
  build: {
    outDir: "dist",
    minify: true,
    rollupOptions: {
      input: "index.html"
    }
  },
  server: {
    port: 5173,
    proxy: {
      "/api": "http://localhost:3000"  // dev proxy
    }
  }
});

// Vite features:
// - Dev server with instant HMR (no rebuild)
// - ESM-first
// - TypeScript out of the box
// - CSS Modules, PostCSS
// - Dynamic imports + code splitting
// - Fast builds via Rollup

Webpack — The Veteran

// npm install -D webpack webpack-cli
// webpack.config.js:
const path = require("path");
module.exports = {
  mode: "production",
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.[contenthash].js"  // cache busting
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "babel-loader",    // transpile modern JS
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  optimization: {
    splitChunks: { chunks: "all" }  // code splitting
  }
};

// Tree shaking — automatically removes unused code:
// If you import { add } from "./math.js" and never use subtract,
// webpack/rollup removes subtract from the bundle entirely

Code Splitting

// Dynamic imports create separate chunks:
async function loadAnalytics() {
  const { default: Analytics } = await import("./analytics.js");
  Analytics.init();
}

// Route-based splitting (common in SPAs):
const HomePage = () => import("./pages/Home.js");
const AboutPage = () => import("./pages/About.js");

// Only loads code when needed — faster initial load!

// Preload critical chunks:
const link = document.createElement("link");
link.rel = "modulepreload";
link.href = "/assets/critical-chunk.js";
document.head.appendChild(link);

⚡ Key Takeaways

🎯 Practice Exercises

EXERCISE 1

Set up a Vite project with TypeScript. Add a route-based code splitting: lazily load a "Dashboard" module only when the user navigates to /dashboard.

← Testing