npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

hmr-redux-mapper

v0.9.1

Published

A tool to scan for redux reducer usage in UI script files so that the reducers needed by a route can be automatically loaded in HMR scenarios

Downloads

3

Readme

hmr-redux-mapper

NPM version Build/Test status

If you have written Redux applications in a hot-module-reloading environment, you have probably written a significant amount of boilerplate code in your routing handler to hot-swap all the Redux reducer and saga modules needed to render each route. Adding new Redux stores to existing shared components requires each route using those shared components to swap in those new stores, but it can be tedious to manually determine exactly which routes end up using these shared components so that this requirement can be satisfied.

Enter hmr-redux-mapper, which is a build tool whose purpose is to eliminate the need to manually specify the Redux components which are needed for hot swapping upon route change. The tool is designed to recursively walk each component in your project, starting at each route container, looking for all the Redux modules that are imported either directly by the route container or by any of its child components. That information is written in a mapping file (reducerMap.js).

You can then use the reduxMapperLoader integration module to automatically hot-swap all the Redux modules needed for a new route without the need to write any boilerplate code in your routing handlers to manually load the necessary modules.

npm install hmr-redux-mapper --save-dev

The following usage instructions are specific to React, and specifically to react-router, but in theory similar principles should apply to other Redux HMR environments where modules need to be swapped on route change.

First, ensure the Redux mapper tool is run early in the build process (before webpack or browserify). If you use npm to perform your build, you can add lines similar to these to the "scripts" section of package.json:

"scripts": {
   ...
   "redux-mapper": "node ./node_modules/hmr-redux-mapper/bin/hmr-redux-mapper",
   "prebuild": "npm run build:clean && npm run redux-mapper",
   ...
},

If you use gulp, grunt, or another build tool, you simply need to ensure that you use the proper methodology for those tools to run hmr-redux-mapper as a node script early in the build process (before webpack or browserify).

The build tool will look for a redux-mapper.json file in the root of your project that specifies some details about the way your project folders are laid out, such as what subfolder paths in your project can potentially contain route-handling components or Redux modules, what kind of filenames your Redux stores are implemented using (e.g., reducer.js, saga.js, etc), and where to output the resulting mapper files. More details on the available build tool configuration options and how to specify them to meet the needs of your project can be found in the API documentation.

Here is an example of the version of the file that is needed to integrate with react-boilerplate:

{
  "config": {
    "basePath": "app",
    "mainAppPath": "utils/request.js",
    "containerPaths": "containers,components",
    "actionFilenames": "actions.js,selectors.js",
    "globalReducersOutputPath": "globalReducerImports.js",
    "ignorePaths": "-spec",
    "reducerMapOutputPath": "reducerMap.js",
    "reduxPaths": "containers",
    "sagaFilename": "sagas.js"
  }
}

Once you have configured the build tool itself, you need to decorate each Redux reducer file with an constant that provides a name for the reducer for mapping purposes:

// this is needed for hmr-redux-mapper to identify the reducer name for this reducer
export const PRM_REDUCER_NAME = 'home';

Finally, remove all the boilerplate code for loading Redux and component modules on route change and replace that code with a handler from reduxMapperLoader that can load the necessary modules by referring to the reducerMap.js generated by the build tool.

Right now, reduxMapperLoader only directly supports react-router. To integrate with react-router, replace any getComponent callbacks inside of your implementation of createRoutes calls to reduxMapperLoader's getComponentFromReduxMapper function.

Consider this example diff showing how to replace boilerplate component loading code with the reduxMapperLoader (this example diff is based on app/routes.js from react-boilerplate):

+import reduxMapperLoader from 'hmr-redux-mapper';
+import reducerMap from './reducerMap';

export default function createRoutes(store) {
   // create reusable async injectors using getAsyncInjectors factory
   const { injectReducer, injectSagas } = getAsyncInjectors(store);

+  const getComponentFromReduxMapper = reduxMapperLoader({
+    store,
+    createReducer,
+    reducerMap,
+    injectReducer,
+    injectSagas,
+    loadModule,
+    errorLoading,
+  });
+
   return [
     {
       path: '/',
       name: 'home',
-      getComponent(nextState, cb) {
-        const importModules = Promise.all([
-          import('containers/HomePage/reducer'),
-          import('containers/HomePage/sagas'),
-          import('containers/HomePage'),
-        ]);
-
-        const renderRoute = loadModule(cb);
-
-        importModules.then(([reducer, sagas, component]) => {
-          injectReducer('home', reducer.default);
-          injectSagas(sagas.default);
-
-          renderRoute(component);
-        });
-
-        importModules.catch(errorLoading);
-      },
+      getComponent: getComponentFromReduxMapper('./containers/HomePage/index.js'),
     }, {
       path: '/features',
       name: 'features',
-      getComponent(nextState, cb) {
-        import('containers/FeaturePage')
-          .then(loadModule(cb))
-          .catch(errorLoading);
-      },
+      getComponent: getComponentFromReduxMapper('./containers/FeaturePage'),
     }, {
       path: '*',
       name: 'notfound',
-      getComponent(nextState, cb) {
-        import('containers/NotFoundPage')
-          .then(loadModule(cb))
-          .catch(errorLoading);
-      },
+      getComponent: getComponentFromReduxMapper('./containers/NotFoundPage'),
     },
   ];
 }

That's right - all you need to do to implement react-router's getComponent call is specify the path to the component! All of the necessary Redux modules and the React component itself will be injected automatically on route change by getCompoenntFromReduxMapper, using the data collected by the build tool.

Don't hesitate to create a pull request. Right now we only offer direct support for npm-built React projects using react-router, and we hope that the community can help integrate this tool with other Redux HMR environments. Any contribution will be greatly appreciated!

(c)2017 Raycom Media, Inc. Released under the MIT license.

MIT