All articles

Setting Up an Angular Development Environment

Node, the Angular CLI, strict mode and your first workspace — a clean Angular 22 setup, with the exact version minimums that bite.

0 · log in to like, save & follow Share on LinkedIn Share on X

Every Angular problem is easier with a healthy toolchain, and half of beginners' "Angular is broken" moments are really environment problems. This guide sets up a clean Angular 22 development environment — Node via a version manager, the Angular CLI, a first workspace, strict mode, and the VS Code setup that matters — with the version pitfalls called out before you hit them. Every command output below is real, captured from the companion repository while writing this.

Setting Up an Angular Development Environment

Node.js: use a version manager, mind the minimums

This is where most setups break. Angular's CLI declares an exact Node range in its package.json, and npm enforces it. For Angular 22 that range is:

node: ^22.22.3 || ^24.15.0 || >=26.0.0

Read those carefully — they're minor version floors, not major ones. Node 22.14 fails. Node 24.10 fails. Node 22.22.3 passes. This trips people up constantly, because "I'm on Node 22, the docs say Node 22" feels like it should be enough.

The fix isn't to chase a specific installer — it's to stop installing Node in a way you can't change. Use a version manager:

# macOS / Linux — nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
nvm install 24
nvm use 24
node --version   # v24.x

On Windows, nvm-windows or fnm work the same way. Whichever you pick, commit a .nvmrc file at the repo root containing the major version:

echo "24" > .nvmrc
nvm use          # reads .nvmrc, no argument needed

Now every checkout — yours, a teammate's, CI — resolves to the same runtime without anyone remembering a number. The companion repo pins Node 24, the current LTS.

npm ships with Node, and plain npm is fine for Angular. If your team standardises on pnpm or yarn, run corepack enable and set cli.packageManager in angular.json so the CLI's own ng add and ng update use the same one.

Install the Angular CLI

npm install -g @angular/cli
ng version

Two habits worth adopting immediately.

First: the local CLI wins. Inside a workspace, ng resolves to the version in that project's node_modules, not your global install. That's deliberate and good — it means a global CLI on 22.1 can safely work on a project still pinned to 20.x. It also means the version you see depends on where you're standing:

Angular CLI       : 22.1.5
Angular           : 22.1.3
Node.js           : 26.6.0
Package Manager   : npm 11.12.1
Operating System  : darwin arm64

Second: you may not need a global install at all. npx @angular/cli@latest new my-app scaffolds with the newest CLI without leaving anything on your machine — handy when you create projects rarely and don't want a stale global binary drifting out of date.

How the pieces fit together

The Angular 22 toolchain

Four moving parts, and version mismatches at the first one are what break the other three. That's why the Node section comes before everything else.

Create and run a workspace

ng new my-app --style css
cd my-app
ng serve

The scaffold asks about stylesheet format, zoneless change detection, and SSR. The defaults are sensible; take them for a first project. ng serve compiles, serves at http://localhost:4200, and hot-reloads on save.

A production build on this setup is fast, and the numbers are worth internalising as a baseline:

Initial chunk files | Names         |  Raw size | Estimated transfer size
main-MIP6P3KO.js    | main          | 270.08 kB |                73.04 kB
styles-5INURTSO.css | styles        |   0 bytes |                 0 bytes

                    | Initial total | 270.08 kB |                73.04 kB

Application bundle generation complete. [1.231 seconds]

270 kB raw, 73 kB over the wire, in about a second. If your builds are dramatically slower than this on a small app, something is misconfigured — that's a signal, not the cost of doing business.

What Angular 22 gives you by default

If you learned Angular a few years ago, several defaults have changed, and tutorials that predate them will actively mislead you:

  • Standalone components — no NgModule to learn first. If a tutorial opens app.module.ts, it's from an earlier era.
  • Signals for reactive state, alongside the input() / output() functions that replace the @Input() / @Output() decorators.
  • Built-in control flow@if, @for, @switch in templates instead of *ngIf and *ngFor.
  • esbuild-based builds via the @angular/build:application builder — the source of those sub-second rebuilds.
  • Vitest as the default test runner. Karma is gone. New workspaces use the @angular/build:unit-test builder with Vitest and jsdom, so tests run in Node rather than launching a browser:
 Test Files  1 passed (1)
      Tests  2 passed (2)
   Duration  522ms
  • TypeScript 6.0, which brings its own stricter defaults.

That last group matters for debugging setup: if you copy a launch.json from an older project, its test configuration will point at Karma's http://localhost:9876/debug.html, which no longer exists. (The companion repo had exactly this stale config — a good reminder that scaffolded files age.)

VS Code: the extensions that matter

Only one is genuinely essential: the Angular Language Service (angular.ng-template). It gives you template type checking, autocomplete for component members inside HTML, and go-to-definition across the template/class boundary. Without it, your templates are effectively stringly-typed; with it, a typo'd property name is a red squiggle before you ever save.

Worth adding: Prettier for formatting and EditorConfig so line endings and indentation stay consistent across editors. Commit both configs — the scaffold ships an .editorconfig already. Check your recommendations into .vscode/extensions.json and new team members get prompted automatically.

For debugging, you need no extension at all. VS Code's built-in JavaScript debugger attaches to Chrome or Edge:

{
  "name": "ng serve",
  "type": "chrome",
  "request": "launch",
  "preLaunchTask": "npm: start",
  "url": "http://localhost:4200/"
}

Breakpoints land in your TypeScript, not the compiled output, because the dev server ships source maps by default.

Turn strict mode on now

New workspaces enable strict TypeScript by default, but plenty of older projects have it switched off, and turning it on later is painful in proportion to how long you waited. The settings that pay for themselves:

{
  "compilerOptions": {
    "strict": true
  },
  "angularCompilerOptions": {
    "strictTemplates": true,
    "typeCheckHostBindings": true
  }
}

strictTemplates is the one people skip and later regret. It type-checks bindings against your component's actual types, so passing a string into a number input becomes a build error instead of a runtime surprise. typeCheckHostBindings extends the same checking to host bindings and listeners.

Enabling these on the companion repo cost nothing — the build stayed clean and both tests still passed. On an established codebase, expect to fix real bugs.

The commands you'll live in

ng serve                          # dev server + HMR
ng generate component products    # scaffold a component with its spec
ng build                          # production build to dist/
ng test                           # unit tests (Vitest)
ng update                         # framework migrations between majors

ng update is the underrated one. Angular ships automated migrations with every major release, and the CLI rewrites your code for you:

Updating package.json with dependency @angular/core to version 22.1.3...
Updating package.json with dependency @angular/cli to version 22.1.5...
✔ Cleaning node modules directory
✔ Installing packages

Codebases that update on schedule stay boring. Codebases that skip three majors become migration projects with their own budget. Run ng update the month a release lands, not the year after.

Troubleshooting the classics

  • "The Angular CLI requires a minimum Node.js version..." — read the required minor version, not just the major. nvm install 24 && nvm use 24 resolves it.
  • ng not found after a global install — npm's global bin directory isn't on your PATH. Version managers handle this; system Node installs often don't.
  • EACCES on global installs — never reach for sudo npm install -g. That error means Node is installed somewhere you don't own, which is exactly what a version manager fixes.
  • Corporate proxy pain — set npm config set proxy and https-proxy, and confirm the CLI's package manager reads the same config.
  • Tests fail after upgrading — check whether a stale spec still asserts against the scaffold's original markup. This is the single most common "the upgrade broke my tests" cause, and it isn't the upgrade's fault.
  • Stale-state weirdnessrm -rf node_modules .angular && npm install resolves more mysteries than anyone likes to admit. The .angular cache directory is the part people forget.

Where to go next

With a healthy environment, the framework itself is the easy part. Next up is Angular in VS Code — the editor setup, the Language Service, and debugging. After that the components tutorial builds your first real components with signals, directives and control flow covers the template syntax, nested components shows data flowing down and events flowing up, and lifecycle hooks explains exactly when each phase runs.

Every example in that series lives in one runnable workspace — clone the companion repository, run npm install && npm start, and read along with the code in front of you.

Enjoyed this article? Get the best GeeksArray articles in your inbox — once a week, no spam, unsubscribe anytime.

Comments (0)

Log in to join the conversation.

No comments yet — be the first to share your thoughts.