Behind the Scenes: Webpack and Vite

Like every React beginner, I started with this:

npx create-react-app my-app

Quick confession: I thought NPX was some "express" version of NPM because of the 'X'. Turns out it actually stands for eXecute! NPM installs packages, whereas NPX just executes Node.js packages directly without requiring them to be permanently installed in your project or globally. It’s great for one-time use, and it also downloads the latest version so you don’t have to worry about updating your packages.

The Hidden Tool Behind CRA

YouTube tutorials made it look so simple. One command, boom - React app ready! I was just happy it worked and didn't question anything. Then something caught my eye. When I ran npm start on my CRA app, I noticed this in the terminal:

I thought, “Wait… what’s Webpack?” Turns out, CRA was using this powerful build tool behind the scenes all along!

Why Bother With Build Tools Anyway?

Modern JavaScript often uses features or syntax (like JSX in React) that browsers don’t understand directly. That’s why we need build tools, which typically combine two main roles:

  1. Compiler/Transpiler (e.g., Babel): Converts JSX or modern JS into browser-friendly JavaScript. For example:
const App = () => <h1>Hello, World!</h1>;

becomes

const App = React.createElement('h1', null, 'Hello, World!');
  1. Bundler (e.g., Webpack, Vite, RsBuild, Rollup, Parcel): Resolves all your module dependencies and packs them into files the browser can load efficiently.

Every bundler follows two stages: dependency resolution and packing. The first stage is largely the same across tools — what really differentiates them is how they handle the second stage, the packing.

Webpack: Manual Setup Walkthrough

I was curious about the pain point that led to CRA being created. So I tried setting up Webpack myself.

Here's what I had to do manually :

  1. Initialize Project
    npm init -y → creates package.json.

  2. Install React
    npm install react react-dom → actual React library + DOM renderer.

  3. Install Webpack & Dev Server
    npm install --save-dev webpack webpack-cli webpack-dev-server → handles bundling, running a local server, and commands.

  4. Set up Babel + Loaders

    • npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react → compiles JSX and modern JS.

    • Loaders:

      • babel-loader → JSX/ES6 → browser code

      • css-loader → lets you import CSS

      • file-loader → handles images/assets

  5. HTML Plugin
    npm install --save-dev html-webpack-plugin → auto-generates index.html with your bundle included.

  6. Project Setup

    • Create folder structure (src/, public/, etc.)

    • Add webpack.config.js (custom config, else defaults)

    • Add .babelrc (tells Babel which presets to use)

    • Create HTML template + React components

  7. Scripts
    Update package.json with:

     "scripts": { "start": "webpack serve --open", "build": "webpack" }
    

Then you finally smile when you see:

webpack 5.101.3 complied successfully in 395 ms

Don’t worry if this list looks scary — CRA automates all of this for you. All you have to do is this :

npx create-react-app my-app
cd my-app
npm start

Then Vite Showed Up

Vite (pronounced veet) literally means “fast” in French. It’s a modern JavaScript build tool — lightweight, quick to spin up, and built for modern browsers. Plus, it works seamlessly with React, Vue, Svelte, and more.

npx create vite@latest my-app
cd my-app
npm install
npm run dev

That’s it. Just a couple of commands and you’ve got a project template ready to go — no fiddling with loaders or heavy configs.

Because, let’s face it — we developers are never satisfied. Always hunting for something faster, cleaner, and better.

What’s Really Happening Under the Hood?

How Webpack Does Its Magic

Webpack was built in a time when browsers couldn’t natively understand ESM. Its job is to take your modular code and turn it into something every browser can run:

  1. Finds the entry point – usually your src/index.js file.

  2. Module resolution – follows every import statement to figure out all connected files (fancy term for “discovering your dependency graph”).

  3. Converts everything – uses loaders to turn CSS, images, or TypeScript into JavaScript.

  4. Bundles it all – smooshes everything into one big bundle.js file in your /dist folder during the build process.

  5. Serves the bundle – your browser just downloads this single file.

This works well, but it can feel heavy during development — every change requires Webpack to rebuild or re-bundle a big chunk of your app.

Vite’s Smarter Approach

Vite was designed to leverage the fact that modern browsers already understand ES modules. Instead of bundling everything upfront, it does the opposite:

  • Starts instantly – the dev server boots up immediately without pre-bundling.

  • Browser requests files – when you open the page, your browser says: “I need App.js.”

  • On-demand processing – only then does Vite transform that specific file (e.g., from JSX to JS) and send it back.

  • Individual files – the browser loads separate ESM files directly, not one giant bundle.

But what about production?
In production, Vite does bundle your code (using Rollup under the hood). This ensures your final app is optimized with techniques like minification, tree-shaking, and code-splitting. So you get the best of both worlds: blazing-fast dev server + production-ready optimized build.

Fun fact: Create React App (CRA) runs on port 3000 by default, while Vite uses 5173.
📌 At the time of writing, the latest versions are Webpack 5 and Vite 7.

Should You Switch?

Honestly, both tools are solid choices.

  • If you’re a beginner: Go with Vite — it’s simpler, faster, and feels modern.

  • If you’re in a company setting: You’ll likely still come across Webpack, so having at least a basic understanding of it will definitely help.

I’m currently exploring Rsbuild, as I’ve heard it’s much faster than Vite. Built with Rust, it promises consistent speed for both development and production builds, making it especially appealing for large-scale projects or when migrating from Webpack. Excited to see how it performs in practice!

The key is — don’t get stuck overthinking which one is “better”. Try both. Pick the one that fits your project needs and workflow, but also think about what will make deployment smoother.

Next time you run either command, you’ll know there’s an entire world of complexity hidden behind that one line of simplicity. And as developers, it’s always good to peek under the hood — don’t you think?

See you in my next learning adventure!

3
Subscribe to my newsletter

Read articles from Sharanya Ramchandra directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sharanya Ramchandra
Sharanya Ramchandra