This episode explains JavaScript's production layer: the differences between the Node.js, Deno, and Bun runtimes, the role of bundlers like Vite and esbuild, and the practice of creating a project with scaffolding tools. You build and run an application through a build script.

Up to episode 20, you ran code with node and tested in the browser. In real projects, there's one more layer connecting source code to the application that actually runs: build tools and bundlers. They combine many module files into a bundle ready to serve users, with optimal speed and size.
Episode 21 dissects this layer from two sides. First, runtimes — the engines where JavaScript runs: Node.js, Deno, and Bun. Second, bundlers — the tools that unite modules: Vite, esbuild, Webpack, and Rollup. You'll also create a real project with Vite and run its build script.
This is the episode that connects many earlier topics: modules from episode 10, tooling from episode 20, and it leads up to optimization in episode 22.
A runtime is the environment that executes JavaScript outside the browser. The three main runtimes in today's ecosystem:
node --version
deno --version
bun --versionnode --version shows the Node version. The deno --version and bun --version commands only run if those runtimes are installed. For this series, Node.js is the main focus because its ecosystem is the largest and most widely used in production.
Choosing a runtime depends on your needs:
All three run the same JavaScript — ES modules, fetch, async/await — because they all support the standards. What differs is speed, security, and the surrounding ecosystem. Your code from episodes 1 through 20 runs on all three with minor adjustments.
Browsers load ES modules with import statements — but each request has a network cost. Letting the browser load hundreds of module files one by one makes a page slow. A bundler solves this: combining all modules into one (or a few) compact bundle files.
npm run buildnpm run build runs the build script that invokes the bundler. The result: readable source code is transformed into an optimized bundle — smaller files, merged dependencies, and modern features transformed for compatibility with older browsers.
Four of the most widely used bundlers, each with different strengths:
For new projects, Vite is the most frequently recommended choice because of its speed and developer experience.
Vite provides official templates for various frameworks. For pure JavaScript:
npm create vite@latest project-js -- --template vanilla
cd project-js
npm installnpm create vite@latest project-js -- --template vanilla creates an empty Vite project with the vanilla JavaScript template. npm install pulls in all dependencies. When finished, the project structure is ready to run and build.
Development mode uses a server with hot module replacement — file changes show up immediately without a manual reload:
npm run devnpm run dev starts the development server at http://localhost:5173. Features you feel right away: code changes reflect instantly, and module errors are displayed clearly on screen. This is the mode you use day to day while developing an application.
When the application is ready to release, run the production build:
npm run build
npm run previewnpm run build produces ready-to-use files in the dist directory — a minified module bundle, optimized assets, and hashed filenames for caching. npm run preview serves the built output locally so it can be inspected before deploying. This is the artifact used in production.
A package manager is part of the runtime layer that's often underappreciated. The four dominant ones:
pnpm installpnpm install installs a project's dependencies. pnpm saves disk by sharing files across projects and tightening the node_modules structure, which prevents cross-access bugs. Choosing a package manager is often decided by team convention, but everyone understands the same package.json.
Two files govern all of a project's dependencies:
The lockfile must be committed to the repository. With it, npm ci installs the exact same versions on a developer's laptop, in CI, and on production servers — no more "but it works on my machine".
Info
The standard modern project flow now feels coherent: the ES modules from episode 10 split the code, ESLint and Prettier from episode 20 keep quality high, and the bundlers from this episode combine everything into a production-ready bundle. One chain running from source code to the user.
Episode 21 closed the tooling layer: the Node.js, Deno, and Bun runtimes as execution environments, the Vite, esbuild, Webpack, and Rollup bundlers as the bridge from source code to production, and the practice of scaffolding, development, and production builds with Vite. You also understood the role of package managers and the lockfile.
Key takeaways:
npm create vite@latest creates a new project quickly.npm run dev for development, npm run build for production.dist and can be checked with npm run preview.In the next episode 22 we'll cover performance, memory, and code optimization — measuring and improving application performance, avoiding memory leaks, and applying patterns like debounce and lazy loading. This episode also closes the series with production-ready code practices and best practices.