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.

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

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
NgModuleto learn first. If a tutorial opensapp.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,@switchin templates instead of*ngIfand*ngFor. - esbuild-based builds via the
@angular/build:applicationbuilder — the source of those sub-second rebuilds. - Vitest as the default test runner. Karma is gone. New workspaces use the
@angular/build:unit-testbuilder 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 24resolves it. ngnot found after a global install — npm's global bin directory isn't on yourPATH. Version managers handle this; system Node installs often don't.EACCESon global installs — never reach forsudo 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 proxyandhttps-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 weirdness —
rm -rf node_modules .angular && npm installresolves more mysteries than anyone likes to admit. The.angularcache 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.
Comments (0)
No comments yet — be the first to share your thoughts.