gatsby-plugin-schema-snapshot avoid WebP picture source from a Json data source

Created on 5 Mar 2020  路  4Comments  路  Source: gatsbyjs/gatsby

Hi, I have a project with some Json as data source: I added the gatsby-plugin-schema-snapshot plugin to speed up my build time and I saw that the images served by the gatsby-image component stopped delivering the WebP picture source.

Here a demo of the issue: https://codesandbox.io/s/infallible-snow-i60fj

I changed the image component to get the image childImage field querying the Json source (in the data directory) instead of querying the file system directly.

The source with the WebP format is missing:
image.

I don't knpw if it's correlated but during the build I have this warning message:
The type `File` does not explicitly define the field `childDataJson`. On types with the `@dontInfer` directive, or with the `infer` extension set to `false`, automatically adding fields for children types is deprecated. In Gatsby v3, only children fields explicitly set with the `childOf` extension

Thanks
valse

not stale confirmed GraphQL bug

All 4 comments

This is certainly a bug that I can reproduce.

As a workaround (for now), you can exclude gatsby-transformer-sharp from snapshot plugin:

    {
      resolve: `gatsby-plugin-schema-snapshot`,
      options: {
        update: true,
        exclude: {
          plugins: [`gatsby-transformer-sharp`],
        },
      },
    },

Which seems to make it work again.

I'm not sure where to attribute this bug to. With snapshot enabled (and not excluding types from sharp transformer), we get following types in schema:

type ImageSharpFluid {
  base64: String
  tracedSVG: String
  aspectRatio: Float!
  src: String!
  srcSet: String!
  srcWebp: String
  srcSetWebp: String
  sizes: String!
  originalImg: String
  originalName: String
  presentationWidth: Int
  presentationHeight: Int
}

type ImageSharp implements Node @childOf(mimeTypes: [], types: ["File"], many: false) @dontInfer {
  # removed fields other than "fluid" for brevity [...] 
  fluid(
    maxWidth: Int
    maxHeight: Int
    base64Width: Int
    grayscale: Boolean = false
    jpegProgressive: Boolean = true
    pngCompressionSpeed: Int = 4
    duotone: DuotoneGradient
    traceSVG: Potrace
    quality: Int
    jpegQuality: Int
    pngQuality: Int
    webpQuality: Int
    toFormat: ImageFormat = NO_CHANGE
    toFormatBase64: ImageFormat = NO_CHANGE
    cropFocus: ImageCropFocus = ATTENTION
    fit: ImageFit = COVER
    background: String = "rgba(0,0,0,1)"
    rotate: Int = 0
    trim: Float = 0
    sizes: String = ""

    """
    A list of image widths to be generated. Example: [ 200, 340, 520, 890 ]
    """
    srcSetBreakpoints: [Int] = []
  ): ImageSharpFluid
}

Now, resolver for fluid field works fine ( https://github.com/gatsbyjs/gatsby/blob/08d63c5e4ed25e9315101dec4fdb98186c527927/packages/gatsby-transformer-sharp/src/customize-schema.js#L357-L375 ), but resolver for srcWebp (and probably rest of those resolvers on field of ImageSharpFluid type, I just checked one) is not being hit ( https://github.com/gatsbyjs/gatsby/blob/08d63c5e4ed25e9315101dec4fdb98186c527927/packages/gatsby-transformer-sharp/src/customize-schema.js#L236-L252 ). So my gut tells me default resolver is used and because there is no actual srcWebp on object return by fluid - this just make it null?

My guess - ImageSharp type is defined with schema.buildObjectType which seems to play nicely with schema customization (so resolver is attached to type/field defined by schema.gql), while ImageSharpFluid is created using vanilla graphql-js(new GraphQLObjectType({ ... })) which potentially doesn't play nicely?

Thought @vladar?

@pieh This is another rabbit hole %) But I think I've found the root of the problem.

The issue is that the type ImageSharpFluid is created inline as a part of ImageSharp type definition:

https://github.com/gatsbyjs/gatsby/blob/627d552f2df48ab6354cb0e271338cc0dc56d1ea/packages/gatsby-transformer-sharp/src/customize-schema.js#L212-L222

In other words when we call createTypes(typeDefs) the type ImageSharpFluid is not in the list of typeDefs. It just sits somewhere deep inside ImageSharp type definition.

It works as long as you don't provide another typeDef for this type (we do this here in snapshot plugin). So instead of merging two typeDefs we rewrite the old typeDef with a new one created from AST (which doesn't have any custom resolvers).

We do this because we don't even know that there is an old ImageSharpFluid typeDef - it is not on our list.

I think the only way to fall into this trap is by using native GraphQL type definitions with schema csutomization. Type builders and AST probably don't have this problem (as you have to add all types to typeDefs directly).

So the unfortunate outcome of this is that we must additionally recursively walk through all fields and manually add any types defined inline into typeDefs.

(I personally think we should probably have fewer options for type definition formats in schema customization API but that's obviously not gonna happen anytime soon for BC and convenience reasons)

@valse This is a very rare and unfortunate edge case and the workaround suggested by @pieh should work for you for now. Still, we must address it in the core as it is a bug.

Yes I confirm that the workaround solve the problem, thanks: could I ignore the "File" warning too?

For the file warning - you could add the following to gatsby-node.js:

// in site's gatsby-node.js:
exports.createSchemaCustomization = ({ actions }) => {
  const typeDefs = `
    type DataJson implements Node @childOf(types: ["File"]) {
      id
    } 
  `
  actions.createTypes(typeDefs)
}

This should fix the warning. There is a bit more context on this in #19674

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  路  3Comments

benstr picture benstr  路  3Comments

mikestopcontinues picture mikestopcontinues  路  3Comments

jimfilippou picture jimfilippou  路  3Comments

brandonmp picture brandonmp  路  3Comments