Bring an Islands-style architecture to Gatsby. EXPERIMENTAL - USE AT YOUR OWN RISK.
npm i gatsby-islands
AstroJS lacks the source-plugin ecosystem of Gatsby - and its built-in React renderer doesn’t account for many niceties we’re used to with Gatsby - like SPA navigation, Context, responding to props, etc. But Gatsby projects can quickly get gigantic in bundle size - and that doesn’t improve much even when using Loadable Components. Gatsby-Islands doesn’t try to completely adhere to a strict Islands architecture - instead it assumes you’ll likely want full-app context and state, while minimising the size and interactivity of your individual pages. It’s lightweight and lets you work with Gatsby the way you’re used to.
Gatsby-Islands lets you load components as Islands or Oceans - independent of the rest of your Gatsby app. This means you can have interactive headers, footers, and transitions - but mostly dumb pages - perfect for most website projects.
Any component loaded only through an Island or Ocean will be excluded from your main Gatsby bundles. Islands will hydrate when the page is loaded, or on some other command (by using the deferUntil prop). Oceans will not hydrate and will only show server-rendered content (thus excluding the component completely from your user runtime*** (see pitfalls)).
As opposed to AstroJS’s implementation of Islands in React, it does not create individual bundles - instead only using component-based chunking - so that the existing Gatsby Webpack implementation (which you may have customised with extra plugins etc) remains in tact.
- In order to keep the Gatsby SPA working - Oceans will be loaded on subsequent page changes (i.e. any navigation to a page that isn’t the original SSR-ed entry point). This is because there’s no way to get SSR generated content after original SSR. In practical terms - this in almost every case won’t result in a noticeable performance hit (as the rest of your app has already loaded, and you’re only loading a small amount of new JS in response to a page change). If you want to avoid this - don’t use Gatsby’s link component, turn prefetching off, and use ‘a’ tags for navigation (so that every page rendered is one that has been SSR-ed). In many cases this will result in a worse performance hit (as the browser has to go to a new page and rehydrate React again) - but YMMV.
- You will see several render errors in the console when using React 18. Most of the time these can be safely ignored. This will be fixed as soon as solutions become available.
- You may experience issues with ID assignment (important for re-rendering) in React 18 from concurrent rendering. If you experience this issue, please lodge a Github Issue.
|IslandsProvider||This enables Islands to work inside your app. This should be place in your layout (it needs to observe route changes to function correctly) and is responsible for creating persistent IDs for your components|
|Island||name: Path to Component; deferUntil: Idle/Visible; clientOnly: boolean; context: React Context instance, …props: any||A component that will separate the component specified by name prop into a separate chunk, and load when the page is visited (or deferred via deferUntil prop). You can provide props to your component by adding them to Island, and provide Context to your component by passing it in via the context prop. Your island will respond to context and prop updates, and will also render them initially in SSR.|
|Ocean||name: Path to Component, context: Context instance, …props: any||A component that will not server-render only. Subsequent page changes will load your component as an island. You may provide an initial props and context for SSR, but your component will not respond to updates.|
|useIslandContext||context: Context Instance||If you need to consume a React Context within your Island or Ocean, use this hook instead of React’s useContext. This hook allows useContext to SSR correctly.|