Widgets Application

Let us build a React + Redux application using redux-dynamic-modules to demonstrate code splitting.

We will split not just the React components but also Redux artifacts.

We will bundle related Actions, Reducers and Middlewares as modules. We will only load a specific module when it is needed (e.g. a component mounts). We will unload the module when it is no longer needed (e.g. a component un-mounts).

Without using redux-dynamic-modules we have to pass all reducers and middlewares when initializing the store, even when they are not needed.

Our React application has multiple widgets, which will be loaded on demand when they are needed. One widget will display the top stories from Hacker News and the other will display the current weather in Seattle. They are only mounted when the corresponding checkbox is checked.

The full source code for this application can be found on GitHub.

Widgets

The application is split in following parts

The main component renders the check boxes and mounts the Widgets based on the checkbox state.

Main component

2. Two Widgets, one for displaying top 5 stories on Hacker news, and the other displaying current weather in Seattle.

Just for fun and to show the extensibility of redux-dynamic-modules , each widget uses a different middleware. The HN widget uses redux-thunk and Weather widget uses redux-saga . In your app you may want to use only one kind of middleware for consistency.

Hacker news widget

Building the Application

Let us get started. I will be copy-pasting screen shots for the code snippets, you can look at the code at GitHub rather than copy-pasting it from here.

The app is created using create-react-app .

create-react-app

It has following dependencies, we will talk about them as we use them in the code.

Dependencies

The code is organized in following folders, each widget has two folders. The component contains the react component and the redux folder contains the Redux module, actions, reducer and middleware (sagas).

Folder structure

The App.js renders the check boxes and the Widgets based on the state of the check boxes. We have following imports in App.js

Imports in App.js

We configure the module store in the constructor of App.js

Configure the store in constructor

We pass the store to Provider in react-redux

Use the store in the provider

Then, we render the widget using react-loadable , which ensures that the scripts for the widget will load only when we render the widget.

use react-loadable

Let us look at module definitions for the widgets.

Hacker news module

Weather Module

Connect the component to the module

Connect the component to module

An we are done! We write our reducers, actions and middleware as we used to before using redux-dynamic-modules , they need not be refactored when you decide to use redux-dynamic-modules . This gives you the flexibility to gradually create modules and adopt the library.

Summary

Let us summarize what we did.

We used configureStore from redux-dynamic-modules to configure the store. We optionally passed middleware extensions for the middleware used in the app e.g. redux-thunk or redux-saga . We defined a JSON object that has a unique id, reducer map, any initial or final actions, middlewares and sagas. We wrapped our Connected component in DynamicModuleLoader provided by redux-dynamic-modules to connect the modules to our component.

I hope you find the library useful, it is battle tested and production ready. We are using it to build new experiences in Azure DevOps. Please leave a comment if you have any questions, or open issues on GitHub if you have any feature requests or feedback.

If you are like me, you would want to learn more about internals of the library before using it, my co-author Alex Bettadapur wrote another post which goes in little bit more details, take a look it here.