Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent loading vendors multiple times with code splitting

I'm playing around with create-react-app and code splitting at the moment. It worked really well until I began to import vendor libraries, which are going to be included in every chunk.

That's my current approach:

App.js

const HomePage = Loadable({
  loader: () => import('./Home.js'),
  LoadingComponent: Loading
});

const AboutPage = Loadable({
  loader: () => import('./About.js'),
  LoadingComponent: Loading
});

class App extends PureComponent {
  render() {
    return (
      <Router>
      <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={HomePage}/>
      <Route path="/about" component={AboutPage}/>
    </div>
  </Router>
    );
  }
}

About.js

import React, { PureComponent } from 'react';
import styled from 'styled-components';

const Button = styled.button`
  color: aqua;
`;

class AboutPage extends PureComponent {
  render() {
    return (
      <div>
        About
        <Button>Fooobar!</Button>
      </div>
    );
  }
}

export default AboutPage;

Home.js

import React, { PureComponent } from 'react';
import styled from 'styled-components';

const Button = styled.button`
  color: orange;
`;

class HomePage extends PureComponent {
  render() {
    return (
      <div>
        Home
        <Button>Fooobar!</Button>
      </div>
    );
  }
}

export default HomePage;

So HomePage and AboutPage are basically the same at the moment, but it's just a playground.

The problem is: the chunk for HomePage and AboutPage loads the entire styled-components package. This should be loaded once, shouldn't it?

enter image description here

As you can see on the image, 2.chunk.js and 1.chunk.js are both 121kb. I thought that code splitting would move styled-components to it's own chunk as soon as the packages get's imported multiple times?

For your information: I'm using create-react-app and didn't run eject so I have no idea what's inside the webpack configuration (if this should matter).

like image 660
Slevin Avatar asked Jun 07 '17 20:06

Slevin


People also ask

What can you use to handle code splitting?

Code-Splitting is a feature supported by bundlers like Webpack, Rollup and Browserify (via factor-bundle) which can create multiple bundles that can be dynamically loaded at runtime.

Does code splitting improve performance?

Code-splitting is splitting the bundle file into chunks based on the user's needs or what the user is interested in seeing. This idea brings about a decrease in the website's load time since users will need to download a smaller bundle file, giving users a better experience.

What is a purpose of code splitting?

Code splitting is a feature supported by bundlers like Webpack and Browserify which can create multiple bundles that can be dynamically loaded at runtime.

Which approaches are used by next JS for code splitting * Entry points prevent duplicate dynamic imports all of the above?

There are three general approaches to code splitting available: Entry Points: Manually split code using entry configuration. Prevent Duplication: Use Entry dependencies or SplitChunksPlugin to dedupe and split chunks. Dynamic Imports: Split code via inline function calls within modules.


1 Answers

The problem was the missing webpackRequireWeakId.

Instead of ...

const HomePage = RouteLoader({ loader: () => import('routes/home') })

...I have to use ...

const HomePage = RouteLoader({ 
  loader: () => import('routes/home'),
  webpackRequireWeakId: () => require.resolveWeak('routes/home')
})

... as described in the documentation of react-loadable: https://github.com/thejameskyle/react-loadable#why-are-there-multiple-options-for-specifying-a-component

like image 179
Slevin Avatar answered Oct 02 '22 13:10

Slevin