Last active
March 13, 2019 05:13
-
-
Save faceyspacey/be2ea05eb69de705f9da61c6b236f08a to your computer and use it in GitHub Desktop.
Rudy custom code-splitting middleware (split reducers, components, routes, libs)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// implementation 1 | |
const load = (api) => async (req, next) => { | |
const { route, action } = req | |
const hasLoad = route && route.load | |
if (!hasLoad) return next() | |
const { components, reducers, chunks, ...res } = await route.load(req) || {} | |
if (hasChunks(req.ctx, chunks)) return next() | |
if (reducers) { | |
req.options.replaceReducer(reducers) | |
if (req.tmp.committed) { | |
req.commitDispatch(req.action) // double commit so reducer is up to date | |
// but what about reducer receiving potential _COMPLETE action?? -- autoDispatch middleware only does it after both complete | |
} | |
} | |
if (components) { | |
if (!req.tmp.committed) { | |
const currentComponents = req.getLocation().components | |
req.action.components = { ...currentComponents, ...components } | |
} | |
else { | |
req.commitDispatch({ type 'LOAD', payload: { components } }) | |
} | |
} | |
if (isServer()) { | |
req.ctx.chunks.push(...chunks) | |
} | |
Object.assign(route, res) | |
return next() | |
} | |
} | |
// implementation 2 | |
import { createStore, applyMiddleware, compose, combineReducers } from 'redux' | |
export default (name = 'load') => (api) => async (req, next) => { | |
const load = req.route && req.route[name] | |
if (load) { // if `route.load` does not exist short-circuit | |
const parts = await load(req) | |
addPartsToRuntime(req, parts) | |
} | |
return next() | |
} | |
const addPartsToRuntime = (req, parts) => { | |
const { route, action, options, tmp, ctx, commitDispatch } = req | |
const { components, reducers, chunk, ...rest } = parts | |
if (ctx.chunks.includes(chunk)) return // chunk was already added to runtime, so short-circuit | |
if (reducers) { | |
// options.replaceReducer(reducers) | |
} | |
if (components) { | |
req.location.components = components | |
action.components = components // we need to modify `createReducer` to store `state.location.components` so after load they can be dynamically rendered within existing components! | |
} | |
if (tmp.committed && (components || reducers)) { // if the route change action has already been dispatched, we need to re-dispatch it again, so the new goodies are received | |
action.force = true // we need a flag to force this action through, so component are added to state or new reducers receive action -- the `force` flag doesn't already exist, it's a placeholder for something we can already use to force the action passed the `isDoubleDispatch` check; we may have some other piece of infrastructure that precludes needing to create a new custom flag | |
commitDispatch(action) | |
} | |
Object.assign(route, rest) // rest allows you to tack on additional thunks, sagas, etc, to your route object (optionally) -- i.e. you can build the "plane" (aka route) while flying | |
ctx.chunks.push(chunk) | |
} | |
// usage | |
const routes = { | |
CODESPLIT: { | |
path: '/split/:page', | |
load: ({ params }) => (typeof window === 'undefined') ? require.resolveWeak(`./components/${params.page}`) : import(`./components/${params.page}`) | |
}, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment