Porting from Create React App to Gatsby
Create React App is an officially supported CLI tool from Facebook to set up React apps, without having to deal with complicated configurations. It provides a default setup for tools like webpack and Babel that are useful in a modern development pipeline.
Gatsby is similar in that it can also help you set up an application and removes much of the configuration headache. However, Gatsby offers some additional advantages like performance optimizations with static rendering and a thriving ecosystem of plugins. Gatsby and Create React App even share nearly identical webpack and Babel configurations which makes porting less cumbersome. React’s own docs run on Gatsby, and React even recommends Gatsby to users of Create React App!
Both Create React App and Gatsby use React and allow users to build apps more quickly. However, there are some important differences.
Gatsby enables some useful performance optimizations for you, by default. Route-based code splitting and pre-loading of the next resources make your application lightning fast, without any additional effort! Further still, the following optimizations and techniques are also available to you:
gatsby-linkuses an intersection observer to preload linked pages when they appear in the viewport, making them feel like they load instantly
gatsby-imagewill create optimized versions of your images in different sizes, loading a smaller, optimized version of an image and replacing it with a higher resolution version when loading has finished. It also uses an intersection observer to cheaply lazy load images. Check out the demo to see for yourself
These features and more work together to make your Gatsby site fast by default. If you’d like a deep dive on these and other performance optimizations, check out this blog post
Gatsby still works with all the
react packages running in a Create React App project, but adds the ability to leverage hundreds of other Gatsby plugins to drop in additional features such as: adding SEO, responsive images, RSS feeds, and much, much more.
Plugins can also pull in data from any number of sources like APIs, CMSs, or the filesystem. That data is combined into a unified data layer that you can query with GraphQL throughout your app.
This data layer simplifies the process of pulling data from different sources and providing them in your pages and components. This combination of data from different sources stitched together in a modern workflow is referred to as the content mesh.
Note: GraphQL isn’t required for managing data in a Gatsby app. Feel free to look over the guide on using Gatsby without GraphQL as well
In order to transition your codebase over to using Gatsby, a few things need to be taken care of to account for the differences between how the projects are set up.
In order to use Gatsby, you have to install it:
Note: rather than using the
gatsby newcommand like you would initializing a new Gatsby site, this will install Gatsby as a dependency in your project
After installation, the key things that need to change are:
ensuring any calls to browser-based APIs still work (if there are any)
converting routes into pages in the
The following sections explain the above steps as well as other changes that you might need to make depending on the complexity of your app. A default Create React App project is able to run with just the above steps.
To show some of the differences of how your project structure could differ by moving to Gatsby, a default Create React App project looks something like this:
Whereas a default Gatsby project will look something like this (files that are different between Create React App and Gatsby are highlighted):
The structure of a Gatsby project adds some additional configuration files to hook into specific Gatsby APIs for the browser and for server-side rendering, though much of the project structure is similar enough to feel comfortable quickly.
An important difference to note is the
/pages folder in the Gatsby project structure where components will automatically be turned into static pages by Gatsby. This is discussed more in the routing section below.
src/pages/index.js file in Gatsby is a little different from the
src/index.js file in Create React App where the root React element mounts, because it is a sibling to other pages in the app — rather than a parent like Create React App. This means in order to share state or wrap multiple pages you should use the wrapRootElement Gatsby API.
Server-side rendering means pages and content are built out by the server, and then sent to a browser ready to go. It’s like your pages are constructed before even being sent to the user. Gatsby is server-side rendered at build time, meaning that the code that gets to your browser has already been run to build pages and content, but this doesn’t mean you can’t still have dynamic pages.
Understanding the distinction between the client (or browser) and server will help you understand that key difference between Create React App and Gatsby. Create React App doesn’t by default render your components with server-side rendering APIs when it is built like Gatsby does.
Check out Dustin Schau’s blog post about Gatsby internals that explains the technical aspects of the build process in greater detail
gatsby build command also won’t be able to use browser APIs, so some code that relies on browser DOM APIs and globals will cause your build to break if it isn’t protected. Learn more about using client-side only packages.
Some common globals that would need to be protected are:
Additionally, some packages that depend on globals existing (e.g.
react-router-dom) may need to be patched or migrated to other packages.
These are only a few examples, though all can be fixed in one of two ways:
- wrapping the code in an
ifstatement to check if whatever you are referencing is defined so builds won’t try to reference something undefined. Then the browser will be able to deal with it fine when the condition matches:
- For class components: moving references to browser globals into a
Would be changed into:
- For function components: moving references to browser globals into a
Would be changed to:
If these browser globals aren’t protected correctly, you’ll see a webpack error like the one below when building your site:
There are two possibilities of routes that you can set up: static and client-only. Gatsby automatically turns React components in the pages folder into static routes. This means that a statically rendered page directly corresponds to index.html files in the app’s built assets, whereas a client-only route is rendered by the client and configured by the routing setup you define. Both types of pages can fetch data at runtime just like any other React app.
Note: An advantage to having pages in separate files like this is a defined way of automatically code splitting, whereas Create React App requires you to use the
import()syntax to assign what elements should be loaded dynamically.
For dynamic routes, you should implement routing with @reach/router, which is already included with Gatsby. Dynamic routes can be implemented the same way you would implement a router in Create React App (or any other React application). However, because these routes won’t be represented as HTML files in the final build, if you want users to be able to visit the routes directly (like entering the URL in the search bar), you’ll need to generate pages in the
gatsby-node.js file which is demonstrated in the Building Apps with Gatsby guide.
Gatsby provides a
<Link /> component and a
navigate function to help you direct users through pages on your site. You can read about how to use each in the
Because Gatsby rehydrates into a regular React app, state can be handled inside of components in the same way it would in Create React App. If you use another library for state management and want to wrap your app in some sort of global state the section on context providers will be helpful.
Create React App requires you to create environment variables prefixed with
REACT_APP_. Gatsby instead uses the
GATSBY_ prefix to make environment variables accessible in the browser context.
Part of Gatsby’s philosophy around tooling is progressively disclosing complexity; this simplifies the experience for a wider audience while still allowing the option to configure more advanced features for those that feel inclined. You won’t have to “eject” your Gatsby app to edit more complex configurations.
In terms of levels of abstraction, Gatsby allows you to move up or down to tap into more sophisticated, lower-level APIs without needing to eject like you would in Create React App.
Create React App will require you to eject or rely on another workaround to edit the webpack configuration. Gatsby allows custom configuration of webpack via the
React’s context API allows you to share state from a higher component and distribute it to components below it in the component tree without having to deal with issues like prop drilling.
How do you share state across components like a theme without one top level
App.js file? Gatsby has a
wrapRootElement and a
wrapPageElement API that allow you to wrap the root element or all pages of your Gatsby site with components you want.
In Create React App it could look like this:
In Gatsby, if you want your providers to be global across pages you would move those providers to