Code Splitting in Create React App

From @jayair on Sat Aug 12 2017 21:37:43 GMT+0000 (UTC)

@origicom Yeah it looks like react-loadable has been updated.

Just made the change - https://github.com/AnomalyInnovations/serverless-stack-com/commit/02b273342cad736f43ba3349dfda2baa11007589. Thanks!

From @rtmalone on Wed Aug 30 2017 17:00:44 GMT+0000 (UTC)

Great article; thanks for detailing the ‘why’ in some of the decisions. I immediately added an AsyncComponent in three of my apps. I wondering though how to descriptively name the chunks to correspond to the component or file name. Any thoughts?

From @jayair on Wed Aug 30 2017 21:19:42 GMT+0000 (UTC)

@rtmalone I haven’t tried this but I think you are looking for the webpackChunkName option - https://webpack.js.org/api/module-methods/#import-.

From @simvisfear on Mon Sep 04 2017 06:21:32 GMT+0000 (UTC)

How do you handle the case where we have redux store and when reducers have child reducers.?

From @jayair on Mon Sep 04 2017 17:40:01 GMT+0000 (UTC)

@simvisfear I’m not sure what you mean specifically (with respect to code splitting) but the dynamic import works similarly to a regular import.

From @bestwestern on Wed Oct 18 2017 07:39:36 GMT+0000 (UTC)

Thank you very much for this. I am looking for a way to preload some routes (without react-loadable).
Right now I simply call
componenDidMount(){ import("./containers/Login"); }
which seems to do the trick

From @jayenashar on Mon Dec 18 2017 00:48:26 GMT+0000 (UTC)

Hi there, I’m pretty new to react and am not using redux. I have implemented code splitting with an async component as described in this chapter and it works great. However, I call child component instance methods from parent components (e.g., childComponentRef.triggerABC()). I’m not sure the proper way to do this with the AsyncComponent as a proxy, but I would like to share what I have done.

First, I save a ref of the child component: <C {...this.props} /> becomes <C {...this.props} ref={c => c && (this.c = c)} />

Second, I return a Proxy: return AsyncComponent; becomes

    return new Proxy(AsyncComponent, {
        construct: (target, argumentsList, newTarget) => {
            return new Proxy(new target(...argumentsList), {
                get: (target, property, receiver) => {
                    const p = target[property];
                    if (p === undefined && target.c) {
                        return target.c[property];
                    } else {
                        return p;
                    }
                }
            });
        },
    });

Please let me know how I might improve on this (or simplify it), and feel free to share.

From @jayair on Thu Dec 21 2017 19:22:00 GMT+0000 (UTC)

@jayenashar I have not had a chance to try out the pattern of calling instance methods for async components. Hopefully, somebody else that comes across this has some ideas.

From @jayenashar on Tue Dec 26 2017 09:58:47 GMT+0000 (UTC)

@jayair the proxy got too complicated when i realised i needed to apply this for functions. i got it working, but threw it out. instead i use innerRef a la styled-components. Separate to that, I saw a warning when calling this.setState if the component unmounts while importing. I also opted not to use async/await as it added to the bundle size. I provide my modified functions below:

        componentDidMount() {
            this._isMounted = true;
            importComponent().then(({default: component}) => this._isMounted && this.setState({component}));
        }

        render() {
            const Component = this.state.component;
            const {innerRef, ...props} = this.props;
            return Component ? <Component {...props} ref={component => innerRef && innerRef(component)}/> : null;
        }

        componentWillUnmount() {
            this._isMounted = false;
        }

From @jayair on Wed Dec 27 2017 22:46:13 GMT+0000 (UTC)

@jayenashar That makes sense. Thanks for adding the context.

Having an issue with the Loadable library - my “loading” component shows up immediately, even if for only a split second, whether or not I have the delay property set. Has anyone else encountered this? I eliminated the additional routing wrappers and used simply Route but the issue persisted. Here’s the relevant libraries/versions:
react@16.6.1
react-router-dom@4.3.1
react-loadable@5.5.0

Code:

const LoadingSpinner = () => <div>Loading...</div>; 

const AsyncHome = Loadable({
    loader: () => import("./containers/Home"),
    loading: LoadingSpinner,
    delay: 300
});
const AsyncLogin = Loadable({
    loader: () => import("./containers/Login"),
    loading: LoadingSpinner,
    delay: 500
});

export default ({ childProps }) => (
    <Switch>
        <Route path="/" exact component={AsyncHome} />
        <Route path="/login" exact component={AsyncLogin} />
    </Switch>
);

I think you need to implement the props.pastDelay aspect in your LoadingSpinner. You can read about it here

I did read through that - my understanding was that this functionality comes out of the box (props.pastDelay is part of the Loadable component) with a default delay prop of 200ms. Whether or not I have the delay prop set, the loader still flashes.

Hmm I’m not entirely sure. The pastDelay is available for you to us in your spinner component? As in if you don’t implement it, it will flash.

The prop that gets set in the Loadable component is delay which then sets the internal pastDelay prop. The spinner is flashing whether I set this delay prop or not. My router code is here, and the site here.

The delay prop is set to 500 for both the Home and Login page, and it is not set for the Signup page. All three flash the loading icon in the top left corner.

Unfortunately I can’t open an issue against the repo as it isn’t publicly available to do so.

Yeah I noticed that they have issues disabled. Thanks for letting me know. We might move away from using them.

This is great thanks - what if I am wanting to pass props to the Async-loaded component? The above seems to assume I’m rendering <Home /> - but what if I want to render <Home foo="bar" /> ?

Apologies - I found that Loadable has a render method that allows this perfectly

1 Like

Hey, I am trying to refactor the code from the chapter to use react hooks but am doing something wrong and can’t figure it out, maybe someone has some ideas on how to help me?

Here is my code for the src/components/AsyncComponent.js :

export default function asyncComponent(importComponent) {
function AsyncComponent(props) {
	const [component, setComponent] = useState(null);

	useEffect(() => {
		async function onLoad() {
			try {
                const component = await importComponent();
				setComponent(component);
			} catch (err) {
				console.error(err);
			}
		}
		onLoad();
	}, []);

	const C = component;

	return C ? <C {...props} /> : <div>loading</div>;
}
    return AsyncComponent;
}

and the error message I get is:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Hey there, I’m not entirely sure about your issue. But this chapter needs to be updated to use React Suspense, since they added native support for this.