Skip to content

Commit

Permalink
Rework code splitting page per review feedback and add page
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson committed Dec 16, 2018
1 parent 95ff8d5 commit 2338655
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
41 changes: 34 additions & 7 deletions docs/recipes/CodeSplitting.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
---
id: code-splitting
title: Code Splitting
sidebar_label: Code Splitting
hide_title: true
---

# Code Splitting
In large web applications, it is often desirable to split up the app code into multiple JS bundles that can be loaded on-demand. This strategy, called 'code splitting', helps to increase performance of your application by reducing the size of the initial JS payload that must be fetched.

To code split with Redux, we want to be able to dynamically add reducers to the store. The default usage of Redux mandates that a single root reducer should to be passed to the `configureStore` call, which makes dynamically adding new reducers more difficult. Below, we discuss some approaches to solving this problem and reference two libraries that provide this functionality.
To code split with Redux, we want to be able to dynamically add reducers to the store. However, Redux really only has a single root reducer function. This root reducer is normally generated by calling `combineReducers()` or a similar function when the application is initialized. In order to dynamically add more reducers, we need to call that function again to re-generate the root reducer. Below, we discuss some approaches to solving this problem and reference two libraries that provide this functionality.

## Basic Principle
To dynamically add Reducers to a Redux store, there are two approaches that can be taken

### Using `replaceReducer`
The Redux store exposes the `replaceReducer` function, which replaces the current active reducer function with a new reducer function. We can leverage this function to add a reducer as follows:

The Redux store exposes a `replaceReducer` function, which replaces the current active root reducer function with a new root reducer function. Calling it will swap the internal reducer function reference, and dispatch an action to help any newly-added slice reducers initialize themselves:

```js
const newRootReducer = combineReducers({
existingSlice : existingSliceReducer,
newSlice : newSliceReducer,
})

store.replaceReducer(newRootReducer)
```

## Reducer Injection Approaches

### Defining an `injectReducer` function

We will likely want to call `store.replaceReducer()` from anywhere in the application. Because of that, it's helpful
to define a reusable `injectReducer()` function that keeps references to all of the existing slice reducers, and attach
that to the store instance.

```javascript
import { createStore } from 'redux';
Expand Down Expand Up @@ -131,8 +155,11 @@ To add a new reducer, one can now call `store.reducerManager.add("asyncState", a
To remove a reducer, one can now call `store.reducerManager.remove("asyncState")`

## Libraries and Frameworks

There are a few good libraries out there that can help you add the above functionality automatically:
* [`redux-dynamic-reducer`](https://github.com/ioof-holdings/redux-dynamic-reducer)
* This library exposes the `addReducer` function on the Redux store to accomplish the behavior we described above. It also has React bindings which make it easier to add reducers within the React component lifecycle.
* [`redux-dynamic-modules`](https://github.com/Microsoft/redux-dynamic-modules)
* This library introduces the concept of a 'Redux Module', which is a bundle of Redux artifacts (reducers, middleware) that should be dynamically loaded. It also exposes a React higher-order component to load 'modules' when areas of the application come online. Additionally, it has integrations with libraries like `redux-thunk` and `redux-saga` which also help dynamically load their artifacts (thunks, sagas).

* [`redux-dynostore`](https://github.com/ioof-holdings/redux-dynostore):
Provides tools for building dynamic Redux stores, including dynamically adding reducers and sagas, and React bindings to help you add in association with components.
* [`redux-dynamic-modules`](https://github.com/Microsoft/redux-dynamic-modules):
This library introduces the concept of a 'Redux Module', which is a bundle of Redux artifacts (reducers, middleware) that should be dynamically loaded. It also exposes a React higher-order component to load 'modules' when areas of the application come online. Additionally, it has integrations with libraries like `redux-thunk` and `redux-saga` which also help dynamically load their artifacts (thunks, sagas).
* [Redux Ecosystem Links: Reducers - Dynamic Reducer Injection](https://github.com/markerikson/redux-ecosystem-links/blob/master/reducers.md#dynamic-reducer-injection)
1 change: 1 addition & 0 deletions website/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"recipes/implementing-undo-history",
"recipes/isolating-redux-sub-apps",
"recipes/using-immutablejs-with-redux",
"recipes/code-splitting",
{
"type": "subcategory",
"label": "Structuring Reducers",
Expand Down

0 comments on commit 2338655

Please sign in to comment.