Skip to content

Commit

Permalink
Integrate redux-bundler into subapp-pbundle
Browse files Browse the repository at this point in the history
  • Loading branch information
christianlent committed Jan 7, 2020
1 parent 7619241 commit d578b7f
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 0 deletions.
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";
74 changes: 74 additions & 0 deletions packages/subapp-pbundle/src/redux-bundler.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from "react";
import { render, hydrate } from "react-dom";
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
};

0 comments on commit d578b7f

Please sign in to comment.