Code Monkey home page Code Monkey logo

m-thompson-code / ngx-feature-flag-router Goto Github PK

View Code? Open in Web Editor NEW
11.0 1.0 0.0 1.89 MB

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.

Home Page: https://m-thompson-code.github.io/ngx-feature-flag-router/

License: MIT License

TypeScript 76.94% JavaScript 3.39% SCSS 14.43% HTML 5.22% Shell 0.03%
angular lazy-loading loadchildren monorepo nx-workspace router typescript

ngx-feature-flag-router's Introduction

NgxFeatureFlagRouter

GitHub package.json version GitHub npm npm Website Custom badge

Demo

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 Major Version Support

Angular Version Support
9 ✅ Yes
10 ✅ Yes
11 ✅ Yes
12 ✅ Yes
13 ✅ Yes
14 Mostly. Support for loadComponent coming soon

Installation

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

How to Use

  1. Replace RouterModule.forChild() with FeatureFlagRouterModule.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 {}
  1. Add alternativeLoadChildren and featureFlag to conditional lazy-load alternative module when featureFlag returns true

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
    },
];

How to Use Services / API

  1. Add your Service ( MyService ) as the second argument of FeatureFlagRouterModule.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 {}
  1. Add implements FeatureFlagRoutesService to your Service.
@Injectable({ providedIn: 'root' })
export class FeatureFlagService implements FeatureFlagRoutesService {
    // ...
}
  1. Add getFeatureRoutes() method and return your FeatureFlagRoutes
@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 }),
        );
    }
}

Mono Repo

Demo and library is managed using Nx.

Contributing

Before adding any new feature or a fix, make sure to open an issue first :)

  1. 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.

  1. Clone the project and install dependencies
git clone https://github.com/m-thompson-code/ngx-feature-flag-router.git
npm install
  1. Create a new branch
git checkout -b feature/some-feature
  1. 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
  1. commit > push > create a pull request 🚀

ngx-feature-flag-router's People

Contributors

m-thompson-code avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.