|
| 1 | +# Gatsby + loadable-components |
| 2 | + |
| 3 | +This repo is meant to illustrate the pattern of adding [loadable-components](https://loadable-components.com/docs/getting-started/) to a Gatsby project. In this case, the Header component is being code-split out while maintaining SSR. |
| 4 | + |
| 5 | +```jsx |
| 6 | +// src/components/layout.jsx |
| 7 | +import * as React from "react" |
| 8 | + |
| 9 | +const Header = loadable(() => import("./header")) |
| 10 | +export default Header |
| 11 | +``` |
| 12 | + |
| 13 | +## Why? |
| 14 | + |
| 15 | +Why do you need to do this when Gatsby already has excellent out-of-the-box code-splitting configuration? |
| 16 | + |
| 17 | +There is one main scenario: _conditional rendering_. This can come in two forms: |
| 18 | + |
| 19 | +- flex layouts from CMS content |
| 20 | +- logic in a component that may or may not render an import |
| 21 | + |
| 22 | +These are essentially the same thing, but at different scales. |
| 23 | + |
| 24 | +### Flex Layouts |
| 25 | + |
| 26 | +When you build a page with a headless CMS, parts of your site may have a structured layout that is defined in code by components and can only be changed with a code change. Other pages, due to business cases or user preferences, need to have flexible layouts where a content editor can mix and reorder components in the CMS, and have that layout reflected in the code. |
| 27 | + |
| 28 | +The most common pattern is a switch case or series of if statements checking the component’s type, rendering the correct one and passing in its props. |
| 29 | + |
| 30 | +```jsx |
| 31 | +// src/components/flex-page.jsx |
| 32 | +import * as React from "react" |
| 33 | + |
| 34 | +const FlexPage = ({ components }) => { |
| 35 | + return ( |
| 36 | + <> |
| 37 | + {components.map(component => { |
| 38 | + switch (component.type) { |
| 39 | + case "header": |
| 40 | + return <Header {...component} /> |
| 41 | + case "text": |
| 42 | + return <Text {...component} /> |
| 43 | + case "carousel": |
| 44 | + return <Carousel {...component} /> |
| 45 | + default: |
| 46 | + return <div>empty</div> |
| 47 | + } |
| 48 | + })} |
| 49 | + </> |
| 50 | + ) |
| 51 | +} |
| 52 | + |
| 53 | +export default FlexPage |
| 54 | +``` |
| 55 | + |
| 56 | +### Logical Checks in Render |
| 57 | + |
| 58 | +This is basically the above pattern but on a smaller scale. |
| 59 | + |
| 60 | +```jsx |
| 61 | +import * as React from "react" |
| 62 | + |
| 63 | +const FlexPage = ({ hasCarousel }) => { |
| 64 | + return ( |
| 65 | + <div> |
| 66 | + <Heading /> |
| 67 | + <Text /> |
| 68 | + {hasCarousel && <Carousel />} |
| 69 | + </div> |
| 70 | + ) |
| 71 | +} |
| 72 | + |
| 73 | +export default FlexPage |
| 74 | +``` |
| 75 | + |
| 76 | +### The Conditional Drawback |
| 77 | + |
| 78 | +So what’s the problem with the patterns above? A content editor can build a page with a Heading, Text or a Carousel. Technically, the page will display as expected, but imagine a page where the editor only choose a Heading and Text. In that case, the Carousel and its dependencies will still be on the page! |
| 79 | + |
| 80 | +This is because Gatsby’s default code splitting configuration we mentioned at the beginning splits bundles by page-level. That means any import in a page template will end up in its bundle whether it is actually rendered, used, or not. |
| 81 | + |
| 82 | +## How to Configure |
| 83 | + |
| 84 | +To use loadable-components with SSR, we use a Gatsby plugin, [gatsby-plugin-loadable-components-ssr](https://github.com/graysonhicks/gatsby-plugin-loadable-components-ssr). This makes the webpack configuration we need to use loadable-components while _maintaining SSR_. This is crucial, because if you only code-split, yes the bundle can be smaller, but the client-side rendering will drastically hurt performance more than the bundle reduction could make up. To configure the plugin, follow the [instructions here](https://github.com/graysonhicks/gatsby-plugin-loadable-components-ssr). |
| 85 | + |
| 86 | +## Verification |
| 87 | + |
| 88 | +Once you follow this pattern, how can you test if a component is being code-split and SSR'd? The easiest way is through DevTools. |
| 89 | + |
| 90 | +After building the site and serving locally, refresh the page with DevTools open. |
| 91 | + |
| 92 | +First, verify the code-splitting by looking for a JS bundle in the Network tab with the naming pattern: `component--[my-component]-[hash].js`. |
| 93 | + |
| 94 | +Then, to verify SSR is still working, click the 'All' option in the Network tab and look for the first item `localhost`. This is the initial HTML sent by Gatsby. Verify that you can see the code-split component in this initial HTML. |
| 95 | + |
| 96 | +That's it, happy building! 🎉 |
0 commit comments