Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add redux-bundler support for Electrode subapps #1484

Merged
merged 2 commits into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/subapp-pbundle/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const subappWeb = require("subapp-web");
const preact = require("preact");
const FrameworkLib = require("./framework-lib");
const { reduxBundlerLoadSubApp } = require("./redux-bundler");
const { default: AppContext } = require("../browser/app-context");

const { h, Component, render } = preact;
Expand All @@ -16,5 +17,6 @@ module.exports = {
preact,
h,
Component,
reduxBundlerLoadSubApp,
render
};
20 changes: 20 additions & 0 deletions packages/subapp-pbundle/lib/redux-bundler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";

const { registerSubApp } = require("subapp-util");

const shared = require("../dist/shared");

module.exports = {
reduxBundlerLoadSubApp: subapp => {
const extras = {
__redux: true
};

if (!subapp.reduxCreateStore) {
extras._genReduxCreateStore = "subapp";
extras.reduxCreateStore = shared.getReduxCreateStore(subapp);
}

return registerSubApp(Object.assign(extras, subapp));
}
};
2 changes: 2 additions & 0 deletions packages/subapp-pbundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
"jsdom": "^15.2.1",
"preact": "^10.1.1",
"preact-render-to-string": "^5.1.3",
"redux-bundler": "^26.0.0",
"redux-bundler-preact": "^2.0.1",
"run-verify": "^1.2.2"
},
"peerDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions packages/subapp-pbundle/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export { h, Component, render } from "preact";
export { default as AppContext } from "./app-context";

export { FrameworkLib };

export { reduxBundlerLoadSubApp } from "./redux-bundler";
73 changes: 73 additions & 0 deletions packages/subapp-pbundle/src/redux-bundler.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { h, render, hydrate } from "preact";
import { loadSubApp } from "subapp-web";
import { Provider } from 'redux-bundler-preact';
import { setStoreContainer, getReduxCreateStore } from "./shared";

setStoreContainer(typeof window === 'undefined' ? global : window);

//
// client side function to start a subapp with redux-bundler support
//
export function reduxRenderStart(options) {
const store = options._store || options.reduxCreateStore(options.initialState);
const { Component } = options;

if (options.serverSideRendering) {
hydrate(
<Provider store={store}>
<Component />
</Provider>,
options.element
);
} else {
render(
<Provider store={store}>
<Component />
</Provider>,
options.element
);
}

return store;
}

let store;

//
// Load a subapp with redux-bundler support
// info - the subapp's information
//
export function reduxBundlerLoadSubApp(info) {
const renderStart = function(instance, element) {
const initialState = instance._prepared || instance.initialState;
const reduxCreateStore = instance.reduxCreateStore || this.info.reduxCreateStore;
const Component = this.info.StartComponent || this.info.Component;

const store = reduxRenderStart({
_store: instance._store,
initialState,
reduxCreateStore,
Component,
serverSideRendering: instance.serverSideRendering,
element
});

instance._store = store;
return store;
};

const extras = {
__redux: true
};

if (!info.reduxCreateStore) {
extras._genReduxCreateStore = "subapp";
}

return loadSubApp(
Object.assign(extras, info, {
reduxCreateStore: getReduxCreateStore(info)
}),
renderStart
);
}
56 changes: 56 additions & 0 deletions packages/subapp-pbundle/src/shared.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const composeBundles = require("redux-bundler").composeBundles;

//
// - stores can be shared between subapps with reduxShareStore flag
// - if it's true, then a common global store is used
// - if it's a string, then it's use to name a store for sharing.
// - otherwise subapp gets its own private store
// - state sharing is made possible through named reducers
// - each subapp must provide named reducers for states
// - other subapps can then provide the same reducer under the same name
// - all the reducers are then merged into a single object and then combined
// - initial state handling follow these rules
// - the first subapp that loads and initializes wins and all subapps load
// after will use the initial state from it
// - a top level initializer can be specified to do this
//

let shared = {};

function setStoreContainer(container) {
shared = container;
}

function clearSharedStore() {
delete shared.store;
}

function getSharedStore() {
return shared.store;
}

function setSharedStore(store) {
shared.store = store;
}

function getReduxCreateStore(info) {
const bundles = info.reduxBundles || [];
return function reduxCreateStore(initialState) {
let store = getSharedStore();
if (store) {
store.integrateBundles.apply(this, bundles);
} else {
store = composeBundles.apply(this, bundles)(initialState);
setSharedStore(store);
}
return store;
}
}

module.exports = {
setStoreContainer,
getReduxCreateStore,
getSharedStore,
setSharedStore,
clearSharedStore
};