Redux: Make applyMiddleware ignore falsy arguments

Created on 19 Aug 2015  路  2Comments  路  Source: reduxjs/redux

This would allow us to write

const createStoreWithMiddleware = applyMiddleware(
  ... other middleware ...
  DEBUG && logger,
)(createStore);

instead of

const middleware = [
  ... other middleware ...
  DEBUG && logger,
].filter(Boolean);
const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);

fcomb/redux-logger#6

docs question

Most helpful comment

I thought about this, but then this makes it too easy to do runtime checking as you describe which is actually an anti-pattern because you still bundle the code you don't use.

The proper solution is something like

let middleware = [a, b];

if (process.env.NODE_ENV !== 'production') {
  let c = require('something-for-dev');
  let d = require('something-for-dev-2');
  middleware = [...middleware, c, d];
} else {
  let e = require('something-for-prod');
  let f = require('something-for-prod-2');
  middleware = [...middleware, e, f];
}

const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);

Note that require calls are _inside_ the if parameterized by process.env.NODE_ENV. If your build tool (Webpack, Browserify, etc) supports envifying, it will replace if (process.env.NODE_ENV !== 'production') with if (false) in production, and development-only middleware will not go into the production build. This is especially important for more complex middleware and store enhancers like Redux DevTools that can increase the bundle size significantly if you're not careful.

This information is a good candidate for inclusion in docs, so if anybody cares to make a PR, I'd be happy to accept it.

All 2 comments

I thought about this, but then this makes it too easy to do runtime checking as you describe which is actually an anti-pattern because you still bundle the code you don't use.

The proper solution is something like

let middleware = [a, b];

if (process.env.NODE_ENV !== 'production') {
  let c = require('something-for-dev');
  let d = require('something-for-dev-2');
  middleware = [...middleware, c, d];
} else {
  let e = require('something-for-prod');
  let f = require('something-for-prod-2');
  middleware = [...middleware, e, f];
}

const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);

Note that require calls are _inside_ the if parameterized by process.env.NODE_ENV. If your build tool (Webpack, Browserify, etc) supports envifying, it will replace if (process.env.NODE_ENV !== 'production') with if (false) in production, and development-only middleware will not go into the production build. This is especially important for more complex middleware and store enhancers like Redux DevTools that can increase the bundle size significantly if you're not careful.

This information is a good candidate for inclusion in docs, so if anybody cares to make a PR, I'd be happy to accept it.

Uglify eliminates short-circuit clauses just fine. You are right that disabled middleware should not be bundled. My example is then

const createStoreWithMiddleware = applyMiddleware(
  ... other middleware ...
  DEBUG && require('redux-logger').createLogger(),
)(createStore);

as opposed to the current

const middleware = [
  ... other middleware ...
  DEBUG && require('redux-logger').createLogger(),
].filter(Boolean);
const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);

As long as it fits one line, it's fine. But in general I like your approach better.

I'll make a PR to the docs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ilearnio picture ilearnio  路  3Comments

dmitry-zaets picture dmitry-zaets  路  3Comments

elado picture elado  路  3Comments

mickeyreiss-visor picture mickeyreiss-visor  路  3Comments

timdorr picture timdorr  路  3Comments