Best Practice: Remove `@ngrx/store-devtools` in production

If you are using `@ngrx/store-devtools` in your application, you should remove it in production.

In production @ngrx/store-devtools should be completly removed from the bundle.
Let's see an example:

Start a new angular application

npx @angular/cli@latest new ngrx-remove-devtools --style css --routing false --minimal

Install @ngrx/store and @ngrx/store-devtools

cd ngrx-remove-devtools
npx ng add @ngrx/store --skip-confirmation
npx ng add @ngrx/store-devtools@latest --skip-confirmation

Populate your state

app.module.ts
@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    StoreModule.forRoot(
      {
        counter: () => 0,
      },
      {}
    ),
    StoreDevtoolsModule.instrument({maxAge: 25, logOnly: !isDevMode()}),
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
Read-only

Examine the state

If you have the Redux dev tools installed you can now examine your state.

ng serve

Redux dev tools

Problem examine state in Production

It's best to disable redux dev tools in production.

npx ng build
cd dist/ngrx-remove-devtools
npx http-server

Redux dev tools still works in production

Solution 1

If on production do not place the StoreDevtoolsModule.instrument in the imports array.

npx ng generate environments

add a production key to the environments files:

src/environments/environment.development.ts
export const environment = {
  production: false,
};
Read-only
src/environments/environment.ts
export const environment = {
  production: true,
};
Read-only
app.module.ts
import {environment} from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    StoreModule.forRoot(
      {
        counter: () => 0,
      },
      {}
    ),
    !environment.production ? StoreDevtoolsModule.instrument({maxAge: 25, logOnly: !isDevMode()}) : [],
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
Read-only

Problem

@ngrx/store-devtools is still in the bundle

npx ng build --source-map
npx source-map-explorer dist/ngrx-remove-devtools/main.4a92d461e97ce051.js

source-map-explorer

it will add around 16kb of unused code to your bundle.

Replace app.module.ts

We can achieve the same result with fileReplacement.

src/app/imports.common.ts
import {BrowserModule} from '@angular/platform-browser';
import {StoreModule} from '@ngrx/store';

export const commonImports = [
  BrowserModule,
  StoreModule.forRoot(
    {
      counter: () => 0,
    },
    {}
  ),
];
Read-only
src/app/imports.development.ts
import {StoreDevtoolsModule} from '@ngrx/store-devtools';
import {commonImports} from './imports.common';
import {isDevMode} from '@angular/core';

export const imports = [
	...commonImports, 
	StoreDevtoolsModule.instrument({maxAge: 25, logOnly: !isDevMode()})
];
Read-only
src/app/imports.ts
import {commonImports} from './imports.common';

export const imports = [...commonImports];
Read-only
src/app/app.module.ts
import {NgModule} from '@angular/core';
import {AppComponent} from './app.component';
import {imports} from './imports';

@NgModule({
  declarations: [AppComponent],
  imports: [...imports],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
Read-only

@ngrx/store-devtools is completly removed from the bundle.
The source code is available here.