reactjscode-splittingreact-loadable

code splitting with Loadable from react-loadable causes screen flicker


I'm trying to apply code splitting to my React app. The below code is my routes with code splitting applied by Loadable from react-loadable. With the implementation, every time I access each page, the code chunk from webpack is properly loaded. However, when I access my webpage initially, it brings about screen flicker initially. After that, if I move to another page, no more screen flicker. It only happens when accessing my website initially.

Does anyone know why it's happening? Is there something wrong on my configuration?

By the way, I used server-side rendering with Node.js in my React app. Does it have something to do with screen flicker by code splitting?

routes.jsx

import React from "react";
import Loadable from "react-loadable";
import { Route, Switch } from "react-router-dom";

import NotFound from "routes/not-found";

const Landing = Loadable({
  loader: () => import(/* webpackChunkName: "landing" */ "routes/landing"),
  loading: () => null,
  modules: ["landing"]
});

const About = Loadable({
  loader: () => import(/* webpackChunkName: "about" */ "routes/about"),
  loading: () => null,
  modules: ["about"]
});

export default props => {
  return (
    <Switch>
      <Route
        exact
        path="/"
        render={routeProps => <Landing {...routeProps} options={options} />}
      />
      {/* <Route exact path="/" component={Homepage} /> */}
      <Route
        exact
        path="/about"
        render={routeProps => <About {...routeProps} options={options} />}
      />

      <Route component={NotFound} />
    </Switch>
  );
};

src/index.js

const { store, history } = createStore();
const generateClassName = createGenerateClassName();

const Application = (
  <JssProvider generateClassName={generateClassName}>
    <MuiThemeProvider theme={theme}>
      <Provider store={store}>
        <ConnectedRouter history={history}>
          <Frontload noServerRender={true}>
            <App />
          </Frontload>
        </ConnectedRouter>
      </Provider>
    </MuiThemeProvider>
  </JssProvider>
);

const root = document.querySelector("#root");

if (root.hasChildNodes() === true) {
  // If it's an SSR, we use hydrate to get fast page loads by just
  // attaching event listeners after the initial render
  Loadable.preloadReady().then(() => {
    hydrate(Application, root, () => {
      document.getElementById("jss-styles").remove();
    });
  });
} else {
  // If we're not running on the server, just render like normal
  render(Application, root);
}

Solution

  • the flickering is happening because the router don't have the source of your component when routing and it renders null as you defined in loading func provided to Loadable HOC to prevent flickering you can render a Loading component that should look something like this: https://github.com/osamu38/react-loadable-router-example/blob/master/src/components/Loading.js

    or you can preload all the pages onComponentDidMount like this (you should convert your component to class component for it):

     componentDidMount = () => {
        About.preload()
        Landing.preload()
      }