Code splitting in Gatsby
Tags: gatsby, webpack, performance
Published: 2022-05-02 07:57:40


 > This article will be especially interesting for large Gatsby projects: +1,000 pages.
> Also if your project uses React18 or +, use this method instead : [https://youtu.be/lypEGNEIRKE](https://youtu.be/lypEGNEIRKE)

Gatsby is a very powerful meta framework for developing very quick loading sites. Which is very important for SEO and for UX.

With the generation of static pages of Gatsby, the TTFB (time to first byte) and the FCP (first contentful paint) are lowered a lot compared to a CSR site (client side rendering) resulting for instance from a React pure development. And with the optimization of picture loading, with Gatsby Image, comes as well the optimisation of the LCP.

And all this is done almost automatically with Gatsby! Incredible ! Nothing's left? Not really 😅 It would have been too easy.

The more your project grows, the more likely you will load more JS bundles than needed in some pages of your site. If you perform a test using PageSpeed Insights ([pagespeed.web.dev](https://pagespeed.web.dev/)) you may get this advice / opportunity to optimize your page :

![PageSpeed Insights Analyze](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zeqlyp3a47h29zf5q3ui.png)


This optimization opportunity occurs when you load javascript code that is not used by the page on which you are performing the test.

There are two main causes:

- bad code splitting
- third party scripts: GTM, Facebook pixels, etc.

In this article, we will see how to fix the main cause of this problem, _**bad code splitting**_. The second cause will be discussed in a second article.

## How does Gatsby split your code natively?

Initially, Gatsby organize your JS bundles into 3 categories:

- application-level chunks (shared with all pages),
- template-level chunks (shared with all pages of the same template),
- page-level data imports

Let's take the example of a news site that creates articles for each news, some having videos. 

Our site has several page templates:

- Home page template
- News page template (potentially with videos depending on the news)
- News categories page template (which lists and organizes news depending on their category)

We will focus on the news pages, which are the most important on the site. The specificity of our news pages is that they potentially have videos.
Therefore we need a library allowing a good management of these videos. Let's take **Video.js** for example. This library is perfect, it allows us to play videos in many formats (MP4, Webm, HLS, DASH, etc.) and it implements an easy way to customize our video player.

The problem with this library is that it’s heavy, 573.6kb MINIFIED, and 159.1 kB MINIFIED + GZIPPED.


![bundlephobia Video js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgjb3f5es0sffcnon9fd.png)

According to [bundlephobia](https://bundlephobia.com/package/video.js@7.18.1), it can take up to 3.18 seconds to load in slow 3G. This can seriously spoil the experience of our site, which aims to be efficient and quick to load (which is why we decided to develop it with Gatsby).

Now we will check the bundles of our articles without videos, to see if they have also the Video.js imported. 

## How to analyze the bundles of each pages in Gatsby ?

Thanks to the **gatsby-plugin-perf-budgets** and **gatsby-plugin-webpack-bundle-analyse-v2** plugins which are installed using this command:

```
npm i gatsby-plugin-webpack-bundle-analyser-v2 -D
npm i gatsby-plugin-perf-budgets -D
```

We can see that our video library (**Video.js**) is loaded in all article pages, even if they don't have videos.

Bundle analyze of a page article without video :


![Bundle analyze before code splitting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7fzexevqgpf9x49ye2c.png)
And we import 457 kb of JS : 
![Bundles size import before code splitting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q3f0xgppqowwiw84yr7s.png)

> I simplified the rendering of the analysis to make it more readable (Yes I'm a photoshop master)

That’s where _**code splitting**_ sets in : we basically split the import of our _**VideoPlayer**_ component (which itself imports and uses our **Video.js** library).

## How to do code splitting with Gatsby?

Once we have identified what code to split by analysing the different bundles of the pages, we are able to code split the components containing the packages that we want to import only on page with videos : in our example, the **VideoPlayer** component.

To do so with Gatsby, complementary packages are needed :

- `@loadable/babel-plugin`
- `@loadable/component`
- `@loadable/webpack-plugin`
- `gatsby-plugin-loadable-components-ssr`

And add the `gatsby-plugin-loadable-components-ssr` plugin that we just installed to our plugin list in the `gatsby-config.js`.

Then we just have to use `@loadable/component` to import our VideoPlayer component:

```jsx
import loadable from "@loadable/component"
const VideoPlayer = loadable(
  () => import("~/components/VideoPlayer/VideoPlayer")
)
```

And then make sure to **conditionally** use the ***VideoPlayer*** component only if the article has a video:

```jsx
{
  article.video && (
    <VideoPlayer
        src={article.video.url}
	title={article.video.intro}
    />
  )
}
```

And so, now our pages without videos no longer have the ***Video.js*** library in their bundles:

(Always the same photoshop talents)
![Bundle analyze after code splitting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o2alq7qqe0gblzckxenm.png)
Now we import 355kb of JS files, and we economize 2 requests!
![Bundles size import after code splitting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ix12u06iddd4hyqj5mjx.png)
 

Voilà, you have just seen how to create code splitting with Gatbsy. 

But you should know that with React 18 and **React.lazy()**, it's now possible to create splitting code natively! Without the `gatsby-plugin-loadable-components-ssr` plugin ! So moving to React 18 seems then to be a good alternative.

I put here a list of some reliable sources to deepen what we have just seen together if you are interested:

- [https://www.gatsbyjs.com/docs/how-to/performance/improving-site-performance/#step-1-profile-your-bundle](https://www.gatsbyjs.com/docs/how-to/performance/improving-site-performance/#step-1-profile-your-bundle)
- [https://www.slideshare.net/calcsam/the-anatomy-of-a-performance-audit/29](https://www.slideshare.net/calcsam/the-anatomy-of-a-performance-audit/29)