Migration Guide: gatsby-source-prismic V2 to V3

This migration guide is going to help you upgrade the gatsby-source-prismic plugin from version V2 to V3 on your Gatsby project.


What has changed?

The v3 release includes three major features designed to improve the developer and content editor experience.

  • Schemas: Custom types and their fields are fully integrated into Gatsby's GraphQL data system.
  • Previews: Content editors can preview content before publishing without the need to rebuild the entire site.
  • Imgix-backed gatsby-image: Significantly reduce build times by utilizing Imgix's URL-based image manipulation when using gatsby-image.

This release also fixes several long-standing issues as a result of the new schema processing.

  • Gatsby now knows about fields that are defined on a custom type but have no content. This previously required developers to create "placeholder" documents with every field filled in with dummy content.
  • Rich Text and Title fields always return the expected result. Adding an image or embed as the first piece of content to a Rich Text field will not confuse the plugin.
  • Accessing linked documents on Link fields no longer requires using a strange single-item array.

Updating your dependencies

The very first thing you will need to do is update your dependencies.

Update Gatsby

Update your package.json to use at least v2.5.0 of Gatsby.

Copy
// Truncated package.json example file

{
  "dependencies": {
    "gatsby": "^2.5.0"
  }
}

Update gatsby-source-prismic version

Update your package.json to use v3 of gatsby-source-prismic.

Copy
// Truncated package.json example file

{
  "dependencies": {
    "gatsby-source-prismic": "^3.0.0"
  }
}

Update React

Previewing Prismic documents before publishing requires React hooks. If your project is not already on a release of React that includes hooks, update your version of react and react-dom.

Copy
// Truncated package.json example file

{
  "dependencies": {
    "react": "^16.8.0",
    "react-dom": "^16.8.0"
  }
}

Handling breaking changes

Provide Custom Type schemas

In v2, Custom Types and their fields were inferred based on the data stored in your Prismic repository. In cases where fields were empty in Prismic, Gatsby did not know of the fields and threw GraphQL errors if queried.

In v3, providing Custom Type schemas to the plugin is required. This tells Gatsby exactly which Custom Types and fields are available and their types even if they are empty in Prismic.

  1. Copy the JSON schema from Prismic for each Custom Type into your project. 〜/src/custom_types/<custom_type_id>.json is the recommended location.
  2. In gatsby-config.js, provide the schemas to the plugin options on the schemas key as an object mapping Custom Type ID to the JSON.
  • After
  • Before
Copy
// Truncated gatsby-config.js example file

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-prismic',
      options: {
        schemas: {
          page: require('./src/custom_types/page.json'),
          blog_post: require('./src/custom_types/blog_post.json'),
        },
       // All other plugin options...
      },
    },
  ],
}
Copy
// Truncated gatsby-config.js example file

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-prismic',
      options: {
       // All other plugin options...
      },
    },
  ],
}

Note that the key for each custom type is the API ID as set in Prismic. This is usually snakecase by default.

Access linked documents

In v2, Link fields that point to a Prismic document provided the document data on the example_link.document field as one item array. This was required to tell Gatsby that the document's type could be any of your custom types.

In v3, the example_link.document field is no longer an array but instead a direct reference to the linked document.

  1. In your GraphQL queries, add the fragment syntax to your document field if not already present. The fragment type must refer to the linked document's type.
  • After
  • Before
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_link {
          document {
            ... on PrismicOtherType {
              uid
            }
          }
        }
      }
    }
  }
`
Copy
query MyQuery {
  prismicPage {
    data {
      example_link {
        document {
          uid
        }
      }
    }
  }
}

2. When accessing document, use it like any other object field, not an array.

  • After
  • Before
Copy
const uid = data.prismicPage.data.example_link.document.uid
Copy
const uid = data.prismicPage.data.example_link.document[0].uid

Replace local images with Imgix-processed ones

In v2, Image fields provided a localFile field with a locally downloaded copy of the image. This allows gatsby-transformer-sharp to provide gatsby-image integration.

In v3, this can be replaced with Imgix's URL-based image manipulation. This can significantly reduce your build times if your site is image-heavy as no image processing is done at build-time.

Note that this is an optional, but recommended, change if your site does not use SVG placeholder images as it is currently not supported.

localFile will continue to be supported.

  1. In your GraphQL queries, replace localFile.childImageSharp.fluid and localFile.childImageSharp.fluid with fluid and fixed, respectively.
    Also replace GatsbyImageFluid and GatsbyImageFixed fragments with GatsbyPrismicImageFluid and GatsbyPrismicImageFixed.
  • After
  • Before
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_image {
          fluid(maxWidth: 1000) {
            ...GatsbyPrismicImageFluid
          }
        }
      }
    }
  }
`
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_image {
          localFile {
            childImageSharp {
              fluid(maxWidth: 1000) {
                ...GatsbyImageFluid
              }
            }
          }
        }
      }
    }
  }
`

2. When providing image data to gatsby-image, access the image data using the new path.

  • After
  • Before
Copy
const fluid = data.prismicPage.data.example_image.fluid
Copy
const fluid = data.prismicPage.data.example_image.localFile.childImageSharp.fluid

Replace shouldNormalizeImage with shouldDownloadImage

In v2, the shouldNormalizeImage plugin option allowed enabling or disabling downloading an image locally to make it available for gatsby-transformer-sharp. This defaulted to true for all images.

In v3shouldNormalizeImage is renamed to shouldDownloadImage and defaults to false for all images.

If you are using Imgix for all of your images, you can remove shouldNormalizeImage and leave shouldDownloadImage as the default.

  • After
  • Before
Copy
// Truncated gatsby-config.js example file

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-prismic',
      options: {
        // All other plugin options...
      },
    },
  ],
}
Copy
// Truncated gatsby-config.js example file

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-prismic',
      options: {
        // All other plugin options...
        shouldNormalizeImage: () => true,
      },
    },
  ],
}

If you wish to continue using gatsby-transformer-sharp for image transformations, change shouldNormalizeImage to shouldDownloadImage and ensure it returns true for all images requiring transformations.

  • After
  • Before
Copy
// Truncated gatsby-config.js example file

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-prismic',
      options: {
        // All other plugin options...
       shouldDownloadImage: () => true,
      },
    },
  ]
}
Copy
// Truncated gatsby-config.js example file

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-prismic',
      options: {
        // Along with your other options...
       shouldNormalizeImage: () => true,
      },
    },
  ]
}

Namespacing image thumbnails

In v2, Image fields contained the image thumbnail data at the same level as the primary image data. If you had a mobile thumbnail size, for example, the mobile field would be at the same level as the primary image's url field. This could potentially cause conflicts if a thumbnail name took the name of an existing image field.

In v3, image thumbnail fields are nested under a thumbnails field.

  1. In your GraphQL queries, move image thumbnails under the thumbnail field.
  • After
  • Before
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_image {
          url
          thumbnails {
            mobile {
              url
            }
          }
        }
      }
    }
  }
`
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_image {
          url
          mobile {
            url
          }
        }
      }
    }
  }
`

2. When accessing a thumbnail, use the thumbnails property.

  • After
  • Before
Copy
const mobileUrl = data.prismicPage.data.example_image.thumbnails.mobile.url
Copy
const mobileUrl = data.prismicPage.data.example_image.mobile.url

Using raw fields

In v2, certain field types contain a raw field populated with an untouched version of Prismic's data. For example, a Rich Text field's raw field would contain Prismic's custom representation of formatted text. This required you to list out all child fields, such as spans for a Rich Text field.

In v3raw is now a JSON type, removing the need to explicitly request child fields. All child fields will automatically be returned as a JSON object.

  • After
  • Before
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_rich_text {
          raw
        }
      }
    }
  }
`
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      data {
        example_rich_text {
          raw {
            spans
          }
        }
      }
    }
  }
`

Replace dataString with dataRaw

In v2dataString was available to allow querying the raw API data as a fallback. This was the node's data run through JSON.stringify.

In v3dataString is deprecated and replaced by dataRaw. Like the raw fields, dataRaw is now a JSON type, meaning you can query the field without needing to specify the child fields. Unlike dataStringdataRaw will return a JSON object, removing the need to run JSON.parse.

Note that the dataRaw field is not recommended and is included as an escape hatch if the untouched data is needed.

  • After
  • Before
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      dataRaw
    }
  }
`
Copy
export const query = graphql`
  query MyQuery {
    prismicPage {
      dataString
    }
  }
`

Things to know

Previews have their own plugin

If you want to enable the preview configuration, you will need to migrate the gatsby-source-prismic plugin from v3 to v4 and then configure the previews separately with the gatsby-plugin-prismic-previews plugin.

Type paths file in /public

The new schema system builds a map of your custom types' fields to their GraphQL type. This is used internally to ensure fields are transformed correctly depending on their type.

The same map is used in the front-end when previewing documents. In order for the preview system to use the map, the plugin saves a JSON file in your public folder. This file is then fetched in the browser during a preview.

The type paths file looks something like this:

Copy
// public/prismic-typepaths---my-repo-md5hash2049b789871e9494879b29464.json

;[
  { path: ['page'], type: 'PrismicPage' },
  { path: ['page', 'uid'], type: 'String' },
  { path: ['page', 'data'], type: 'PrismicPageDataType' },
  {
    path: ['page', 'data', 'parent'],
    type: 'PrismicLinkType',
  },
  {
    path: ['page', 'data', 'title'],
    type: 'PrismicStructuredTextType',
  },
  { path: ['page', 'data', 'featured_image'], type: 'PrismicImageType' },
  {
    path: ['page', 'data', 'body'],
    type: '[PrismicPageBodySlicesType]',
  },
  { path: ['page', 'data', 'body', 'text'], type: 'PrismicPageBodyText' },
  {
    path: ['page', 'data', 'body', 'text', 'primary'],
    type: 'PrismicPageBodyTextPrimaryType',
  },
  {
    path: ['page', 'data', 'body', 'text', 'primary', 'text'],
    type: 'PrismicStructuredTextType',
  },
]

You can override the filename's prefix in your plugin options with the typePathsFilenamePrefix option.


Was this article helpful?
Not really
Yes, Thanks

Can't find what you're looking for? Get in touch with us on our Community Forum.