or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

action-creators.mdfeature-management.mdindex.mdmodule-configuration.mdreducer-creators.mdselectors.mdstandalone-providers.mdstore-service.mdtesting-utilities.md

module-configuration.mddocs/

0

# Module Configuration

1

2

Module configuration provides NgModule-based setup for traditional Angular applications using the `StoreModule` with `forRoot` and `forFeature` patterns for root and feature state management.

3

4

## Capabilities

5

6

### Store Module

7

8

Main NgModule for configuring NgRx Store in module-based Angular applications.

9

10

```typescript { .api }

11

/**

12

* NgModule for configuring NgRx Store

13

*/

14

class StoreModule {

15

/**

16

* Configure the root store with initial reducers and configuration

17

* @param reducers - Map of reducers or injection token for reducers

18

* @param config - Root store configuration options

19

* @returns ModuleWithProviders for StoreRootModule

20

*/

21

static forRoot<T, V extends Action = Action>(

22

reducers?: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>,

23

config?: RootStoreConfig<T, V>

24

): ModuleWithProviders<StoreRootModule>;

25

26

/**

27

* Configure feature store with feature-specific reducers

28

* @param featureName - Name/key for the feature state slice

29

* @param reducers - Feature reducers map or single reducer

30

* @param config - Feature store configuration options

31

* @returns ModuleWithProviders for StoreFeatureModule

32

*/

33

static forFeature<T, V extends Action = Action>(

34

featureName: string,

35

reducers: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>,

36

config?: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>>

37

): ModuleWithProviders<StoreFeatureModule>;

38

39

static forFeature<T, V extends Action = Action>(

40

featureName: string,

41

reducer: ActionReducer<T, V> | InjectionToken<ActionReducer<T, V>>,

42

config?: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>>

43

): ModuleWithProviders<StoreFeatureModule>;

44

45

static forFeature<T, V extends Action = Action>(

46

slice: FeatureSlice<T, V>

47

): ModuleWithProviders<StoreFeatureModule>;

48

}

49

50

/**

51

* Root store module implementation

52

*/

53

class StoreRootModule {}

54

55

/**

56

* Feature store module implementation

57

*/

58

class StoreFeatureModule implements OnDestroy {}

59

```

60

61

**Usage Examples:**

62

63

```typescript

64

import { NgModule } from "@angular/core";

65

import { StoreModule } from "@ngrx/store";

66

import { reducers, metaReducers } from "./app.reducers";

67

68

// Root module configuration

69

@NgModule({

70

imports: [

71

StoreModule.forRoot(reducers, {

72

metaReducers,

73

runtimeChecks: {

74

strictStateImmutability: true,

75

strictActionImmutability: true,

76

strictStateSerializability: true,

77

strictActionSerializability: true,

78

strictActionWithinNgZone: true,

79

strictActionTypeUniqueness: true

80

}

81

})

82

]

83

})

84

export class AppModule {}

85

86

// Feature module with reducer map

87

@NgModule({

88

imports: [

89

StoreModule.forFeature('users', {

90

list: userListReducer,

91

profile: userProfileReducer,

92

preferences: userPreferencesReducer

93

}, {

94

metaReducers: [userMetaReducer],

95

initialState: {

96

list: { entities: [], loading: false },

97

profile: null,

98

preferences: defaultPreferences

99

}

100

})

101

]

102

})

103

export class UserModule {}

104

105

// Feature module with single reducer

106

@NgModule({

107

imports: [

108

StoreModule.forFeature('orders', orderReducer, {

109

initialState: initialOrderState

110

})

111

]

112

})

113

export class OrderModule {}

114

115

// Feature module with FeatureSlice

116

@NgModule({

117

imports: [

118

StoreModule.forFeature({

119

name: 'products',

120

reducer: productReducer,

121

initialState: initialProductState

122

})

123

]

124

})

125

export class ProductModule {}

126

```

127

128

## Configuration Types

129

130

### Root Store Configuration

131

132

```typescript { .api }

133

/**

134

* Configuration options for root store

135

*/

136

interface RootStoreConfig<T, V extends Action = Action> {

137

/** Initial state for the entire application */

138

initialState?: InitialState<T>;

139

/** Meta-reducers applied to all reducers */

140

metaReducers?: MetaReducer<T, V>[];

141

/** Runtime validation checks configuration */

142

runtimeChecks?: Partial<RuntimeChecks>;

143

}

144

145

/**

146

* Runtime validation checks configuration

147

*/

148

interface RuntimeChecks {

149

/** Verifies if the state is serializable */

150

strictStateSerializability: boolean;

151

/** Verifies if the actions are serializable */

152

strictActionSerializability: boolean;

153

/** Verifies that the state isn't mutated */

154

strictStateImmutability: boolean;

155

/** Verifies that actions aren't mutated */

156

strictActionImmutability: boolean;

157

/** Verifies that actions are dispatched within NgZone */

158

strictActionWithinNgZone: boolean;

159

/** Verifies that action types are not registered more than once */

160

strictActionTypeUniqueness?: boolean;

161

}

162

```

163

164

### Feature Store Configuration

165

166

```typescript { .api }

167

/**

168

* Configuration options for feature store

169

*/

170

interface StoreConfig<T, V extends Action = Action> {

171

/** Initial state for the feature */

172

initialState?: InitialState<T>;

173

/** Meta-reducers applied to feature reducers */

174

metaReducers?: MetaReducer<T, V>[];

175

}

176

177

/**

178

* Feature slice configuration

179

*/

180

interface FeatureSlice<T, V extends Action = Action> {

181

/** Name/key for the feature */

182

name: string;

183

/** Reducer function for the feature */

184

reducer: ActionReducer<T, V>;

185

/** Initial state for the feature */

186

initialState?: InitialState<T>;

187

/** Meta-reducers for the feature */

188

metaReducers?: MetaReducer<T, V>[];

189

}

190

191

/**

192

* Initial state configuration type

193

*/

194

type InitialState<T> = Partial<T> | TypeId<Partial<T>> | void;

195

type TypeId<T> = () => T;

196

```

197

198

## Advanced Configuration Patterns

199

200

### Lazy-Loaded Feature Modules

201

202

```typescript

203

// Lazy-loaded feature module

204

@NgModule({

205

imports: [

206

CommonModule,

207

StoreModule.forFeature('billing', billingReducer, {

208

initialState: () => ({

209

// Dynamic initial state

210

invoices: [],

211

currentPlan: getCurrentUserPlan(),

212

settings: getUserBillingSettings()

213

})

214

})

215

]

216

})

217

export class BillingModule {}

218

219

// Route configuration with lazy loading

220

const routes: Routes = [

221

{

222

path: 'billing',

223

loadChildren: () => import('./billing/billing.module').then(m => m.BillingModule)

224

}

225

];

226

```

227

228

### Injectable Configuration

229

230

```typescript

231

import { InjectionToken } from "@angular/core";

232

233

// Injectable reducer configuration

234

export const USER_REDUCERS = new InjectionToken<ActionReducerMap<UserState>>('User Reducers', {

235

factory: () => ({

236

profile: userProfileReducer,

237

settings: userSettingsReducer,

238

notifications: userNotificationsReducer

239

})

240

});

241

242

export const USER_CONFIG = new InjectionToken<StoreConfig<UserState>>('User Config', {

243

factory: () => ({

244

initialState: {

245

profile: null,

246

settings: defaultUserSettings,

247

notifications: { enabled: true, preferences: {} }

248

},

249

metaReducers: environment.production ? [] : [storeFreeze]

250

})

251

});

252

253

// Module using injectable tokens

254

@NgModule({

255

imports: [

256

StoreModule.forFeature('users', USER_REDUCERS, USER_CONFIG)

257

],

258

providers: [

259

// Custom providers if needed

260

{ provide: USER_CONFIG, useFactory: createUserConfig, deps: [UserService] }

261

]

262

})

263

export class UserModule {}

264

```

265

266

### Meta-Reducers Configuration

267

268

```typescript

269

import { MetaReducer } from "@ngrx/store";

270

import { storeFreeze } from "ngrx-store-freeze";

271

import { storeLogger } from "./store-logger";

272

273

// Environment-specific meta-reducers

274

export const metaReducers: MetaReducer<AppState>[] = !environment.production

275

? [storeLogger, storeFreeze]

276

: [];

277

278

// Feature-specific meta-reducers

279

const userMetaReducers: MetaReducer<UserState>[] = [

280

// Audit trail for user actions

281

auditTrailMetaReducer,

282

// Validation for user state changes

283

userValidationMetaReducer

284

];

285

286

@NgModule({

287

imports: [

288

StoreModule.forRoot(reducers, { metaReducers }),

289

StoreModule.forFeature('users', userReducer, {

290

metaReducers: userMetaReducers

291

})

292

]

293

})

294

export class AppModule {}

295

```

296

297

### Multi-Environment Configuration

298

299

```typescript

300

// Environment-specific configurations

301

const developmentConfig: RootStoreConfig<AppState> = {

302

runtimeChecks: {

303

strictStateImmutability: true,

304

strictActionImmutability: true,

305

strictStateSerializability: true,

306

strictActionSerializability: true,

307

strictActionWithinNgZone: true,

308

strictActionTypeUniqueness: true

309

},

310

metaReducers: [storeLogger, storeFreeze]

311

};

312

313

const productionConfig: RootStoreConfig<AppState> = {

314

runtimeChecks: {

315

strictStateImmutability: false,

316

strictActionImmutability: false,

317

strictStateSerializability: false,

318

strictActionSerializability: false,

319

strictActionWithinNgZone: false,

320

strictActionTypeUniqueness: false

321

},

322

metaReducers: []

323

};

324

325

@NgModule({

326

imports: [

327

StoreModule.forRoot(

328

reducers,

329

environment.production ? productionConfig : developmentConfig

330

)

331

]

332

})

333

export class AppModule {}

334

```

335

336

## Module Lifecycle Integration

337

338

### Feature Module Lifecycle

339

340

```typescript

341

import { OnDestroy } from "@angular/core";

342

import { Store } from "@ngrx/store";

343

344

@NgModule({

345

imports: [

346

StoreModule.forFeature('analytics', analyticsReducer)

347

]

348

})

349

export class AnalyticsModule implements OnDestroy {

350

constructor(private store: Store) {

351

// Initialize feature on module load

352

this.store.dispatch(initializeAnalytics());

353

}

354

355

ngOnDestroy() {

356

// Cleanup when module is destroyed

357

this.store.dispatch(cleanupAnalytics());

358

}

359

}

360

```

361

362

### Dynamic Feature Registration

363

364

```typescript

365

import { Injector } from "@angular/core";

366

import { Store } from "@ngrx/store";

367

368

export class DynamicFeatureService {

369

constructor(

370

private store: Store,

371

private injector: Injector

372

) {}

373

374

loadFeature(featureName: string, reducer: ActionReducer<any>) {

375

// Dynamically add feature reducer

376

this.store.addReducer(featureName, reducer);

377

378

// Initialize feature state

379

this.store.dispatch(initializeFeature({ featureName }));

380

}

381

382

unloadFeature(featureName: string) {

383

// Cleanup feature state

384

this.store.dispatch(cleanupFeature({ featureName }));

385

386

// Remove feature reducer

387

this.store.removeReducer(featureName);

388

}

389

}

390

```

391

392

## Integration with Angular Router

393

394

```typescript

395

import { Router } from "@angular/router";

396

import { Store } from "@ngrx/store";

397

398

// Route-based feature loading

399

const routes: Routes = [

400

{

401

path: 'dashboard',

402

loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule),

403

resolve: {

404

// Preload dashboard data

405

dashboardData: (route, state) => {

406

const store = inject(Store);

407

store.dispatch(loadDashboardData());

408

return store.select(selectDashboardLoaded).pipe(

409

filter(loaded => loaded),

410

take(1)

411

);

412

}

413

}

414

}

415

];

416

```

417

418

## Best Practices

419

420

1. **Root Configuration**: Configure runtime checks and meta-reducers at the root level

421

2. **Feature Isolation**: Use separate feature modules for different business domains

422

3. **Lazy Loading**: Combine with Angular's lazy loading for optimal bundle sizes

423

4. **Environment Configuration**: Use different configurations for development and production

424

5. **Injectable Tokens**: Use injection tokens for complex configuration scenarios

425

6. **Meta-Reducers**: Apply feature-specific meta-reducers for targeted functionality