cloudinary-community / gatsby-transformer-cloudinary

Use Cloudinary images with gatsby-image for high performance and total control!
https://gatsby-transformer-cloudinary.netlify.app/
MIT License
69 stars 28 forks source link

Cannot query gatsbyImageData via Cloudinary app on Contentful #238

Open jasloe opened 1 year ago

jasloe commented 1 year ago

I am trying to use this project to transform Cloudinary-hosted images passed through Contentful with unfortunately mixed results.

In short, I have a Contentful environment with a content type ("Artwork"). The content type includes a JSON Object field ("cloudinaryImage") connected to the Contentful Cloudinary app. The app is configured correctly and returning data.

gatsby-config.js contains:

    {
      resolve: `gatsby-source-cloudinary`,
      options: {
        cloudName: [redacted],
        apiKey: [redacted],
        apiSecret: [redacted],
        tags: true,
        context: true,
        prefix: [redacted],
      },
    },
  {
      resolve: `gatsby-transformer-cloudinary`,
      options: {
        transformTypes: [`CloudinaryMedia`, `contentfulArtworkCloudinaryImageJsonNode`],
        defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
      },
    },
    `gatsby-plugin-image`,

template/artwork.js contains (simplified for brevity):

const Artwork = ({ data }) => (
  <>
    {data.contentfulArtwork.id}
    {data.contentfulArtwork.title}
    {data.contentfulArtwork.cloudinaryImage.map((image) => (
      <div key={image.id}>
        {image.id}
        <GatsbyImage image={getImage(image)} alt="testing" />
      </div>
    ))}
  </>
);

export default Artwork;

export const artworkQuery = graphql`
  query ($ArtworkId: String!) {
    contentfulArtwork(id: { eq: $ArtworkId }) {
      id
      title
      __typename
      cloudinaryImage {
        id
        __typename
        gatsbyImageData(width: 200, height: 200)
      }
    }
  }
`;

Looking at the console output, gatsbyImageData returns null...

{
    "id": [redacted],
    "title": "Example",
    "__typename": "ContentfulArtwork",
    "cloudinaryImage": [
        {
            "id": [redacted],
            "__typename": "contentfulArtworkCloudinaryImageJsonNode",
            "gatsbyImageData": null
        },
        {
            "id": [redacted],
            "__typename": "contentfulArtworkCloudinaryImageJsonNode",
            "gatsbyImageData": null
        }
    ]
}

...and throws an error:

[gatsby-plugin-image] Missing image prop

Looking at the stack trace, the error happens here:

export const GatsbyImage: FunctionComponent<GatsbyImageProps> = memo(
  function GatsbyImage(props) {
    if (!props.image) {
      if (process.env.NODE_ENV === `development`) {
        console.warn(`[gatsby-plugin-image] Missing image prop`)
      }

      return null
    }

    if (!gatsbyImageIsInstalled() && process.env.NODE_ENV === `development`) {
      console.warn(
        `[gatsby-plugin-image] You're missing out on some cool performance features. Please add "gatsby-plugin-image" to your gatsby-config.js`
      )
    }

    return createElement(GatsbyImageHydrator, props)
  }
)

GatsbyImage.propTypes = propTypes
GatsbyImage.displayName = `GatsbyImage`

Not sure where to go with this. I'm able to query and render CloudinaryMedia to the browser without any problem. gatsby-plugin-image is working fine with both Contentful-hosted and locally hosted images.

jasloe commented 1 year ago

Just replicated this issue on a clean Gatsby codebase, a new Contentful space, and a new Cloudinary environment.

Confirming that this works as expected:

query MyQuery {
  allCloudinaryMedia {
    nodes {
      gatsbyImageData
    }
  }
}

But this doesn't:

query MyQuery {
  contentfulArtwork {
    images {
      gatsbyImageData
    }
  }
}

returns...

{
  "data": {
    "contentfulArtwork": {
      "images": [
        {
          "gatsbyImageData": null
        }
      ]
    }
  },
  "extensions": {}
}

My environment:

  System:
    OS: macOS 12.6.3
    CPU: (12) x64 Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.15.0 - ~/.nvm/versions/node/v18.15.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.15.0/bin/yarn
    npm: 9.5.0 - ~/.nvm/versions/node/v18.15.0/bin/npm
  Browsers:
    Firefox: 89.0.2
  npmPackages:
    gatsby: ^5.11.0 => 5.11.0
    gatsby-plugin-image: ^3.11.0 => 3.11.0
    gatsby-plugin-sharp: ^5.11.0 => 5.11.0
    gatsby-source-cloudinary: ^0.5.1 => 0.5.1
    gatsby-source-contentful: ^8.11.0 => 8.11.0
    gatsby-transformer-cloudinary: ^4.4.0 => 4.4.0
    gatsby-transformer-sharp: ^5.11.0 => 5.11.0
  npmGlobalPackages:
    gatsby-cli: 5.7.0
olavea commented 1 year ago

I'll ask my senior dev to send you an email. I'm sure she would like us to have a chat with you about this problem. It is relevant to our work. 😺 👍

raae commented 12 months ago

The shape of contentfulArtworkCloudinaryImageJsonNode does not match the shape that the transformer plugin expects, but you may connect the sourced CloudinaryMedia to your contentfulArtworkCloudinaryImageJsonNode nodes.

exports.createSchemaCustomization = async ({ actions }) => {
  actions.createTypes(`
    type contentfulArtworkCloudinaryImageJsonNode implements Node {
      cloudinaryMedia: CloudinaryMedia @link(by: "publicId", from: "public_id")
    }
  `);
};

Then you'd need to add one level to get the gatsbyImageData query, doing

       cloudinaryMedia {
          gatsbyImageData(width: 200)
        }
AminPainter commented 8 months ago

Try this: https://github.com/cloudinary-devs/gatsby-transformer-cloudinary/issues/246#issuecomment-1794309309

raae commented 8 months ago

Thank you @AminPainter !

raae commented 4 months ago

I would be forever grateful if you tested the newest beta jasloe. It adds support by letting you configure the mapping of data.

yarn add gatsby-transformer-cloudinary@4.6.0-beta.1

Take a look at the documentation and let me know how it goes so I may improve if needed.

raae commented 3 weeks ago

@jasloe have you been able to test the 4.6.0-beta.1? Looking to make this a current version, but would love an external test before I do.