-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve contentful rich text experience #24221
Comments
We’ve seen that when building our site, we frequently encounter out of memory errors when working with Contentful data that has Rich Text fields. This seems to be a fundamental architectural issue with gatsby-source-contentful plugin. Gatsby does not use Contentful’s GraphQL design where text structure and links are distinct fields that can be queried independently (represented as Our content model includes embedded links between blog post nodes for SEO purposes, which means that Gatsby could hypothetically end up eagerly fetching and serialising hundreds of nested nodes in a single rich text field. We have seen that blog posts frequently contain multiple gigabytes of data. This could be fixed by implementing Rich Text fields in the same way that Contentful does (using two fields). This would allow the consumer to specify which fields they need from embedded nodes. GraphQL, by design, does not allow users to construct queries that would recursively fetch data. |
Hi @joshduck checking if https://www.contentful.com/developers/docs/tutorials/general/rich-text-and-gatsby/ will help resolve some of the issues you're seeing. |
@amandasage, no. That's what we're using right now. The problem is that the JSON object referenced in that documentation page ( Out fix so far has been to patch |
Hey @joshduck I will open a ticket on Contentful's side to look at memory issues + sync for preview |
I am currently actively working on this issue and want to share my current status to the community: SummaryComplex data models in combination with Contentful rich text can cause issues. The code can become slow, the worst case will crash the build process. Why does this happen?The root of the issue is how resolving references works in combination with Contentful Rich Text. This PR ensures newly referenced entries will be resolvable: #15084 At the moment, the rich text document gets serialized as a string and stored into graphql. As soon an entry within a rich text node leads somehow to a circular reference pattern, the string resolving can crash the build process. Fixes that did not workAs quick-win I tried to replace the serializer with other packages form npm or node internals. All led to similar issues. And even when we would fix it that way, we can't be sure which data we will receive in the resolved references as all these serializers will add How we can fix itTo fix this issue, we have to change the way Gatsby renders Contentful Rich Text Documents. As Gatsby developer, I want to have full control of which data will be resolved, at best straight in my graphQl query. When rendering the Rich Text Field, I just want to pass the Rich Text Document to a function and output the result via JSX. This how it may work:
richTextField {
references {
... on ContentfulTypeA {
contentful_id # properly required
title
}
... on ContentfulTypeB {
contentful_id # properly required
title
customField
}
}
}
This is how using Contentful Rich Text could look like:import React from 'react'
import * as propTypes from 'prop-types'
import { renderRichText } from 'gatsby-source-contentful'
function PageTemplate({ data }) {
const { title, richTextField } = data.contentfulPage
return (
<div>
<h1>{title}</h1>
{renderRichText(richTextField)}
</div>
)
}
PageTemplate.propTypes = {
data: propTypes.object.isRequired,
}
export default PageTemplate
export const pageQuery = graphql`
query pageQuery($id: String!) {
contentfulPage(id: { eq: $id }) {
title
richTextField {
references {
... on ContentfulTypeA {
contentful_id
title
}
... on ContentfulTypeB {
contentful_id
title
customField
}
}
}
}
}
` I'll open a PR soon to share my current status of the code :) |
@joshduck thanks for sharing your insight on this! I'm having the same problem and wondering how you went about patching @axe312ger excited about your solution. One other issue you might inadvertently fix is that currently the resolved entries that are part of the serialized JSON do not include any incoming link references. For example, a model |
Our patch is quite heavily intertwined with a few other patches making it hard to publish, but the main thing that we do is to strip out anything beyond a certain depth within the |
One of the biggest issue that a lot of us encountered with Rich Text and Gatsby is that there was no easy way to use Gatsby Image inside rich text. Since rich text only returns the image object and we cannot query for the fluid/fixed props that we're used to when working with contentful image, we had to resort to hacky ways. The current solutions in the wild are:
The former causes performance issues while the latter requires a lot of boiler plate code. I found that there's actually a simpler solution which uses the APIs inside I have successfully used it in production and so far haven't had any issues. I created a PR for it but here's how it would look like: import GatsbyImg from 'gatsby-image'
import { resolveFluid } from 'gatsby-source-contentful'
const options = {
[BLOCKS.EMBEDDED_ASSET]: (node) => {
const { file, title } = data.target.fields
const image = {
file: file["en-US"]
}
const fluidProps = resolveFluid(image, { maxWidth: 600 })
return <GatsbyImage fluid={fluidProps} alt={title['en-US']} />
}
} Here's the gist if you want to implement it now. |
The PR is was talking about above: #24905 |
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
@axe312ger this seems problematic if we want to render the rich text differently for various use cases. As an example, rich text used as the body of a blog post will have use different react components to rich text used in the description area of a card widget. Currently, code consuming rich text can directly pass render customizations to import {
documentToReactComponents,
Options,
} from "@contentful/rich-text-react-renderer";
import { Document } from "@contentful/rich-text-types";
export interface RichTextProps {
document: Document;
renderMark?: Options["renderMark"];
renderNode?: Options["renderNode"];
renderText?: Options["renderText"];
}
const RichText: React.FC<RichTextProps> = props => {
// calls documentToReactComponents with any options passed into props
} Question: How do you suggest we apply customizations to rich text rendering in those cases? |
@disintegrator we just released an update that covers your suggestions as well. See the code at: |
Thanks for the update @axe312ger For anyone that comes across memory issues with gatsby-source-contentful. This is likely because of how rich text is handled. In our gatsby project the only property we use out of rich text fields is {
contentfulBlogPost(id: {eq: $id}) {
title
body {
json
}
}
} A lot of the work that Gatsby does around rich text is on inferring the type for the All in all, there is a lot of wasted work and memory going into data we never look at in our project. Our solutionWe use
Below, I've attached the patch-package patch file that targets gatsby-source-contentful @ 2.3.32 with the changes I listed. I hope it helps you overcome slow builds and OOM errors until the upcoming rebuild of gatsby-source-contentful! 😄 |
@disintegrator did you find a chance to try the new version of See: #25249 |
@axe312ger that's next on my list to evaluate. I need a quick solution to my problem based on the released version of the contentful plugin. |
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
@daydream05 yes please have a look at the new version from #24905 and give feedback :) |
Started using it for a new client project and everything thing looks good so far! Great work on this @axe312ger . Waited for this rich text update for so long. One issue though regarding loading multiple contentful spaces in the same Gatsby app, it seems that it’s broken. (The content models for the 2nd space is not loading any attributes or data, just the name of the content model) I’ll create an issue tomorrow. |
Thank you, @disintegrator Just wanted to say 'thank you' for attaching this. I've been beating my head against a wall for weeks now trying to track down a solution. I spoke too soon. Applied the patch this morning and while schema generation was much faster, everything dies after when trying to visit a page or right before. Going to give migration an attempt! |
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes gatsbyjs#24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
Also want to say thanks to @axe312ger who has been pushing through these issues to build a better Rich Text framework. |
@bsgreenb thanks! you are welcome! :) We pushing further, release is coming closer :) |
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes gatsbyjs#24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
* Allow circular references * Improve performance and reduce RAM footprint * Query referenced entries and assets via GraphQL fixes #24221 BREAKING CHANGE: * Entities references in Rich Text fields are no more automatically resolved * Use the `raw` subfield instead of `json` * Use GraphQL to define your referenced data with the new `references` field * Removes the `resolveFieldLocales` as the new `references` field automatically resolves locales * To render Rich Text fields unse the new `renderRichText()` function from `gatsby-source-contentful/rich-text`
Hi, thanks for this. We're having trouble querying raw and references. Also, we're using the plugin gatsby-plugin-snapshot, would it be possible to share what the RichTextNode should look like in schema.gql now with these changes? |
@Jordan314 please file a new issue, this one has been merged. But one thing you should try first is to update to the newest version of I'll close this issue as it has been resolved and merged. If you were inclined to post a reply to it please open a new issue and refer to this one. Thank you. |
Summary
I'm not super familiar with contentful rich text. For now this is just a placholder issues.
The text was updated successfully, but these errors were encountered: