| name | ngrx-devtool-debugger |
| description | Debug and visualize NgRx state management in Angular apps with real-time action monitoring, effect tracking, state diffs, and performance metrics |
| triggers | ["debug ngrx state and actions","setup ngrx devtool","visualize ngrx effects and state changes","monitor ngrx actions in real time","configure ngrx debugging tool","track angular state management with ngrx devtool","troubleshoot ngrx performance issues","inspect ngrx store state changes"] |
NgRx DevTool Debugger
Skill by ara.so — Devtools Skills collection.
NgRx DevTool is a comprehensive debugging and visualization tool for NgRx state management in Angular applications. It provides real-time action monitoring, effect tracking, state visualization with diff viewer, and performance metrics without requiring browser extensions. The tool runs a separate WebSocket server that your Angular app connects to, displaying all NgRx activity in a dedicated UI.
Installation
Install the package as a development dependency:
npm install --save-dev @amadeus-it-group/ngrx-devtool
Or with yarn:
yarn add -D @amadeus-it-group/ngrx-devtool
Basic Setup
1. Configure Your Angular Application
Add the DevTool provider and meta-reducer to your application configuration:
import { ApplicationConfig } from '@angular/core';
import { provideStore } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import {
provideNgrxDevTool,
createDevToolMetaReducer
} from '@amadeus-it-group/ngrx-devtool';
import * as fromRoot from './store/reducers';
import { AppEffects } from './store/effects/app.effects';
export const appConfig: ApplicationConfig = {
providers: [
provideStore(
fromRoot.reducers,
{
metaReducers: [createDevToolMetaReducer()]
}
),
provideEffects([AppEffects]),
provideNgrxDevTool({
wsUrl: 'ws://localhost:4000',
trackEffects: true,
enabled: true
})
]
};
2. Module-Based Configuration (Legacy)
If using NgModule instead of standalone components:
import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import {
NgRxDevToolModule,
createDevToolMetaReducer
} from '@amadeus-it-group/ngrx-devtool';
import { reducers } from './store/reducers';
import { AppEffects } from './store/effects/app.effects';
@NgModule({
imports: [
StoreModule.forRoot(reducers, {
metaReducers: [createDevToolMetaReducer()]
}),
EffectsModule.forRoot([AppEffects]),
NgRxDevToolModule.forRoot({
wsUrl: 'ws://localhost:4000',
trackEffects: true
})
]
})
export class AppModule {}
CLI Commands
Start the DevTool Server
The primary command to launch both the WebSocket server and UI:
npx ngrx-devtool
This starts:
- WebSocket server on
ws://localhost:4000
- UI server on
http://localhost:3000
Custom Port Configuration
npx ngrx-devtool --ws-port 5000
npx ngrx-devtool --ui-port 8080
npx ngrx-devtool --ws-port 5000 --ui-port 8080
Server Only Mode
Run only the WebSocket server without the UI:
npx ngrx-devtool --server-only
Configuration Options
DevTool Configuration Interface
interface NgRxDevToolConfig {
wsUrl?: string;
enabled?: boolean;
trackEffects?: boolean;
maxActions?: number;
autoConnect?: boolean;
reconnectAttempts?: number;
reconnectDelay?: number;
}
Environment-Based Configuration
import { isDevMode } from '@angular/core';
import { provideNgrxDevTool, createDevToolMetaReducer } from '@amadeus-it-group/ngrx-devtool';
export const appConfig: ApplicationConfig = {
providers: [
provideStore(
reducers,
{
metaReducers: isDevMode() ? [createDevToolMetaReducer()] : []
}
),
provideNgrxDevTool({
wsUrl: `ws://${window.location.hostname}:4000`,
enabled: isDevMode(),
trackEffects: true,
maxActions: 200,
reconnectAttempts: 5
})
]
};
Production-Safe Configuration
import { environment } from './environments/environment';
export const appConfig: ApplicationConfig = {
providers: [
provideStore(
reducers,
{
metaReducers: environment.devToolEnabled
? [createDevToolMetaReducer()]
: []
}
),
provideNgrxDevTool({
wsUrl: environment.devToolWsUrl,
enabled: environment.devToolEnabled,
trackEffects: environment.devToolEnabled
})
]
};
export const environment = {
production: false,
devToolEnabled: true,
devToolWsUrl: 'ws://localhost:4000'
};
export const environment = {
production: true,
devToolEnabled: false,
devToolWsUrl: ''
};
Usage Patterns
Monitoring Actions
Once configured, all dispatched actions are automatically tracked:
import { createAction, props } from '@ngrx/store';
export const loadUsers = createAction('[User List] Load Users');
export const loadUsersSuccess = createAction(
'[User API] Load Users Success',
props<{ users: User[] }>()
);
export const loadUsersFailure = createAction(
'[User API] Load Users Failure',
props<{ error: string }>()
);
this.store.dispatch(loadUsers());
Effect Tracking
Effects are automatically tracked when trackEffects: true:
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { catchError, map, switchMap } from 'rxjs/operators';
import { of } from 'rxjs';
import * as UserActions from './user.actions';
import { UserService } from '../services/user.service';
@Injectable()
export class UserEffects {
loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUsers),
switchMap(() =>
this.userService.getUsers().pipe(
map(users => UserActions.loadUsersSuccess({ users })),
catchError( (.({
: error.
})))
)
)
)
);
() {}
}
State Visualization
The DevTool automatically captures state before and after each action, showing diffs:
import { createReducer, on } from '@ngrx/store';
import * as CounterActions from './counter.actions';
export interface CounterState {
count: number;
lastUpdated: Date | null;
}
export const initialState: CounterState = {
count: 0,
lastUpdated: null
};
export const counterReducer = createReducer(
initialState,
on(CounterActions.increment, state => ({
...state,
count: state.count + 1,
lastUpdated: new Date()
})),
on(CounterActions.decrement, state => ({
...state,
count: state.count - 1,
lastUpdated: new Date()
})),
on(CounterActions., initialState)
);
Custom Action Metadata
Add metadata to actions for better debugging:
import { createAction, props } from '@ngrx/store';
export const addToCart = createAction(
'[Product] Add to Cart',
props<{
productId: string;
quantity: number;
metadata?: { source: string; timestamp: number }
}>()
);
this.store.dispatch(addToCart({
productId: 'prod-123',
quantity: 2,
metadata: {
source: 'product-detail-page',
timestamp: Date.now()
}
}));
Advanced Configuration
Selective Action Tracking
Filter which actions to track by customizing the meta-reducer:
import { ActionReducer, Action } from '@ngrx/store';
import { createDevToolMetaReducer } from '@amadeus-it-group/ngrx-devtool';
function createFilteredDevToolMetaReducer() {
const devToolMetaReducer = createDevToolMetaReducer();
return (reducer: ActionReducer<any>) => {
const wrappedReducer = devToolMetaReducer(reducer);
return (state: any, action: Action) => {
if (action.type.includes('[Router]') ||
action.type.includes('[Internal]')) {
return reducer(state, action);
}
return wrappedReducer(state, action);
};
};
}
export const appConfig: ApplicationConfig = {
providers: [
provideStore(reducers, {
metaReducers: [createFilteredDevToolMetaReducer()]
}),
()
]
};
Multiple Environment Setup
const devToolConfig = (() => {
const hostname = window.location.hostname;
if (hostname === 'localhost') {
return { wsUrl: 'ws://localhost:4000', enabled: true };
} else if (hostname.includes('staging')) {
return { wsUrl: 'ws://staging-devtool.example.com:4000', enabled: true };
}
return { enabled: false };
})();
export const appConfig: ApplicationConfig = {
providers: [
provideNgrxDevTool(devToolConfig)
]
};
Troubleshooting
Connection Issues
Problem: DevTool UI shows "Disconnected" status
Solutions:
- Verify the DevTool server is running:
npx ngrx-devtool
- Check WebSocket URL matches server configuration:
provideNgrxDevTool({
wsUrl: 'ws://localhost:4000'
})
- Check browser console for connection errors:
WebSocket connection to 'ws://localhost:4000' failed: Connection refused
- Verify no firewall blocking WebSocket connections
Actions Not Appearing
Problem: Actions are dispatched but not showing in DevTool
Solutions:
- Ensure meta-reducer is registered:
provideStore(reducers, {
metaReducers: [createDevToolMetaReducer()]
})
- Verify DevTool is enabled:
provideNgrxDevTool({
enabled: true
})
- Check for action filtering that might be excluding actions
Effects Not Tracked
Problem: Effects execute but don't appear in DevTool
Solutions:
- Enable effect tracking:
provideNgrxDevTool({
trackEffects: true
})
- Ensure effects are properly registered:
provideEffects([UserEffects, ProductEffects])
- Verify effects use the
createEffect() function
Performance Issues
Problem: Application slows down with DevTool enabled
Solutions:
- Reduce action history limit:
provideNgrxDevTool({
maxActions: 50
})
- Filter high-frequency actions:
- Disable in production builds:
provideNgrxDevTool({
enabled: !environment.production
})
Port Conflicts
Problem: Port 4000 or 3000 already in use
Solutions:
- Use custom ports:
npx ngrx-devtool --ws-port 5000 --ui-port 8080
- Update configuration to match:
provideNgrxDevTool({
wsUrl: 'ws://localhost:5000'
})
State Diff Not Showing
Problem: State changes occur but diff viewer is empty
Solutions:
- Ensure reducer returns new state reference:
on(updateUser, (state, { user }) => {
state.user = user;
return state;
})
on(updateUser, (state, { user }) => ({
...state,
user
}))
- Check state serialization for circular references
Browser Compatibility
The DevTool requires WebSocket support. All modern browsers support WebSockets, but if you encounter issues:
- Ensure browser is up to date
- Check corporate proxy/firewall settings
- Try different browser to isolate issue
- Check browser console for specific WebSocket errors