Loading...
Loading...
The toolchain that transforms your source code into production-ready bundles.
Module 12 · Path to Frameworks
Frameworks like React and Next.js build on JavaScript fundamentals. Node.js runs JavaScript on servers, npm manages packages, and build tools prepare code for production. This module bridges vanilla JS to the modern ecosystem.
Learn Build Tools in JavaScript — covering Why Build, Bundlers, Transpilers, Linters & Formatters with interactive visual examples and step-by-step explanations.
Vanilla JavaScript teaches you how the language works. Frameworks like React teach you how teams ship user interfaces at scale. This module bridges the gap — showing how the fundamentals you have learned map directly to React components, Node.js servers, and npm workflows.
You do not need to pick a framework on day one, but understanding how JavaScript powers React, Next.js, and Node.js makes every future tutorial easier to follow.
Understanding build tools is essential for every JavaScript developer. It shows up in frontend UI code, backend APIs, and framework internals — and getting it wrong leads to bugs that are hard to trace. This chapter builds intuition with visuals so the behavior sticks.
Browsers can't run your source code directly. Build tools bridge the gap.
// Your source code uses things browsers don't understand: // - TypeScript (.ts, .tsx) // - JSX (<Component />) // - CSS Modules, Tailwind // - Import from node_modules // - Environment variables // - Modern syntax older browsers don't support // The build pipeline transforms source → browser-ready code: // // Source files Build process Output // ───────────── ───────────── ────────── // .tsx, .ts → TypeScript compiler → .js // JSX → Babel/SWC transform → createElement calls // 100+ modules → Bundler → few optimized files // Modern JS → Transpiler → compatible JS // Tailwind CSS → PostCSS → optimized CSS // Images/fonts → Asset pipeline → optimized assets // The build toolchain: // Bundler → Vite, Webpack, Rollup, esbuild // Transpiler → SWC, Babel, TypeScript compiler // Linter → ESLint, Biome // Formatter → Prettier, Biome // Type checker → TypeScript (tsc) // Test runner → Vitest, Jest // Dev server → Vite, webpack-dev-server
Combine many files into few optimized bundles.
// Vite — the modern standard: // Instant dev server (no bundling during dev!) // Uses Rollup for production builds // Blazing fast with native ES modules // Create a Vite project: // $ pnpm create vite my-app --template react-ts // vite.config.ts: import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], build: { outDir: "dist", sourcemap: true, }, server: { port: 3000, }, }); // Commands: // pnpm dev → start dev server (instant) // pnpm build → production bundle // pnpm preview → preview production build locally
Vite is the recommended bundler for new projects. It's fast because it uses native ES modules in development — no bundling needed.
Transform modern/extended syntax into standard JavaScript.
// TypeScript → JavaScript: // Input (app.tsx): interface User { name: string; age: number; } const greet = (user: User): string => { return "Hello, " + user.name; }; // Output (app.js) — types are removed: const greet = (user) => { return "Hello, " + user.name; }; // JSX → JavaScript: // Input: const App = () => <div className="app"><h1>Hello</h1></div>; // Output: const App = () => createElement("div", { className: "app" }, createElement("h1", null, "Hello") ); // Modern syntax → older browsers: // Input (modern): const items = data?.items ?? []; const doubled = items.map(x => x * 2); // Output (for older browsers): var _data; var items = ((_data = data) === null ? void 0 : _data.items) || []; var doubled = items.map(function(x) { return x * 2; }); // Transpiler options: // SWC — Rust-based, extremely fast (used by Next.js, Vite) // Babel — JavaScript-based, most plugins, slower // esbuild — Go-based, fast, used by Vite for dev // tsc — TypeScript compiler (type-checking + transpiling) // Most projects: SWC for speed, tsc for type-checking only // tsconfig.json controls what TypeScript allows/targets
Catch bugs and enforce consistent code style automatically.
// ESLint — catches bugs and enforces rules: // eslint.config.js (flat config): import js from "@eslint/js"; import tseslint from "typescript-eslint"; export default [ js.configs.recommended, ...tseslint.configs.recommended, { rules: { "no-unused-vars": "warn", "no-console": "warn", "@typescript-eslint/no-explicit-any": "error", }, }, ]; // Run: pnpm eslint . // Auto-fix: pnpm eslint . --fix // Prettier — formats code consistently: // .prettierrc: { "semi": true, "singleQuote": false, "tabWidth": 2, "trailingComma": "all", "printWidth": 80 } // Run: pnpm prettier --write . // Biome — all-in-one (lint + format, fast): // Single tool replacing ESLint + Prettier // Written in Rust, 10-100x faster // Typical setup (scripts in package.json): "scripts": { "lint": "eslint .", "lint:fix": "eslint . --fix", "format": "prettier --write .", "check": "tsc --noEmit && eslint . && prettier --check ." } // Pre-commit hooks (lint-staged + husky): // Run linting only on staged files before each commit // Prevents bad code from entering the repo // .husky/pre-commit: pnpm lint-staged // lint-staged config: "*.{ts,tsx}": ["eslint --fix", "prettier --write"]
Hot Module Replacement — see changes instantly without refreshing.
// Vite dev server features: // 1. Instant startup (no bundling — serves ES modules directly) // 2. Hot Module Replacement (HMR) — updates without page reload // 3. Source maps — debug original TypeScript in browser // 4. Proxy API requests to avoid CORS // 5. HTTPS support for local development // How HMR works: // 1. You edit a file and save // 2. Vite detects the change (file watcher) // 3. Only the changed module is re-compiled // 4. Update is sent via WebSocket to browser // 5. Browser applies change WITHOUT full reload // 6. React state is preserved! // vite.config.ts — dev server options: export default defineConfig({ server: { port: 3000, open: true, // auto-open browser proxy: { "/api": { target: "http://localhost:8080", changeOrigin: true, }, }, }, }); // Environment variables: // .env: VITE_API_URL=https://api.example.com VITE_APP_TITLE=My App // Access in code (only VITE_ prefixed): const apiUrl = import.meta.env.VITE_API_URL; // .env.development — dev only // .env.production — production build only // .env.local — local overrides (gitignored) // Full dev workflow: // $ pnpm dev → starts dev server with HMR // Edit code → see changes instantly in browser // $ pnpm build → creates production bundle // $ pnpm preview → test production build locally
Common questions about build tools.