When is it a Good Time to Utilize Integrated GraphQL?
There are a lot of use cases for when you need to investigate utilizing Integrated GraphQL. You will undoubtedly encounter one of these scenarios as a front-end developer working with a Sitecore back-end.
Reducing Unnecessary Data Load
Integrated GraphQL can be used to refine your queries if your components are importing big, complicated data structures from Sitecore items, many of which contain fields you don't really require. This saves needless work, boosts performance, and minimizes front-end payloads.
Enhancing Experience Editor Compatibility
Using jsonValue
in Component GraphQL Query when working with Sitecore's Experience Editor or Pages guarantees that fields stay editable while preserving effective front-end rendering. This is essential for preserving content editing flexibility without compromising efficiency.
Optimizing API Calls for Front-End Rendering
By embedding the required queries directly in Component GraphQL Query, unnecessary API calls are avoided as opposed to creating several GraphQL queries from Next.js components (such as retrieving URLs separately). This makes your codebase easier to maintain, lowers latency, and streamlines data fetching logic.
For this article, I wanted to create a component that pulls in the summary heading, summary description and a summary image from a page to display within a component. A featured article or page component. We’ll call it a Resource List for the purposes here. Each “page” being brought in, we’ll call a Resource List Card. For our example, we’re creating a list of pages related to the Empire, from Star Wars. Nothing too exciting, but it will fit our purpose.
While looking at the component we’re going to build it might not seem too crazy. What’s hidden underneath, however, is the fact that each of those three pages referenced on the right-side, actually have a lot of other fields on them, some of which contain a lot of data. Now it might not always be a single field containing a lot of data, it could very well be that an item has dozens of fields that are irrelevant to what we’re using it for.
So while we might only want three particular fields for our component, this giant Content
field will also come with it. And we can see that it did when we look at the output source when the component is on the page. Completely unnecessary.
So what do we do?
Using the Integrated GraphQL
Nestled deep with the JSON Rendering you will find a field called Component GraphQL Query
. It’s often overlooked as for the most part, when a component is being build, the datasource item probably only contains what is absolutely necessary. But this isn’t always the case. As we’ve seen above.
What Does the Structure of the GraphQL Look Like?
While this is indeed GraphQL, there are key differences as it effectively acts as a function with potential parameters that can be passed through. Those parameters are:
- $datasource
- $contextItem
- $language
So for our function in particular, we’re able to create it as such:
query ResourceListCardQuery($datasource: String!) {
datasource: item(path: $datasource, language: "en") {
id
name
url {
path
}
... on ContentPage{
summaryHeading{
jsonValue
}
summaryDescription{
jsonValue
}
summaryImage{
jsonValue
}
}
}
}
In the above script, ContentPage
is our template with summaryHeading
which is a Field<string>
, summaryDescription
is a RichTextField
, and summaryImage
is an ImageField
. By using jsonValue
we ensure that the fields are still editable within Experience Editor and Pages.
We can verify the output by using the IDE locally.
What Do We Change on the Front-end Next.js Component?
While the changes on the back-end are relatively simple you might be thinking, but I’ve already got my component working, do I have to rewrite it all? The answer, thankfully, is no, you do not.
Let’s Organize Our Types
Initially we had the following type structure setup for our component.
type ResourceListCardFields = {
summaryHeading: Field<string>;
summaryDescription: RichTextField;
summaryImage: ImageField;
url: string;
};
interface ResourceListCardProps extends ComponentProps {
fields: ResourceListCardFields;
}
To that, I’ve now added in an additional type.
type IntegratedResourceListCardFields = {
data: {
datasource: {
summaryHeading: {
jsonValue: Field<string>;
};
summaryDescription: {
jsonValue: RichTextField;
};
summaryImage: {
jsonValue: ImageField;
};
url: {
path: string;
};
};
};
};
Let’s Update Our getStaticProps
While our component already had a getStaticProps
to provide us with the URL to the item by performing an item lookup via a GraphQL query, we no longer need that as we’re now getting that as part of the integrated component GraphQL query within the JSON Rendering itself. As such, this is now one fewer call on the front-end.
const GetComponentProps = async (rendering: ComponentRendering, layoutData: LayoutServiceData) => {
// IntegratedResourceListCardFields is the type of the fields object coming from Component GraphQL Query
const newFields = rendering.fields as unknown as IntegratedResourceListCardFields;
try {
return {
fields: {
summaryHeading: newFields?.data?.datasource?.summaryHeading?.jsonValue,
summaryDescription: newFields?.data?.datasource?.summaryDescription?.jsonValue,
summaryImage: newFields?.data?.datasource?.summaryImage?.jsonValue,
url: newFields?.data?.datasource?.url?.path,
},
};
} catch (error) {
console.error('Error assigning fields:', error);
return {
rendering: { ...rendering },
route: layoutData?.sitecore?.route,
};
}
};
export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData) => {
return await GetComponentProps(rendering, layoutData);
};
With doing it this way, we’ve minimally impacted the way the component functions. In fact, I didn’t even touch the actual rendering portion of the component’s result.
What are the Savings Using Component GraphQL Query?
Well in this example, the savings were minimal. Even looking at the view-source alone, I only saved 2kB which you could certainly argue was a wasted effort. However, this was a very simple case. If I had more metadata fields, or additional referenced items on that page, that size savings could grow quite quickly.
The important thing to realize is that while in the beginning, it might look like a drop in the bucket, keeping your eye open for savings could have great benefits in the future.
What are the Downsides to Component GraphQL Query?
The most noticeable downside is that if this is something you and your team are not used to using, if you decide to or requirements change in the future and you have to add a field, you could very easily forget this is in place and then waste time trying to figure out why a particular field is not showing up.
The other downside is potentially increased complexity now required in the front-end to support it. The more and more fields your component requires the additional steps required to support them. It ultimately becomes a judgement call. That said, in my case because I needed to do a GQL lookup to get the URL of the item anyways, this actually reduced code and build time for the component.
Prefer a visual guide? I've got you covered — check out this video for a walkthrough of everything covered here.