Module 3: Professional Tooling & Workflow
Package Managers & Build Tools
Package managers (npm, pnpm, Yarn, Bun — covered in the Node.js chapter) install code. Build tools take your source code (JavaScript, JSX, CSS, etc.) and bundle/transform it into files a browser can actually run efficiently:
npm create vite@latest my-app // scaffolds a new project using Vite
npm run dev // starts a fast local dev server
npm run build // bundles everything for production
- Vite — the current standard for new projects; near-instant dev server startup using native browser ES Modules, bundles for production with Rollup underneath
- Webpack — the older, highly configurable standard, still common in established codebases
- Rollup / esbuild / SWC — lower-level bundlers/compilers, often used as the engine inside higher-level tools like Vite
- Turbopack — a newer Rust-based bundler, built by the Next.js team, aimed at replacing Webpack for large Next.js apps
ESLint & Prettier
// .eslintrc — catches likely bugs and enforces code conventions
{
"extends": "eslint:recommended",
"rules": { "no-unused-vars": "warn" }
}
// .prettierrc — automatically formats code consistently (spacing, quotes, line length)
{
"semi": true,
"singleQuote": true
}
ESLint catches problems (like a genuinely unused variable or an obviously buggy comparison); Prettier only reformats how code looks — the two are commonly run together, often automatically on save or before every commit.
Git & GitHub
git init
git add .
git commit -m "Initial commit"
git branch feature/login // create a branch for new work
git checkout feature/login
git push origin feature/login
git merge feature/login // bring changes back into main
Git is the version control tool itself, running locally. GitHub is a hosted service for storing Git repositories and collaborating — Pull Requests propose merging one branch's changes into another with review and discussion attached, and Issues track bugs and planned work.
Environments & Debugging
// .env — secrets and config kept OUT of source code
DATABASE_URL=postgres://localhost/mydb
API_KEY=abc123
// Read in Node.js
process.env.DATABASE_URL
Apps typically run in different environments — development (on your own machine, verbose errors), staging (a production-like test environment), and production (the live app real users see).
Browser DevTools (usually F12): the Console for logs/errors, the Network tab for
inspecting every request/response (essential for debugging fetch calls), and the
Sources tab for setting breakpoints — pausing code mid-execution to inspect variables live.
Node's debugger works the same way via node --inspect, connected to
Chrome DevTools or an editor like VS Code.
Testing: Unit, Integration & E2E
// Jest / Vitest — unit testing a single function in isolation
test("adds two numbers", () => {
expect(add(2, 3)).toBe(5);
});
// Testing Library — testing a React component from the user's perspective
render(<Counter />);
fireEvent.click(screen.getByText("+1"));
expect(screen.getByText("Count: 1")).toBeInTheDocument();
// Playwright / Cypress — end-to-end (E2E) testing, driving a REAL browser
test("user can log in", async ({ page }) => {
await page.goto("/login");
await page.fill("#email", "chiru@example.com");
await page.click("button[type=submit]");
await expect(page).toHaveURL("/dashboard");
});
- Unit tests — test one small function/unit in isolation (fastest, most numerous)
- Integration tests — test several pieces working together (e.g. a component plus its state logic)
- E2E tests — test a full real user flow through the actual running app (slowest, fewest, but catch the most realistic bugs)