Migrating from v2 to v3
Looking for the v2 docs?
Have you run into something that’s not covered here? Add your changes to GitHub!
Introduction
This is a reference for upgrading your site from Gatsby v2 to Gatsby v3. Since the last major release was in September 2018, Gatsby v3 includes a couple of breaking changes. If you’re curious what’s new, head over to the v3.0 release notes.
If you want to start a new Gatsby v3 site, run
npm init gatsby
oryarn create gatsby
in your terminal.
Table of Contents
- Updating Your Dependencies
- Handling Breaking Changes
- Future Breaking Changes
- For Plugin Maintainers
- Known Issues
Updating Your Dependencies
First, you need to update your dependencies.
Update Gatsby version
You need to update your package.json
to use the latest version of Gatsby.
Or run
Please note: If you use npm 7 you’ll want to use the --legacy-peer-deps
option when following the instructions in this guide. For example, the above command would be:
Update Gatsby related packages
Update your package.json
to use the latest version of Gatsby related packages. You should upgrade any package name that starts with gatsby-*
. Note, this only applies to plugins managed in the gatsbyjs/gatsby repository. If you’re using community plugins, they might not be upgraded yet. Many plugins won’t need updating so they may keep working (if not, please check their repository for the current status). You can run an npm script to see all outdated dependencies.
npm
Compare the “Wanted” and “Latest” versions and update their versions accordingly. For example, if you have this outdated version:
Install the new package with:
yarn
You’ll be given an overview of packages which to select to upgrade them to latest
.
Updating community plugins
Using community plugins, you might see warnings like these in your terminal:
If you are using npm 7, the warning may instead be an error:
This is because the plugin needs to update its peerDependencies
to include the new version of Gatsby (see section for plugin maintainers). While this might indicate that the plugin has incompatibilities, in most cases they should continue to work. When using npm 7, you can pass the --legacy-peer-deps
to ignore the warning and install anyway. Please look for already opened issues or PRs on the plugin’s repository to see the status. If you don’t see any, help the maintainers by opening an issue or PR yourself! :)
Handling dependencies for plugins that are not yet updated
Gatsby has an amazing ecosystem of plugins that make it easier to get up and running, and to incorporate various data sources and functionality into your Gatsby project. Part of that huge ecosystem includes dependency trees!
Depending on how the plugin authors have declared dependencies (e.g. marking a package as a dependency instead of a peerDependency) within those plugins, there could be a myriad of failures that arise. If you encounter any of these issues when migrating your project to Gatsby Version 3, we recommend that you use Yarn resolutions within your package.json
.
Please note: If you rely on a plugin that is not found within the list of plugins within the Gatsby framework, you very well may need to use the following resolutions in the near term.
The specific resolutions we recommend at this time are found below:
Handling version mismatches
When upgrading an already existing project (that has an existing node_modules
folder and package-lock.json
file) you might run into version mismatches for your packages as npm/yarn don’t resolve to the latest/correct version. An example would be a version mismatch of webpack@4
and webpack@5
that can throw an error like this:
An effective way to get around this issue is deleting node_modules
and package-lock.json
and then running npm install
again. Alternatively, you can use npm dedupe
.
Handling Breaking Changes
This section explains breaking changes that were made for Gatsby v3. Most, if not all, of those changes had a deprecation message in v2. In order to successfully update, you’ll need to resolve these changes.
Minimal Node.js version 12.13.0
We are dropping support for Node 10 as it is approaching maintenance EOL date (2021-04-30).
The new required version of Node is 12.13.0
. See the main changes in Node 12 release notes.
Check Node’s releases document for version statuses.
webpack upgraded from version 4 to version 5
We tried our best to mitigate as much of the breaking change as we could. Some are sadly inevitable. We suggest looking at the official webpack 5 blog post to get a comprehensive list of what changed.
If you hit any problems along the way, make sure the Gatsby plugin or webpack plugin supports version 5.
ESLint upgraded from version 6 to version 7
If you’re using Gatsby’s default ESLint rules (no custom eslintrc
file), you shouldn’t notice any issues. If you do have a custom ESLint config, make sure to read the ESLint 6 to 7 migration guide
src/api
is a reserved directory now
With the release of Gatsby 3.7 we introduced Functions. With this any JavaScript or TypeScript files inside src/api/*
are mapped to function routes like files in src/pages/*
become pages. This also means that if you already have an existing src/api
folder you’ll need to rename it to something else as it’s a reserved directory now.
Gatsby’s Link
component
The APIs push
, replace
& navigateTo
in gatsby-link
(an internal package) were deprecated in v2 and now with v3 completely removed. Please use navigate
instead.
Removal of __experimentalThemes
The deprecated __experimentalThemes
key inside gatsby-config.js
was removed. You’ll need to define your Gatsby themes inside the plugins
array instead.
Removal of pathContext
The deprecated API pathContext
was removed. You need to rename instances of it to pageContext
. For example, if you passed information inside your gatsby-node.js
and accessed it in your page:
Removal of boundActionCreators
The deprecated API boundActionCreators
was removed. Please rename its instances to actions
to keep the same behavior. For example, in your gatsby-node.js
file:
Removal of deleteNodes
The deprecated API deleteNodes
was removed. Please iterate over the nodes
instead and call deleteNode
:
Removal of fieldName
& fieldValue
from createNodeField
The arguments fieldName
and fieldValue
were removed from the createNodeField
API. Please use name
and value
instead.
Removal of hasNodeChanged
from public API surface
This API is no longer necessary, as there is an internal check for whether or not a node has changed.
Removal of sizes
& resolutions
for image queries
The sizes
and resolutions
queries were deprecated in v2 in favor of fluid
and fixed
.
While fluid
, fixed
, and gatsby-image
will continue to work in v3, we highly recommend migrating to the new gatsby-plugin-image
. Read the Migrating from gatsby-image
to gatsby-plugin-image
guide to learn more about its benefits and how to use it.
Calling touchNode
with the node id
Calling touchNode
with a string (the node id) was deprecated in Gatsby v2. Pass the full node
to touchNode
now.
Calling deleteNode
with the node id
Calling deleteNode
with a string (the node id) was deprecated in Gatsby v2. Pass the full node
to deleteNode
now.
Removal of three gatsby-browser
APIs
A couple of gatsby-browser
APIs were removed. In the list below you can find the old APIs and their replacements:
getResourcesForPathnameSync
=>loadPageSync
getResourcesForPathname
=>loadPage
replaceComponentRenderer
=>wrapPageElement
Using a global graphql
tag for queries
Until now you were able to use the graphql
tag for queries without explicitly importing it from Gatsby. You now have to import it: import { graphql } from 'gatsby'
CSS Modules are imported as ES Modules
The web moves forward and so do we. ES Modules allow us to better treeshake and generate smaller files. From now on you’ll need to import cssModules as: import { box } from './mystyles.module.css'
You can also import all styles using the import * as styles
syntax e.g. import * as styles from './mystyles.module.css'
. However, this won’t allow webpack to treeshake your styles so we discourage you from using this syntax.
Migrating all your CSS could be painful or you’re relying on third-party packages that require you to use CommonJS. You can work around this issue for Sass, Less, Stylus & regular CSS modules using respective plugins. If you’re using regular CSS modules, please install gatsby-plugin-postcss to override the defaults.
This example covers Sass. The other plugins share the same cssLoaderOptions
property.
File assets (fonts, pdfs, …) are imported as ES Modules
Assets are handled as ES Modules. Make sure to switch your require functions into imports.
If you’re using require with expression
or require.context
(which is not recommended), you’ll have to append .default
to your require statement to make it work.
webpack 5 node configuration changed (node.fs, node.path, …)
Some components need you to patch/disable node APIs in the browser, like path
or fs
. webpack removed these automatic polyfills. You now have to manually set them in your configurations:
If it’s still not resolved, the error message should guide you on what else you need to add to your webpack config.
process is not defined
A common error is process is not defined
. webpack 4 polyfilled process automatically in the browser, but with v5 it’s not the case anymore.
If you’re using process.browser
in your components, you should switch to a window is not undefined check.
If you’re using any other process properties, you want to polyfill process.
- Install
process
library -npm install process
- Configure webpack to use the process polyfill.
GraphQL: character escape sequences in regex
filter
In v2, backslashes in regex
filters of GraphQL queries had to be escaped
twice, so /\w+/
needed to be written as "/\\\\w+/"
.
In v3, you only need to escape once:
GraphQL: __typename
field is no longer added automatically
In v2, the __typename
field used to be added implicitly when querying for a field of abstract type (interface or union).
In v3, __typename
has to be added explicitly in your query:
Schema Customization: Add explicit childOf
extension to types with disabled inference
Imagine you have node type Foo
that has several child nodes of type Bar
(so you expect field Foo.childBar
to exist).
In Gatsby v2 this field was added automatically even if inference was disabled for type Foo
.
In Gatsby v3 you must declare a parent-child relationship explicitly for this case:
To make upgrading easier, check the CLI output of your site on the latest v2 and follow the suggestions when you see a warning like this:
If you don’t see any warnings, you are safe to upgrade to v3.
If this warning is displayed for a type defined by some plugin, open an issue in the plugin repo with a suggestion to upgrade (and a link to this guide).
You can still fix those warnings temporarily in your site’s gatsby-node.js
file until it is fixed in the plugin.
Related docs:
Schema Customization: Extensions must be set explicitly
Starting with v3, whenever you define a field of complex type, you must also assign the corresponding extension (or a custom resolver):
In Gatsby v2, we add those extensions for you automatically but display a deprecation warning.
To make upgrading easier, when you see a warning like the one below, check the CLI output of your site on the latest v2 and follow the suggestions provided.
If this warning is displayed for a type defined by some plugin, open an issue in the plugin repo with a suggestion to upgrade (and a link to this guide).
You can still fix those warnings temporarily in your site’s gatsby-node.js
until it is fixed in the plugin.
If you don’t see any warnings, you are safe to upgrade to v3. Read more about custom extensions in this blog post.
Schema Customization: Removed noDefaultResolvers
argument from inference directives
Search for noDefaultResolvers
entries and remove them:
Deprecation announcement for noDefaultResolvers
.
Schema Customization: Remove many
argument from childOf
directive
The many
argument is no longer needed for the childOf
directive in Gatsby v3:
Schema Customization: Consistent return for nodeModel.runQuery
For Gatsby v2, nodeModel.runQuery
with firstOnly: false
returns null
when nothing is found.
In v3 it returns an empty array instead.
To upgrade, find all occurrences of runQuery
(with firstOnly: false
or not set) and make sure checks for emptiness
are correct:
Note: When using argument firstOnly: true
the returned value is object
or null
.
So do not confuse those two cases.
Future Breaking Changes
This section explains deprecations that were made for Gatsby v3. These old behaviors will be removed in v4, at which point they will no longer work. For now, you can still use the old behaviors in v3, but we recommend updating to the new signatures to make future updates easier.
touchNode
For Gatsby v2 the touchNode
API accepted nodeId
as a named argument. This now has been deprecated in favor of passing the full node
to the function.
In case you only have an ID at hand (e.g. getting it from cache or as __NODE
), you can use the getNode()
API:
deleteNode
For Gatsby v2, the deleteNode
API accepted node
as a named argument. This now has been deprecated in favor of passing the full node
to the function.
@nodeInterface
For Gatsby v2, @nodeInterface
was the recommended way to implement queryable interfaces.
Now it is deprecated in favor of interface inheritance:
JSON imports: follow the JSON modules web spec
JSON modules are coming to the web. JSON modules only allow you to import the default export and no sub-properties. If you do import properties, you’ll get a warning along these lines:
webpack deprecation messages
When running community Gatsby plugins, you might see [DEP_WEBPACK]
messages popup during the “Building JavaScript” or the “Building SSR bundle” phase. These often mean that the plugin is not compatible with webpack 5 yet. Contact the Gatsby plugin author or the webpack plugin author to flag this issue. Most of the time Gatsby will build fine, however there are cases that it won’t and the reasons why could be cryptic.
Using fs
in SSR
Gatsby v3 introduces incremental builds for HTML generation. For this feature to work correctly, Gatsby needs to track all inputs used to generate HTML file. Arbitrary code execution in gatsby-ssr.js
files allow usage of fs
module, which is marked as unsafe and results in disabling of this feature. To migrate, you can use import
instead of fs
:
For Plugin Maintainers
In most cases, you won’t have to do anything to be v3 compatible. But one thing you can do to be certain your plugin won’t throw any warnings or errors is to set the proper peer dependencies.
gatsby
should be included under peerDependencies
of your plugin and it should specify the proper versions of support.
If your plugin supports both versions:
Known Issues
This section is a work in progress and will be expanded when necessary. It’s a list of known issues you might run into while upgrading Gatsby to v3 and how to solve them.
reach-router
We vendored reach-router to make it work for React 17. We added a webpack alias so that you can continue using it as usual. However, you might run into an error like this after upgrading:
To resolve the error above, make sure that you have updated all dependencies. It’s also possible that you have an outdated .cache
folder around. Run gatsby clean
to remove the outdated cache.
In some situations the webpack alias will be ignored, so you will need to add your own alias. The most common example is in Jest tests. For these, you should add the following to your Jest config:
Configuring using a jest.config.js
file:
Configuring using package.json
:
webpack EACCES
You might see errors like these when using Windows or WSL:
Gatsby will continue to work. Please track the upstream issue to see how and when this will be fixed.
yarn workspaces
Workspaces and their hoisting of dependencies can cause you troubles if you incrementally want to update a package. For example, if you use gatsby-plugin-emotion
in multiple packages but only update its version in one, you might end up with multiple versions inside your project. Run yarn why package-name
(in this example yarn why gatsby-plugin-emotion
) to check if different versions are installed.
We recommend updating all dependencies at once and re-checking it with yarn why package-name
. You should only see one version found now.
Legacy Browser (IE 11 Polyfill)
If you plan on targeting IE 11, you might run into an error like this:
To fix this, first create a polyfill for Object.setPrototypeOf()
in a file called setPrototypeOf.js
at the root of the site:
Then create a file called polyfills.js
, where you can add multiple polyfills (custom or imported):
Then inject them into webpack using the onCreateWebpackConfig
API in gatsy-node.js
during stage build-javascript
:
IE11 browser will now use this polyfill for Object.setPrototypeOf()
.