Code Splitting in Create React App


#21

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!


#22

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?


#23

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-.


#24

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.?


#25

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.


#26

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


#27

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.


#28

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.


#29

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;
        }

#30

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

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


#31

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>
);

#32

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


#33

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.


#34

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.