Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Deployment and Build Optimization in React

Deployment and Build Optimization

~15 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

So far our project has only run via npm run dev – Vite's development server with hot reload, but NOT meant for real users. This chapter covers the final step: creating an optimized production build and understanding what happens along the way.

Running npm run build

npm run build

This produces a dist/ folder with static HTML, CSS, and JavaScript files – NO Node.js server needed to serve them (our own reviews server/ from "React for Beginners" chapters 25/26 is a separate, STANDALONE Node application and stays unaffected by this, needs to be deployed SEPARATELY).

What esbuild/Rollup does under the hood

  • Minification: variable names get shortened, whitespace/comments removed – smaller file size, unreadable to humans, functionally identical to the browser.
  • Tree shaking: UNUSED code (e.g. functions from react-window we never imported) gets removed entirely from the final bundle.
  • Code splitting: Remember lazy() from "React for Beginners" chapter 20? EVERY lazy()-imported page (ReviewsPage, LoginPage, AccountPage, CartPage) becomes its OWN, separately loadable file – users only download the code for the route they actually visit.
  • Asset hashing: filenames get a content hash (index-a3f8b2.js instead of index.js) – if the content changes, the hash changes, allowing browser caching to be used safely and aggressively (the old version stays valid in the cache as long as the filename/hash doesn't change).

Analyzing the build: what's actually in there?

npm run build shows an overview of the generated files with their sizes at the end. For a DEEPER analysis (which PACKAGE contributes how much), there's the rollup-plugin-visualizer plugin:

npm install --save-dev rollup-plugin-visualizer
// In vite.config.js:
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [react(), visualizer({ open: true })],
  // ... rest of the configuration
});

After npm run build, an interactive graphic (a "treemap") opens automatically – bigger boxes are bigger packages in the bundle. A common finding in real projects: ONE accidentally imported, huge library (e.g. all of lodash instead of a single function from it) dominates the entire graphic.

Environment variables for different environments

Our src/api/reviewsApi.js and server/db.js have fixed URLs/credentials hardcoded (http://localhost:4000, secretpassword) – convenient for local development in this tutorial, but NOT suitable for a real production build. Vite supports .env files natively:

.env.production
VITE_API_BASE_URL=https://api.my-product-catalog.com
// In src/api/reviewsApi.js, instead of the hardcoded URL:
const BASE_URL = import.meta.env.VITE_API_BASE_URL;

Achtung: ONLY variables prefixed with VITE_ get embedded into the client code by Vite – that's DELIBERATE, to prevent server secrets (database passwords, API keys) from ACCIDENTALLY ending up in the publicly served JavaScript bundle. The secretpassword in server/db.js should NEVER go into a VITE_ variable – server/ runs as a standalone Node process and needs NO Vite environment variable system, plain process.env variables on the server are enough.

Where to host the dist folder?

The dist/ folder is pure static HTML/CSS/JS – hostable on ANY static hosting service (Netlify, Vercel, Cloudflare Pages, GitHub Pages, a plain Nginx web server). The reviews server/, on the other hand, needs REAL Node.js hosting (Railway, Render, your own VPS) – two DIFFERENT deployment targets for the two parts of our project.

Tipp: Rule of thumb for build size: medium-sized React projects often land at 150-300 KB (gzipped) for the initial JavaScript bundle. Noticeably larger? The visualizer from this chapter is the first step toward diagnosing why – often it's unused dependencies or missing code splitting (see lazy()), not "React itself is too big".