feat: add Angular NgRx best practices documentation

This commit is contained in:
Dennis Hundertmark
2026-03-08 08:51:02 +01:00
parent 67dc823270
commit 2184971175
47 changed files with 8490 additions and 0 deletions
+352
View File
@@ -0,0 +1,352 @@
---
name: angular-tooling
description: Use Angular CLI and development tools effectively in Angular v20+ projects. Use for project setup, code generation, building, testing, and configuration. Triggers on creating new projects, generating components/services/modules, configuring builds, running tests, or optimizing production builds. Don't use for Nx workspace commands, custom Webpack configurations, or non-Angular CLI build systems like Vite standalone or esbuild direct usage.
---
# Angular Tooling
Use Angular CLI and development tools for efficient Angular v20+ development.
## Project Setup
### Create New Project
```bash
# Create new standalone project (default in v20+)
ng new my-app
# With specific options
ng new my-app --style=scss --routing --ssr=false
# Skip tests
ng new my-app --skip-tests
# Minimal setup
ng new my-app --minimal --inline-style --inline-template
```
### Project Structure
```
my-app/
├── src/
│ ├── app/
│ │ ├── app.component.ts
│ │ ├── app.config.ts
│ │ └── app.routes.ts
│ ├── index.html
│ ├── main.ts
│ └── styles.scss
├── public/ # Static assets
├── angular.json # CLI configuration
├── package.json
├── tsconfig.json
└── tsconfig.app.json
```
## Code Generation
### Components
```bash
# Generate component
ng generate component features/user-profile
ng g c features/user-profile # Short form
# With options
ng g c shared/button --inline-template --inline-style
ng g c features/dashboard --skip-tests
ng g c features/settings --change-detection=OnPush
# Flat (no folder)
ng g c shared/icon --flat
# Dry run (preview)
ng g c features/checkout --dry-run
```
### Services
```bash
# Generate service (providedIn: 'root' by default)
ng g service services/auth
ng g s services/user
# Skip tests
ng g s services/api --skip-tests
```
### Other Schematics
```bash
# Directive
ng g directive directives/highlight
ng g d directives/tooltip
# Pipe
ng g pipe pipes/truncate
ng g p pipes/date-format
# Guard (functional by default)
ng g guard guards/auth
# Interceptor (functional by default)
ng g interceptor interceptors/auth
# Interface
ng g interface models/user
# Enum
ng g enum models/status
# Class
ng g class models/product
```
### Generate with Path Alias
```bash
# Components in feature folders
ng g c @features/products/product-list
ng g c @shared/ui/button
```
## Development Server
```bash
# Start dev server
ng serve
ng s # Short form
# With options
ng serve --port 4201
ng serve --open # Open browser
ng serve --host 0.0.0.0 # Expose to network
# Production mode locally
ng serve --configuration=production
# With SSL
ng serve --ssl --ssl-key ./ssl/key.pem --ssl-cert ./ssl/cert.pem
```
## Building
### Development Build
```bash
ng build
```
### Production Build
```bash
ng build --configuration=production
ng build -c production # Short form
# With specific options
ng build -c production --source-map=false
ng build -c production --named-chunks
```
### Build Output
```
dist/my-app/
├── browser/
│ ├── index.html
│ ├── main-[hash].js
│ ├── polyfills-[hash].js
│ └── styles-[hash].css
└── server/ # If SSR enabled
└── main.js
```
## Testing
### Unit Tests
```bash
# Run tests
ng test
ng t # Short form
# Single run (CI)
ng test --watch=false --browsers=ChromeHeadless
# With coverage
ng test --code-coverage
# Specific file
ng test --include=**/user.service.spec.ts
```
### E2E Tests
```bash
# Run e2e (if configured)
ng e2e
```
## Linting
```bash
# Run linter
ng lint
# Fix auto-fixable issues
ng lint --fix
```
## Configuration
### angular.json Key Sections
```json
{
"projects": {
"my-app": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/my-app",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": ["{ \"glob\": \"**/*\", \"input\": \"public\" }"],
"styles": ["src/styles.scss"],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kB",
"maximumError": "1MB"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
}
}
}
}
}
}
```
### Environment Configuration
```typescript
// src/environments/environment.ts
export const environment = {
production: false,
apiUrl: "http://localhost:3000/api",
};
// src/environments/environment.prod.ts
export const environment = {
production: true,
apiUrl: "https://api.example.com",
};
```
Configure in angular.json:
```json
{
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
}
```
## Adding Libraries
### Angular Libraries
```bash
# Add Angular Material
ng add @angular/material
# Add Angular PWA
ng add @angular/pwa
# Add Angular SSR
ng add @angular/ssr
# Add Angular Localize
ng add @angular/localize
```
### Third-Party Libraries
```bash
# Install and configure
npm install @ngrx/signals
# Some libraries have schematics
ng add @ngrx/store
```
## Update Angular
```bash
# Check for updates
ng update
# Update Angular core and CLI
ng update @angular/core @angular/cli
# Update all packages
ng update --all
# Force update (skip peer dependency checks)
ng update @angular/core @angular/cli --force
```
## Performance Analysis
```bash
# Build with stats
ng build -c production --stats-json
# Analyze bundle (install esbuild-visualizer)
npx esbuild-visualizer --metadata dist/my-app/browser/stats.json --open
```
## Caching
```bash
# Enable persistent build cache (default in v20+)
# Configured in angular.json:
{
"cli": {
"cache": {
"enabled": true,
"path": ".angular/cache",
"environment": "all"
}
}
}
# Clear cache
rm -rf .angular/cache
```
For advanced configuration, see [references/tooling-patterns.md](references/tooling-patterns.md).
@@ -0,0 +1,462 @@
# Angular Tooling Patterns
## Table of Contents
- [Custom Schematics](#custom-schematics)
- [Build Optimization](#build-optimization)
- [Multi-Project Workspace](#multi-project-workspace)
- [CI/CD Configuration](#cicd-configuration)
- [Path Aliases](#path-aliases)
- [Proxy Configuration](#proxy-configuration)
## Custom Schematics
### Generate Schematic Collection
```bash
# Install schematics CLI
npm install -g @angular-devkit/schematics-cli
# Create schematic collection
schematics blank --name=my-schematics
```
### Simple Component Schematic
```typescript
// src/my-component/index.ts
import {
Rule,
SchematicContext,
Tree,
apply,
url,
template,
move,
mergeWith,
} from "@angular-devkit/schematics";
import { strings } from "@angular-devkit/core";
export function myComponent(options: { name: string; path: string }): Rule {
return (tree: Tree, context: SchematicContext) => {
const templateSource = apply(url("./files"), [
template({
...options,
...strings,
}),
move(options.path),
]);
return mergeWith(templateSource)(tree, context);
};
}
```
### Use Custom Schematics
```bash
# Link locally
npm link ./my-schematics
# Use
ng generate my-schematics:my-component --name=test --path=src/app
```
## Build Optimization
### Budget Configuration
```json
{
"budgets": [
{
"type": "initial",
"maximumWarning": "500kB",
"maximumError": "1MB"
},
{
"type": "anyComponentStyle",
"maximumWarning": "4kB",
"maximumError": "8kB"
},
{
"type": "anyScript",
"maximumWarning": "100kB",
"maximumError": "200kB"
}
]
}
```
### Differential Loading
Automatic in v20+ - builds for modern browsers by default.
```json
// .browserslistrc
last 2 Chrome versions
last 2 Firefox versions
last 2 Safari versions
last 2 Edge versions
```
### Code Splitting
```typescript
// Lazy load routes for automatic code splitting
export const routes: Routes = [
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.adminRoutes),
},
{
path: "reports",
loadComponent: () =>
import("./reports/reports.component").then((m) => m.Reports),
},
];
```
### Tree Shaking
Ensure proper imports for tree shaking:
```typescript
// Good - tree shakeable
import { map, filter } from "rxjs";
// Avoid - imports entire library
import * as rxjs from "rxjs";
```
### Preload Strategy
```typescript
// app.config.ts
import {
provideRouter,
withPreloading,
PreloadAllModules,
} from "@angular/router";
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes, withPreloading(PreloadAllModules))],
};
```
## Multi-Project Workspace
### Create Workspace
```bash
# Create empty workspace
ng new my-workspace --create-application=false
cd my-workspace
# Add applications
ng generate application main-app
ng generate application admin-app
# Add library
ng generate library shared-ui
ng generate library data-access
```
### Workspace Structure
```
my-workspace/
├── projects/
│ ├── main-app/
│ │ └── src/
│ ├── admin-app/
│ │ └── src/
│ ├── shared-ui/
│ │ └── src/
│ └── data-access/
│ └── src/
├── angular.json
└── package.json
```
### Build Specific Project
```bash
ng build main-app
ng build shared-ui
ng serve admin-app
```
### Library Configuration
```json
// projects/shared-ui/ng-package.json
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/shared-ui",
"lib": {
"entryFile": "src/public-api.ts"
}
}
```
### Using Library in App
```typescript
// After building library: ng build shared-ui
import { Button } from "shared-ui";
@Component({
imports: [Button],
template: `<lib-button>Click</lib-button>`,
})
export class App {}
```
## CI/CD Configuration
### GitHub Actions
```yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm run test -- --watch=false --browsers=ChromeHeadless --code-coverage
- name: Build
run: npm run build -- -c production
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
```
### GitLab CI
```yaml
# .gitlab-ci.yml
image: node:20
cache:
paths:
- node_modules/
- .angular/cache/
stages:
- install
- test
- build
install:
stage: install
script:
- npm ci
test:
stage: test
script:
- npm run lint
- npm run test -- --watch=false --browsers=ChromeHeadless
build:
stage: build
script:
- npm run build -- -c production
artifacts:
paths:
- dist/
```
## Path Aliases
### Configure tsconfig.json
```json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@app/*": ["src/app/*"],
"@env/*": ["src/environments/*"],
"@shared/*": ["src/app/shared/*"],
"@features/*": ["src/app/features/*"],
"@core/*": ["src/app/core/*"]
}
}
}
```
### Usage
```typescript
// Instead of relative imports
import { User } from "../../../core/services/user.service";
// Use path alias
import { User } from "@core/services/user.service";
```
## Proxy Configuration
### Development Proxy
```json
// proxy.conf.json
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true
},
"/auth": {
"target": "http://localhost:4000",
"secure": false,
"pathRewrite": {
"^/auth": ""
}
}
}
```
### Configure in angular.json
```json
{
"serve": {
"options": {
"proxyConfig": "proxy.conf.json"
}
}
}
```
### Or via CLI
```bash
ng serve --proxy-config proxy.conf.json
```
## Custom Builders
### Using esbuild (Default in v20+)
```json
{
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"browser": "src/main.ts"
}
}
}
}
```
### SSR Configuration
```bash
# Add SSR
ng add @angular/ssr
```
```json
{
"architect": {
"build": {
"options": {
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "server.ts"
}
}
}
}
}
```
## Debugging
### Source Maps
```json
{
"configurations": {
"development": {
"sourceMap": true
},
"production": {
"sourceMap": {
"scripts": true,
"styles": false,
"hidden": true,
"vendor": false
}
}
}
}
```
### Verbose Logging
```bash
ng build --verbose
ng serve --verbose
```
### Debug Tests
```bash
# Run tests with debugging
ng test --browsers=Chrome
# In Chrome DevTools, open Sources tab and set breakpoints
```
## Package Scripts
```json
{
"scripts": {
"start": "ng serve",
"build": "ng build",
"build:prod": "ng build -c production",
"test": "ng test",
"test:ci": "ng test --watch=false --browsers=ChromeHeadless --code-coverage",
"lint": "ng lint",
"lint:fix": "ng lint --fix",
"analyze": "ng build -c production --stats-json && npx esbuild-visualizer --metadata dist/my-app/browser/stats.json --open",
"update": "ng update"
}
}
```