Bug 1465455 - extract middleware and enhancer functions from store.js; r=nchevobbe
authorJan Odvarko <odvarko@gmail.com>
Fri, 08 Jun 2018 08:21:32 +0200
changeset 421887 5eb98e41ebd9776cdbe2fd7616676d87f78c10d3
parent 421886 1f16a2ff45ab492025e42afb8122f4d52cb24c0b
child 421931 e0595117ff5bda3a63a72ad7b3b8754fec4fb4f0
child 421932 bf083b3c02c76bca8786d8e0330e07ddd03c5901
push id34108
push useraiakab@mozilla.com
push dateFri, 08 Jun 2018 09:54:54 +0000
treeherdermozilla-central@5eb98e41ebd9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1465455
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1465455 - extract middleware and enhancer functions from store.js; r=nchevobbe MozReview-Commit-ID: L9bhjZD028G
devtools/client/webconsole/enhancers/actor-releaser.js
devtools/client/webconsole/enhancers/batching.js
devtools/client/webconsole/enhancers/css-error-reporting.js
devtools/client/webconsole/enhancers/message-cache-clearing.js
devtools/client/webconsole/enhancers/moz.build
devtools/client/webconsole/enhancers/net-provider.js
devtools/client/webconsole/middleware/history-persistence.js
devtools/client/webconsole/middleware/moz.build
devtools/client/webconsole/middleware/thunk.js
devtools/client/webconsole/moz.build
devtools/client/webconsole/store.js
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/enhancers/actor-releaser.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/enhancers/actor-releaser.js
@@ -1,169 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
 const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
   MESSAGES_ADD,
   MESSAGES_CLEAR,
   PRIVATE_MESSAGES_CLEAR,
   REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
 } = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
-
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
-
-/**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
- */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
-
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
 
 /**
  * This enhancer is responsible for releasing actors on the backend.
  * When messages with arguments are removed from the store we should also
  * clean up the backend.
  */
 function enableActorReleaser(hud) {
   return next => (reducer, initialState, enhancer) => {
@@ -187,196 +38,19 @@ function enableActorReleaser(hud) {
       return state;
     }
 
     return next(releaseActorsEnhancer, initialState, enhancer);
   };
 }
 
 /**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
  * Helper function for releasing backend actors.
  */
 function releaseActors(removedActors, proxy) {
   if (!proxy) {
     return;
   }
 
   removedActors.forEach(actor => proxy.releaseActor(actor));
 }
 
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = enableActorReleaser;
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/enhancers/batching.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/enhancers/batching.js
@@ -1,146 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
-const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
 const {
   BATCH_ACTIONS
 } = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
-  MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
-} = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
-
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
-
-/**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
- */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
 
 /**
  * A enhancer for the store to handle batched actions.
  */
 function enableBatching() {
   return next => (reducer, initialState, enhancer) => {
     function batchingReducer(state, action) {
       switch (action.type) {
@@ -155,228 +26,9 @@ function enableBatching() {
       enhancer = initialState;
       initialState = undefined;
     }
 
     return next(batchingReducer, initialState, enhancer);
   };
 }
 
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = enableBatching;
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/enhancers/css-error-reporting.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/enhancers/css-error-reporting.js
@@ -1,200 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
 const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
-  MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
   INITIALIZE,
   FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
 } = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
-
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
-
-/**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
- */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
-
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
 
 /**
  * This is responsible for ensuring that error reporting is enabled if the CSS
  * filter is toggled on.
  */
 function ensureCSSErrorReportingEnabled(hud) {
   return next => (reducer, initialState, enhancer) => {
     function ensureErrorReportingEnhancer(state, action) {
@@ -214,169 +32,9 @@ function ensureCSSErrorReportingEnabled(
         proxy.target.activeTab.ensureCSSErrorReportingEnabled();
       }
       return state;
     }
     return next(ensureErrorReportingEnhancer, initialState, enhancer);
   };
 }
 
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = ensureCSSErrorReportingEnabled;
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/enhancers/message-cache-clearing.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/enhancers/message-cache-clearing.js
@@ -1,317 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
 const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
   MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
 } = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
-
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
-
-/**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
- */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
-
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
 
 /**
  * This enhancer is responsible for clearing the messages caches using the
  * webconsoleClient when the user clear the messages (either by direct UI action, or via
  * `console.clear()`).
  */
 function enableMessagesCacheClearing(hud) {
   return next => (reducer, initialState, enhancer) => {
@@ -325,58 +25,9 @@ function enableMessagesCacheClearing(hud
       }
       return state;
     }
 
     return next(messagesCacheClearingEnhancer, initialState, enhancer);
   };
 }
 
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = enableMessagesCacheClearing;
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/enhancers/moz.build
@@ -0,0 +1,12 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DevToolsModules(
+    'actor-releaser.js',
+    'batching.js',
+    'css-error-reporting.js',
+    'message-cache-clearing.js',
+    'net-provider.js',
+)
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/enhancers/net-provider.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/enhancers/net-provider.js
@@ -1,228 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
-const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
+const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
+
 const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
-  MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
-} = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
+  getAllNetworkMessagesUpdateById,
+} = require("devtools/client/webconsole/selectors/messages");
+
 const {
   getMessage,
   getAllMessagesUiById,
 } = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
+
 const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
-
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
-
-/**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
- */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
-
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
+  MESSAGE_OPEN,
+  NETWORK_MESSAGE_UPDATE,
+} = require("devtools/client/webconsole/constants");
 
 /**
  * This enhancer is responsible for fetching HTTP details data
  * collected by the backend. The fetch happens on-demand
  * when the user expands network log in order to inspect it.
  *
  * This way we don't slow down the Console logging by fetching.
  * unnecessary data over RDP.
@@ -303,80 +104,9 @@ function enableNetProvider(hud) {
 
       return newState;
     }
 
     return next(netProviderEnhancer, initialState, enhancer);
   };
 }
 
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = enableNetProvider;
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/middleware/history-persistence.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/middleware/history-persistence.js
@@ -1,352 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
 const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
-  MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
   APPEND_TO_HISTORY,
   CLEAR_HISTORY,
 } = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
+
 const historyActions = require("devtools/client/webconsole/actions/history");
 
 loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
 
 /**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
- */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
-
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
  * History persistence middleware is responsible for loading
  * and maintaining history of executed expressions in JSTerm.
  */
 function historyPersistenceMiddleware(store) {
   let historyLoaded = false;
   asyncStorage.getItem("webConsoleHistory").then(value => {
     if (Array.isArray(value)) {
       store.dispatch(historyActions.historyLoaded(value));
@@ -371,12 +43,9 @@ function historyPersistenceMiddleware(st
       const state = store.getState();
       asyncStorage.setItem("webConsoleHistory", state.history.entries);
     }
 
     return res;
   };
 }
 
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = historyPersistenceMiddleware;
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/middleware/moz.build
@@ -0,0 +1,9 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DevToolsModules(
+    'history-persistence.js',
+    'thunk.js',
+)
copy from devtools/client/webconsole/store.js
copy to devtools/client/webconsole/middleware/thunk.js
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/middleware/thunk.js
@@ -1,382 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
-const {
-  applyMiddleware,
-  compose,
-  createStore
-} = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
-  MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
-} = require("devtools/client/webconsole/constants");
-const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
-
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
-
 /**
- * Create and configure store for the Console panel. This is the place
- * where various enhancers and middleware can be registered.
+ * A middleware that allows thunks (functions) to be dispatched.
  */
-function configureStore(hud, options = {}) {
-  const prefsService = getPrefsService(hud);
-  const {
-    getBoolPref,
-    getIntPref,
-  } = prefsService;
-
-  const logLimit = options.logLimit
-    || Math.max(getIntPref("devtools.hud.loglimit"), 1);
-  const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE);
-  const jstermCodeMirror = getBoolPref(PREFS.FEATURES.JSTERM_CODE_MIRROR);
-  const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT);
-
-  const initialState = {
-    prefs: PrefState({
-      logLimit,
-      sidebarToggle,
-      jstermCodeMirror,
-      historyCount,
-    }),
-    filters: FilterState({
-      error: getBoolPref(PREFS.FILTER.ERROR),
-      warn: getBoolPref(PREFS.FILTER.WARN),
-      info: getBoolPref(PREFS.FILTER.INFO),
-      debug: getBoolPref(PREFS.FILTER.DEBUG),
-      log: getBoolPref(PREFS.FILTER.LOG),
-      css: getBoolPref(PREFS.FILTER.CSS),
-      net: getBoolPref(PREFS.FILTER.NET),
-      netxhr: getBoolPref(PREFS.FILTER.NETXHR),
-    }),
-    ui: UiState({
-      filterBarVisible: getBoolPref(PREFS.UI.FILTER_BAR),
-      networkMessageActiveTabId: "headers",
-      persistLogs: getBoolPref(PREFS.UI.PERSIST),
-    })
-  };
-
-  // Prepare middleware.
-  const middleware = applyMiddleware(
-    thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
-  );
-
-  return createStore(
-    createRootReducer(),
-    initialState,
-    compose(
-      middleware,
-      enableActorReleaser(hud),
-      enableBatching(),
-      enableNetProvider(hud),
-      enableMessagesCacheClearing(hud),
-      ensureCSSErrorReportingEnabled(hud),
-    )
-  );
-}
-
 function thunk(options = {}, { dispatch, getState }) {
   return next => action => {
     return (typeof action === "function")
       ? action(dispatch, getState, options)
       : next(action);
   };
 }
 
-function createRootReducer() {
-  return function rootReducer(state, action) {
-    // We want to compute the new state for all properties except
-    // "messages" and "history". These two reducers are handled
-    // separately since they are receiving additional arguments.
-    const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
-      if (key !== "messages" && key !== "history") {
-        res[key] = reducer(state[key], action);
-      }
-      return res;
-    }, {});
-
-    // Pass prefs state as additional argument to the history reducer.
-    newState.history = reducers.history(state.history, action, newState.prefs);
-
-    return Object.assign(newState, {
-      // specifically pass the updated filters and prefs state as additional arguments.
-      messages: reducers.messages(
-        state.messages,
-        action,
-        newState.filters,
-        newState.prefs,
-      ),
-    });
-  };
-}
-
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
-// Provide the store factory for test code so that each test is working with
-// its own instance.
-module.exports.configureStore = configureStore;
-
+module.exports = thunk;
--- a/devtools/client/webconsole/moz.build
+++ b/devtools/client/webconsole/moz.build
@@ -2,16 +2,18 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'actions',
     'components',
+    'enhancers',
+    'middleware',
     'reducers',
     'selectors',
     'test',
     'utils',
 ]
 DevToolsModules(
     'console-commands.js',
     'constants.js',
--- a/devtools/client/webconsole/store.js
+++ b/devtools/client/webconsole/store.js
@@ -1,50 +1,42 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
-const {FilterState} = require("devtools/client/webconsole/reducers/filters");
-const {PrefState} = require("devtools/client/webconsole/reducers/prefs");
-const {UiState} = require("devtools/client/webconsole/reducers/ui");
+// State
+const { FilterState } = require("devtools/client/webconsole/reducers/filters");
+const { PrefState } = require("devtools/client/webconsole/reducers/prefs");
+const { UiState } = require("devtools/client/webconsole/reducers/ui");
+
+// Redux
 const {
   applyMiddleware,
   compose,
   createStore
 } = require("devtools/client/shared/vendor/redux");
-const {
-  BATCH_ACTIONS
-} = require("devtools/client/shared/redux/middleware/debounce");
-const {
-  MESSAGE_OPEN,
-  MESSAGES_ADD,
-  MESSAGES_CLEAR,
-  PRIVATE_MESSAGES_CLEAR,
-  REMOVED_ACTORS_CLEAR,
-  NETWORK_MESSAGE_UPDATE,
-  PREFS,
-  INITIALIZE,
-  FILTER_TOGGLE,
-  APPEND_TO_HISTORY,
-  CLEAR_HISTORY,
-} = require("devtools/client/webconsole/constants");
+
+// Prefs
+const { PREFS } = require("devtools/client/webconsole/constants");
+const { getPrefsService } = require("devtools/client/webconsole/utils/prefs");
+
+// Reducers
 const { reducers } = require("./reducers/index");
-const {
-  getMessage,
-  getAllMessagesUiById,
-} = require("devtools/client/webconsole/selectors/messages");
-const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
-const {
-  getAllNetworkMessagesUpdateById,
-} = require("devtools/client/webconsole/selectors/messages");
-const {getPrefsService} = require("devtools/client/webconsole/utils/prefs");
-const historyActions = require("devtools/client/webconsole/actions/history");
+
+// Middleware
+const historyPersistence = require("./middleware/history-persistence");
+const thunk = require("./middleware/thunk");
 
-loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
+// Enhancers
+const enableBatching = require("./enhancers/batching");
+const enableActorReleaser = require("./enhancers/actor-releaser");
+const ensureCSSErrorReportingEnabled = require("./enhancers/css-error-reporting");
+const enableNetProvider = require("./enhancers/net-provider");
+const enableMessagesCacheClearing = require("./enhancers/message-cache-clearing");
 
 /**
  * Create and configure store for the Console panel. This is the place
  * where various enhancers and middleware can be registered.
  */
 function configureStore(hud, options = {}) {
   const prefsService = getPrefsService(hud);
   const {
@@ -80,41 +72,33 @@ function configureStore(hud, options = {
       networkMessageActiveTabId: "headers",
       persistLogs: getBoolPref(PREFS.UI.PERSIST),
     })
   };
 
   // Prepare middleware.
   const middleware = applyMiddleware(
     thunk.bind(null, {prefsService}),
-    historyPersistenceMiddleware,
+    historyPersistence,
   );
 
   return createStore(
     createRootReducer(),
     initialState,
     compose(
       middleware,
       enableActorReleaser(hud),
       enableBatching(),
       enableNetProvider(hud),
       enableMessagesCacheClearing(hud),
       ensureCSSErrorReportingEnabled(hud),
     )
   );
 }
 
-function thunk(options = {}, { dispatch, getState }) {
-  return next => action => {
-    return (typeof action === "function")
-      ? action(dispatch, getState, options)
-      : next(action);
-  };
-}
-
 function createRootReducer() {
   return function rootReducer(state, action) {
     // We want to compute the new state for all properties except
     // "messages" and "history". These two reducers are handled
     // separately since they are receiving additional arguments.
     const newState = [...Object.entries(reducers)].reduce((res, [key, reducer]) => {
       if (key !== "messages" && key !== "history") {
         res[key] = reducer(state[key], action);
@@ -132,251 +116,12 @@ function createRootReducer() {
         action,
         newState.filters,
         newState.prefs,
       ),
     });
   };
 }
 
-/**
- * A enhancer for the store to handle batched actions.
- */
-function enableBatching() {
-  return next => (reducer, initialState, enhancer) => {
-    function batchingReducer(state, action) {
-      switch (action.type) {
-        case BATCH_ACTIONS:
-          return action.actions.reduce(batchingReducer, state);
-        default:
-          return reducer(state, action);
-      }
-    }
-
-    if (typeof initialState === "function" && typeof enhancer === "undefined") {
-      enhancer = initialState;
-      initialState = undefined;
-    }
-
-    return next(batchingReducer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for releasing actors on the backend.
- * When messages with arguments are removed from the store we should also
- * clean up the backend.
- */
-function enableActorReleaser(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function releaseActorsEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const type = action.type;
-      const proxy = hud ? hud.proxy : null;
-      if (
-        proxy &&
-        ([MESSAGES_ADD, MESSAGES_CLEAR, PRIVATE_MESSAGES_CLEAR].includes(type))
-      ) {
-        releaseActors(state.messages.removedActors, proxy);
-
-        // Reset `removedActors` in message reducer.
-        state = reducer(state, {
-          type: REMOVED_ACTORS_CLEAR
-        });
-      }
-
-      return state;
-    }
-
-    return next(releaseActorsEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This is responsible for ensuring that error reporting is enabled if the CSS
- * filter is toggled on.
- */
-function ensureCSSErrorReportingEnabled(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function ensureErrorReportingEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      state = reducer(state, action);
-      if (!state.filters.css) {
-        return state;
-      }
-
-      const cssFilterToggled =
-        action.type == FILTER_TOGGLE && action.filter == "css";
-      if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
-      }
-      return state;
-    }
-    return next(ensureErrorReportingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for fetching HTTP details data
- * collected by the backend. The fetch happens on-demand
- * when the user expands network log in order to inspect it.
- *
- * This way we don't slow down the Console logging by fetching.
- * unnecessary data over RDP.
- */
-function enableNetProvider(hud) {
-  let dataProvider;
-  return next => (reducer, initialState, enhancer) => {
-    function netProviderEnhancer(state, action) {
-      const proxy = hud ? hud.proxy : null;
-      if (!proxy) {
-        return reducer(state, action);
-      }
-
-      const actions = {
-        updateRequest: (id, data, batch) => {
-          proxy.dispatchRequestUpdate(id, data);
-        }
-      };
-
-      // Data provider implements async logic for fetching
-      // data from the backend. It's created the first
-      // time it's needed.
-      if (!dataProvider && proxy.webConsoleClient) {
-        dataProvider = new DataProvider({
-          actions,
-          webConsoleClient: proxy.webConsoleClient
-        });
-
-        // /!\ This is terrible, but it allows ResponsePanel to be able to call
-        // `dataProvider.requestData` to fetch response content lazily.
-        // `proxy.networkDataProvider` is put by WebConsoleOutputWrapper on
-        // `serviceContainer` which allow NetworkEventMessage to expose requestData on
-        // the fake `connector` object it hands over to ResponsePanel.
-        proxy.networkDataProvider = dataProvider;
-      }
-
-      const type = action.type;
-      const newState = reducer(state, action);
-
-      // If network message has been opened, fetch all HTTP details
-      // from the backend. It can happen (especially in test) that
-      // the message is opened before all network event updates are
-      // received. The rest of updates will be handled below, see:
-      // NETWORK_MESSAGE_UPDATE action handler.
-      if (type == MESSAGE_OPEN) {
-        const updates = getAllNetworkMessagesUpdateById(newState);
-        const message = updates[action.id];
-        if (message && !message.openedOnce && message.source == "network") {
-          dataProvider.onNetworkEvent(message);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType: updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      // Process all incoming HTTP details packets. Note that
-      // Network event update packets are sent in batches from:
-      // `WebConsoleOutputWrapper.dispatchMessageUpdate` using
-      // NETWORK_MESSAGE_UPDATE action.
-      // Make sure to call `dataProvider.onNetworkEventUpdate`
-      // to fetch data from the backend.
-      if (type == NETWORK_MESSAGE_UPDATE) {
-        const actor = action.response.networkInfo.actor;
-        const open = getAllMessagesUiById(state).includes(actor);
-        if (open) {
-          const message = getMessage(state, actor);
-          message.updates.forEach(updateType => {
-            dataProvider.onNetworkEventUpdate({
-              packet: { updateType },
-              networkInfo: message,
-            });
-          });
-        }
-      }
-
-      return newState;
-    }
-
-    return next(netProviderEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * This enhancer is responsible for clearing the messages caches using the
- * webconsoleClient when the user clear the messages (either by direct UI action, or via
- * `console.clear()`).
- */
-function enableMessagesCacheClearing(hud) {
-  return next => (reducer, initialState, enhancer) => {
-    function messagesCacheClearingEnhancer(state, action) {
-      state = reducer(state, action);
-
-      const webConsoleClient = hud && hud.proxy ? hud.proxy.webConsoleClient : null;
-      if (webConsoleClient && action.type === MESSAGES_CLEAR) {
-        webConsoleClient.clearNetworkRequests();
-        webConsoleClient.clearMessagesCache();
-      }
-      return state;
-    }
-
-    return next(messagesCacheClearingEnhancer, initialState, enhancer);
-  };
-}
-
-/**
- * Helper function for releasing backend actors.
- */
-function releaseActors(removedActors, proxy) {
-  if (!proxy) {
-    return;
-  }
-
-  removedActors.forEach(actor => proxy.releaseActor(actor));
-}
-
-/**
- * History persistence middleware is responsible for loading
- * and maintaining history of executed expressions in JSTerm.
- */
-function historyPersistenceMiddleware(store) {
-  let historyLoaded = false;
-  asyncStorage.getItem("webConsoleHistory").then(value => {
-    if (Array.isArray(value)) {
-      store.dispatch(historyActions.historyLoaded(value));
-    }
-    historyLoaded = true;
-  }, err => {
-    historyLoaded = true;
-    console.error(err);
-  });
-
-  return next => action => {
-    const res = next(action);
-
-    const triggerStoreActions = [
-      APPEND_TO_HISTORY,
-      CLEAR_HISTORY,
-    ];
-
-    // Save the current history entries when modified, but wait till
-    // entries from the previous session are loaded.
-    if (historyLoaded && triggerStoreActions.includes(action.type)) {
-      const state = store.getState();
-      asyncStorage.setItem("webConsoleHistory", state.history.entries);
-    }
-
-    return res;
-  };
-}
-
 // Provide the store factory for test code so that each test is working with
 // its own instance.
 module.exports.configureStore = configureStore;