0.2.0 • Published 6 years ago

@wertarbyte/module-loader v0.2.0

Weekly downloads
63
License
MIT
Repository
github
Last release
6 years ago

Module Loader

Inspired by Mantrajs this package build upons the idea to modulize and abstract.

See the medium article to get the idea behind this.

It's still in pretty early stages. We use this in a few projects to see if it works. If you have further ideas feel free to submit a PR

Installation

npm i --save @wertarbyte/module-loader

Goal

The goal is to have one single entrance spot where all modules come together. This package provides the "glue" to attach all together.

It will provide various logics for each module:

  • Routes
  • Reducers
  • Redux Actions
  • API calls

The end result could look something like this:

import {createApp} from '@wertarbyte/module-loader';
...

const store = configureStore({}, history);

const context = {
  store,
};

const app = createApp(context);
app.loadModule(Core);
app.loadModule(Home);
app.loadModule(Contact);
app.init();

export default () => (
  <Provider store={store}>
    <MuiThemeProvider theme={theme}>
      <ConnectedRouter history={history}>
        <Switch>
          <Application>{app.routes}</Application>
        </Switch>
      </ConnectedRouter>
    </MuiThemeProvider>
  </Provider>
);

With that everything is handled. Reducers get injected and routes will be stacked to be used later for the rendering pipeline.

There is currently no limitation on how many modules can be loaded.

Usage

configureStore

In order to inject reducers dynamically we need asyncReducers which basically just means a hook for the module loader.

Note how we add asyncReducers in the createReducer method and add them dynamically in store.injectReducer when a new module is loaded.

import {applyMiddleware, combineReducers, compose, createStore} from 'redux';
import {routerMiddleware, routerReducer} from 'react-router-redux';

export const createReducer = asyncReducers =>
  combineReducers({
    routing: routerReducer,
    ...asyncReducers,
  });

export default function(initialState, browserHistory) {
  const routermw = routerMiddleware(browserHistory);
  return createStore(
    createReducer(),
    initialState,
    process.env.NODE_ENV !== 'production' && window.devToolsExtension
      ? compose(applyMiddleware(routermw), window.devToolsExtension())
      : compose(applyMiddleware(routermw)),
  );
}

Module Config

Every module has an index.js in its root to expose the inner parts.

Let's assume our module contact has:

  • actions as an array
  • reducers
  • routes as a function

Module

import {createModule} from '@wertarbyte/module-loader';
import * as actions from './actions';
import reducers from './reducers';
import routes from './routes';

export default createModule('contact', { actions, reducers, routes });

Entry File

Load modules, init the app and mount your modules to get started

import {createApp} from '@wertarbyte/module-loader';
import configureStore, {createReducer} from './configureStore';
...

const store = configureStore({}, history);


const app = createApp({
  store,
  replaceReducers: (reducers) => {
    store.replaceReducer(createReducer(reducers));
  },
});
app.loadModule(Core);
app.loadModule(Home);
app.loadModule(Contact);
app.init();

export default () => (
  <Provider store={store}>
    <MuiThemeProvider theme={theme}>
      <ConnectedRouter history={history}>
        <Switch>
          <Application>{app.routes}</Application>
        </Switch>
      </ConnectedRouter>
    </MuiThemeProvider>
  </Provider>
);

API

Creation Methods

NameTypeDescription
createAppfuncReturns an app instance to load modules.
createModulefuncReturns an module instance for creating a new module.

App class

NameTypeDescription
checkForInitfuncThrows error message if app is already initialized.
initfuncSet flag that app is initialized.
loadModulefuncLoads a module.

Module class

NameTypeDefaultDescription
actionsobject{}Defines the actions.
apiobject{}Defines the API calls.
loadedbooleanfalseDefines if the module has already been loaded once.
name*stringDefines a unique name.
reducersfuncnullDefines the reducers.
routesfuncnullDefines the routes.
0.2.0

6 years ago

0.1.4

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago