Skip to content

Instantly share code, notes, and snippets.

@rabet
Forked from mgreer/codeSplitting.js
Created March 25, 2019 20:21
Show Gist options
  • Save rabet/031e39ed07389051e120838f9db6937c to your computer and use it in GitHub Desktop.
Save rabet/031e39ed07389051e120838f9db6937c to your computer and use it in GitHub Desktop.
Code splitting HOC
// @flow
import * as React from 'react';
import {asyncComponent} from 'react-async-component';
export const loaderMaker = (bgColor: string = 'transparent') => () => (
<div style={{position: 'absolute', width: '100%', height: '100%', backgroundColor: bgColor}} />
);
const MAX_RETRIES = 3;
const STARTING_BACKOFF = 500;
const pausedPromise = (duration: number): Promise<*> => new Promise(resolve => setTimeout(resolve, duration));
const resolveWithRetryBackoff = (
createPromise: () => Promise<*>,
retries: number,
delay: number = STARTING_BACKOFF
): Promise<*> =>
createPromise().catch(err => {
console.error(err);
if (retries > 1) {
return pausedPromise(delay).then(() => resolveWithRetryBackoff(createPromise, retries - 1, delay * 2));
}
return Promise.reject(err);
});
type Options = {
name?: string,
LoadingComponent?: React.ComponentType<*>,
};
/*
** Loads require or delays import depending on if server or client
** Default loader is transparent, as it could be a component which is not full-page
** This can be overridden.
** Chunk will be retried with a backoff.
*/
export const makeLazy = (resolve: () => Promise<*>, options: Options = {}) => {
if (options.name != null) {
options.name = `AsyncComponent(${options.name})`;
}
if (options.LoadingComponent == null) {
options.LoadingComponent = loaderMaker();
}
return asyncComponent({
resolve: () => (global.isServerRendering ? resolve() : resolveWithRetryBackoff(resolve, MAX_RETRIES)),
env: global.isServerRendering ? 'node' : 'browser',
...options,
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment