Photo by Priscilla Du Preez ๐จ๐ฆ on Unsplash
๐ฅ Persisting Shared State in Angular Micro Frontends (MFEs) using NgRx + localStorage
Persisting Shared State in Angular MFEs with NgRx and localStorage ensures state remains intact after page reloads. By using NgRx MetaReducers
When using NgRx across Micro Frontends, the state resets on page reload because it's stored in memory.
โ
To persist the state across reloads, weโll use localStorage with NgRx MetaReducers.
๐ Step 1: Create a MetaReducer to Sync State with localStorage
Modify projects/mfe1/src/app/store/local-storage.reducer.ts
:
๐น Define MetaReducer
import { ActionReducer, INIT, UPDATE } from '@ngrx/store';
export function localStorageMetaReducer<S>(reducer: ActionReducer<S>): ActionReducer<S> {
return (state, action) => {
if (action.type === INIT || action.type === UPDATE) {
const savedState = localStorage.getItem('appState');
return savedState ? JSON.parse(savedState) : state;
}
const nextState = reducer(state, action);
localStorage.setItem('appState', JSON.stringify(nextState));
return nextState;
};
}
๐ How it Works:
On App Start (
INIT
), it checks if state exists inlocalStorage
and loads it.On Any State Update, it saves the latest state to
localStorage
.
๐ Step 2: Apply MetaReducer in MFE1
Modify projects/mfe1/src/app/app.module.ts
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule, MetaReducer } from '@ngrx/store';
import { counterReducer } from './store/counter.reducer';
import { localStorageMetaReducer } from './store/local-storage.reducer';
import { AppComponent } from './app.component';
const metaReducers: MetaReducer<any>[] = [localStorageMetaReducer];
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
StoreModule.forRoot({ count: counterReducer }, { metaReducers }), // Apply MetaReducer
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
โ
Now, MFE1 automatically saves state to localStorage
and restores it on page reload.
๐ Step 3: Apply MetaReducer in Shell App
Modify projects/shell/src/app/app.module.ts
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule, MetaReducer } from '@ngrx/store';
import { counterReducer } from 'mfe1/Store';
import { localStorageMetaReducer } from 'mfe1/Store'; // Import from remote
const metaReducers: MetaReducer<any>[] = [localStorageMetaReducer];
@NgModule({
declarations: [],
imports: [
BrowserModule,
StoreModule.forRoot({ count: counterReducer }, { metaReducers }), // Apply MetaReducer
],
providers: [],
bootstrap: [],
})
export class AppModule {}
โ
Now, the Shell App also persists and loads state from localStorage
!
๐ Step 4: Test the Persistent State
Run MFE1:
ng serve mfe1 --port 4201
Run Shell App:
ng serve shell --port 4200
Increment/Decrement the counter
Refresh the page
โ State remains intact! ๐
๐ฅ Final Summary
โ
NgRx MetaReducers ensure persistent state storage.
โ
localStorage maintains shared state between MFEs and Shell App.
โ
Cross-MFE state management is seamless with Module Federation.