Fix: Prismic Preview stuck on loading Gatsby-Plugin-Image
A client of mine wanted a Prismic Preview functionality on their Gatsby website. That was easy to add by following Prismic's own documentation. However, when trying to preview some of the Gatsby project's pages, all I got was a white screen and the text “loading”. The page was stuck with an infinite loading screen, but kept refreshing the data source on the browser's inspector screen. Sounds similar? Here’s how I fixed it.
The problem
The infinite loading appeared on some pages, which helped to narrow it down: it was because I used Gatsby-Plugin-Image to optimize the Prismic images and to download them locally on the site. The Prismic Preview uses the page template to build its previews, which meant that it tried to use the Gatsby-Plugin-Image's local image functionality – which resulted in a failure as it’s meant to be run on build time, not on live site. This caused the page to not load as it couldn't render properly – hence the white screen with "loading" text stuck on the screen.
The solution
Your Gatsby Image source looks probably something like this:
1<GatsbyImage2 image={slice.primary.hero_background_image.localFile.childImageSharp.gatsbyImageData}3 alt={slice.primary.hero_background_image.alt}4/>
The part that is causing the render to fail is “localFile.childImageSharp.gatsbyImageData” as that part could not be generated without Gatsby’s build process.
First solution is to add question marks behind every word of the GraphQL source. Like this:
1<GatsbyImage2 image={slice.primary.hero_background_image.localFile?.childImageSharp?.gatsbyImageData}3 alt={slice.primary.hero_background_image?.alt}4/>
This means that the query is optional: if it doesn't return anything, then just render the page without it. In this case, render the page without any images that use Gatsby-Plugin-Image. This is a workaround, and I will provide a better solution next.
Now to the real fix. The following lines of code will get rid of the issue:
1{slice.primary.hero_background_image.localFile?.childImageSharp?.gatsbyImageData !== null ?2 <GatsbyImage3 image={slice.primary.hero_background_image.localFile?.childImageSharp?.gatsbyImageData}4 alt={slice.primary.hero_background_image.alt}5 />6 :7 <img8 className="gatsby-image-wrapper"9 src={slice.primary.hero_background_image.url}10 alt={slice.primary.hero_background_image.alt}11 />12}
This is a conditional render that checks if the Gatsby-Plugin-Image GraphQL path can be accessed. If it can, it shows the Gatsby Image, and if not, it shows a regular image element. This is perfect, because the conditional render happens only on both build time and on Prismic Preview functionality. It doesn't add any extra weight on the actual live page, the only thing getting more complicated is the template file. This means that the visitor will always get the optimized Gatsby Image, whereas any editor using Prismic Preview will get a regular image element that will display the correct image that is shown in the editor's own Prismic Document.
Obviously make sure you change the GraphQL sources to match your own project. Simply use a regular <img> element to access the URL of the Prismic file instead of using localFile.
I hope this helped you! I spent a full day trying to debug the issue.