Extends RouteModule functionality to allow for conditionally lazy-loading child routes based on feature flag. Allows for Services to configure Routes and includes helpers for preload strategy.
This allows you to use an endpoint to lazy-load modules, easily redirect users to 403/404 pages, performant A/B testing for features.
Angular Version | Support |
---|---|
9 | ✅ Yes |
10 | ✅ Yes |
11 | ✅ Yes |
12 | ✅ Yes |
13 | ✅ Yes |
14 | Mostly. Support for loadComponent coming soon |
Add:
ng add ngx-feature-flag-router
Update:
ng update ngx-feature-flag-router #Updates ngx-feature-flag-router to latest version
If you're not using the latest version of Angular, you'll have to specify the major version:
ng update ngx-feature-flag-router@10 #Specific to Angular 10
- Replace
RouterModule.forChild()
withFeatureFlagRouterModule.forChild()
Before:
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
/*...*/
];
@NgModule({
imports: [RouterModule.forChild(routes)],
})
export class MyModule {}
After:
import { FeatureFlagRouterModule, FeatureFlagRoutes } from 'ngx-feature-flag-router';
const routes: FeatureFlagRoutes = [
/*...*/
];
@NgModule({
imports: [FeatureFlagRouterModule.forChild(routes)],
})
export class MyModule {}
- Add
alternativeLoadChildren
andfeatureFlag
to conditional lazy-load alternative module whenfeatureFlag
returnstrue
Before:
const routes: Routes = [
{
path: 'hello-world',
loadChildren: () => import('./hello-world.module').then((m) => m.HelloWorldModule),
},
];
After:
const routes: FeatureFlagRoutes = [
{
path: 'hello-world',
loadChildren: () => import('./hello-world.module').then((m) => m.HelloWorldModule),
alternativeLoadChildren: () => import('./feature.module').then((m) => m.FeatureModule),
featureFlag: () => showFeature(), // Function that returns boolean
},
];
- Add your Service (
MyService
) as the second argument ofFeatureFlagRouterModule.forChild()
import { FeatureFlagRouterModule, FeatureFlagRoutes } from 'ngx-feature-flag-router';
// Initialize routes that don't require Service
const routes: FeatureFlagRoutes = [
/*...*/
];
@NgModule({
imports: [FeatureFlagRouterModule.forChild(routes, MyService)],
})
export class MyModule {}
- Add implements
FeatureFlagRoutesService
to your Service.
@Injectable({ providedIn: 'root' })
export class FeatureFlagService implements FeatureFlagRoutesService {
// ...
}
- Add
getFeatureRoutes()
method and return yourFeatureFlagRoutes
@Injectable({ providedIn: 'root' })
export class FeatureFlagService implements FeatureFlagRoutesService {
// Get current user id
private readonly userId$: Observable<number> = this.getUserId();
constructor(private readonly httpClient: HttpClient) {}
/** Set additional routes using Service */
getFeatureRoutes(): FeatureFlagRoutes {
return [
{
path: 'api-example',
loadChildren: () => import('api-feature-flag-off.module').then((m) => m.ApiFeatureFlagOffModule),
alternativeLoadChildren: () => import('api-feature-flag-on.module').then((m) => m.ApiFeatureFlagOnModule),
featureFlag: () => this.showFeature(), // Function that returns Observable<boolean>
},
];
}
/** Determine showing feature based on user id and API response */
showFeature(): Observable<boolean> {
// Use current user id
return this.userId$.pipe(
switchMap((userId) => {
// Make specific request for that user
return this.httpClient.get<UserStatus>('some/api');
}),
map((userStatus) => {
// Check if we want to turn feature flag on or not
return userStatus.authorized;
}),
// Replay results until user id changes if you only want to make the api request once
shareReplay({ bufferSize: 1, refCount: true }),
);
}
}
Demo and library is managed using Nx.
Before adding any new feature or a fix, make sure to open an issue first :)
- Make sure to use the expected node/npm versions
node -v # v14.17.1
npm -v # 6.14.13
If you have the wrong versions, I suggest using nvm or volta for node version management.
- Clone the project and install dependencies
git clone https://github.com/m-thompson-code/ngx-feature-flag-router.git
npm install
- Create a new branch
git checkout -b feature/some-feature
- Add tests and make sure demo and library jest / cypress tests pass
npm run test # both demo and ngx-feature-flag-router lib
or
npm run test:demo # only demo
npm run test:lib # only ngx-feature-flag-router lib
You can also run jest tests separately
npm run jest:demo # only demo jest tests
npm run jest:lib # only ngx-feature-flag-router lib jest tests
and cypress tests separately
npm run e2e:demo # only demo cypress tests
npm run e2e:lib # only ngx-feature-flag-router lib cypress tests
- commit > push > create a pull request 🚀