Skip to content

Instantly share code, notes, and snippets.

@gbakernet
Forked from acdlite/app.js
Last active July 2, 2018 10:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gbakernet/25c1400bae5b2347e9c87fe19d42de1a to your computer and use it in GitHub Desktop.
Save gbakernet/25c1400bae5b2347e9c87fe19d42de1a to your computer and use it in GitHub Desktop.
Quick and dirty code splitting with React Router v4 with quick and dirty SSR support
// Preserve the server render markup
// This has to run before the root render
let preservedMarkup = {}
if (typeof document !== "undefined") {
[...document.querySelectorAll("[data-async-component]")].map(node =>
preservedMarkup[node.getAttribute("data-async-component")] = node.innerHTML
)
}
// getComponent is a function that returns a promise for a component
// It will not be called until the first mount
// TODO generate id's
function asyncComponent(getComponent, id) {
return class AsyncComponent extends React.Component {
static Component = null;
state = {
Component: AsyncComponent.Component
__html: null,
};
componentWillMount() {
if (!this.state.Component) {
getComponent().then(Component => {
AsyncComponent.Component = Component
this.setState({ Component })
})
}
}
componentDidMount() {
if (!this.state.Component) {
this.setState({__html: preservedMarkup[id]})
}
}
render() {
const { Component, __html } = this.state
const ref = node => this._node = node
// Render the async loaded component finally
if (Component) {
return <div data-async-component={id} ref={ref}><Component {...this.props} /></div>
}
// Render the preserved markup
if (__html) {
return <div data-async-component={id} ref={ref} dangerouslySetInnerHTML={{ __html }} />
}
// Yes, returning null. But.. the preserved markup render will follow immediately.
return null
}
}
}
// Single Use with static ids
const Foo = asyncComponent(() =>
System.import('./Foo').then(module => module.default)
, "foo")
const Bar = asyncComponent(() =>
System.import('./Bar').then(module => module.default)
, "bar")
const App = () =>
<BrowserRouter>
<Link to="/foo">Foo</Link>
<Link to="/bar">Bar</Link>
<Match pattern="/foo" component={Foo} />
<Match pattern="/bar" component={Bar} />
</BrowserRouter>
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment