From c11504f5ad70253be375222236d96d27fbd49f30 Mon Sep 17 00:00:00 2001 From: Tim Blakely Date: Mon, 5 Feb 2018 17:55:19 -0800 Subject: [PATCH] fix(StoreDevtools): Do not send full liftedState for application actions (#790) --- modules/store-devtools/src/extension.ts | 35 ++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/modules/store-devtools/src/extension.ts b/modules/store-devtools/src/extension.ts index 088e1d795c..7394673768 100644 --- a/modules/store-devtools/src/extension.ts +++ b/modules/store-devtools/src/extension.ts @@ -10,6 +10,7 @@ import { takeUntil } from 'rxjs/operator/takeUntil'; import { STORE_DEVTOOLS_CONFIG, StoreDevtoolsConfig } from './config'; import { LiftedState } from './reducer'; +import { PerformAction } from './actions'; import { applyOperators } from './utils'; export const ExtensionActionTypes = { @@ -28,11 +29,13 @@ export interface ReduxDevtoolsExtensionConnection { unsubscribe(): void; send(action: any, state: any): void; init(state?: any): void; + error(any: any): void; } export interface ReduxDevtoolsExtensionConfig { features?: object | boolean; name: string | undefined; instanceId: string; + maxAge?: number; } export interface ReduxDevtoolsExtension { @@ -51,6 +54,7 @@ export interface ReduxDevtoolsExtension { export class DevtoolsExtension { private instanceId = `ngrx-store-${Date.now()}`; private devtoolsExtension: ReduxDevtoolsExtension; + private extensionConnection: ReduxDevtoolsExtensionConnection; liftedActions$: Observable; actions$: Observable; @@ -68,7 +72,26 @@ export class DevtoolsExtension { return; } - this.devtoolsExtension.send(null, state, this.config, this.instanceId); + // Check to see if the action requires a full update of the liftedState. + // If it is a simple action generated by the user's app, only send the + // action and the current state (fast). + // + // A full liftedState update (slow: serializes the entire liftedState) is + // only required when: + // a) redux-devtools-extension fires the @@Init action (ignored by + // @ngrx/store-devtools) + // b) an action is generated by an @ngrx module (e.g. @ngrx/effects/init + // or @ngrx/store/update-reducers) + // c) the state has been recomputed due to time-traveling + // d) any action that is not a PerformAction to err on the side of + // caution. + if (action instanceof PerformAction) { + const currentState = state.computedStates[state.currentStateIndex].state; + this.extensionConnection.send(action.action, currentState); + } else { + // Requires full state update; + this.devtoolsExtension.send(null, state, this.config, this.instanceId); + } } private createChangesObservable(): Observable { @@ -77,15 +100,19 @@ export class DevtoolsExtension { } return new Observable(subscriber => { - const connection = this.devtoolsExtension.connect({ + let extensionOptions: ReduxDevtoolsExtensionConfig = { instanceId: this.instanceId, name: this.config.name, features: this.config.features, - }); + }; + if (this.config.maxAge !== false /* support === 0 */) { + extensionOptions.maxAge = this.config.maxAge; + } + const connection = this.devtoolsExtension.connect(extensionOptions); + this.extensionConnection = connection; connection.init(); connection.subscribe((change: any) => subscriber.next(change)); - return connection.unsubscribe; }); }