Plugins Architecture
MapStore fully embraces both ReactJS and Redux concepts, enhancing them with the plugin concept.
A plugin in MapStore is a smart ReactJS component that is:
- connected to a Redux store, so that some properties are automatically wired to the standard MapStore state
- wired to standard actions for common events
In addition a plugin:
- declares some reducers that need to be added to the Redux store, if needed
- declares some epics that need to be added to the redux-observable middleare, if needed
- is fully configurable to be easily customized to a certain level
Building an application using plugins
To use plugins you need to:
- declare available (required) plugins, properly requiring them from the root application component
- load / declare plugins configuration
- create a store that dynamically includes plugins required reducers
- use a PluginsContainer component as the container for your plugins enabled application slice (can be the whole application or just a part of it)
Declare available plugins
Create a plugins.js file where you declare all the needed plugins:
plugins.js:
1 2 3 4 5 6 | module.exports = { plugins: { MyPlugin: require('../plugins/My') }, requires: {} }; |
Load / Create plugins configuration object
Use pluginsConfig.json to configure your plugins.
pluginsConfig.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { ... "standard": [ { "name": "Map", "cfg": { "zoomControl": false, "tools": ["locate"] } }, ... ], ... } |
Declare a plugins compatible Redux Store
Create a store that properly initializes plugins reducers and epics (see standardStore.js) :
store.js:
1 2 3 4 5 6 7 8 9 | const {combineReducers} = require('../utils/PluginsUtils'); const {createDebugStore} = require('../utils/DebugUtils'); module.exports = (plugins) => { const allReducers = combineReducers(plugins, { ... }); return createDebugStore(allReducers, {}); }; |
Use a PluginContainer to render all your plugins
In the root application component require plugins declaration and configuration and use them to initialize both the store and a PluginsContainer (see our PluginContainer.jsx):
App.jsx:
1 2 3 4 5 6 7 8 | const {pluginsDef} = require('./plugins.js'); const pluginsCfg = require('./pluginsConfig.json'); const store = require('./store')(pluginsDef); const plugins = PluginsUtils.getPlugins(pluginsDef); ReactDOM.render(<PluginsContainer plugins={plugins} mode="standard" pluginsConfig={pluginsCfg}/>, ...container...); |
Developing a plugin
An example is better than a thousand words:
My.jsx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // this is a dumb component const MyComponent = require('../components/MyComponent'); const {connect} = require('../utils/PluginsUtils'); // let's wire it to state and actions const MyPlugin = connect((state) => ({ myproperty: state.myreducer.property }), { myaction })(MyComponent); // let's export the plugin and a set of required reducers const myreducer = require('../reducers/myreducer'); module.exports = { MyPlugin, reducers: {myreducer} }; |
The Plugins Example Application
The example shows the plugins infrastructure power in an interactive way.
The UI allows to add / remove plugins from the base applications, and to configure them using a JSON object with plugins configuration properties.