XM Cloud - SSG only specific language pages
Summary
We had a next.js website hosted in Vercel with thousands of pages of content across 6 different languages. The site was based on the Sitecore XM Cloud Starter Repository (opens in a new tab), which comes with a Sitecore JSS SXA Headless Next.js application.
As the content grew, we started to exceed the Vercel 45 minute build time. We wanted to continue to leverage Static Site Generation (SSG) on our website, but reduce the time and page count to help our our build time. After some investigation we realized that most of our traffic was to our English and Spanish language content. So we decided to modify our code base to accommodate this.
The Solution
We identified that the graphql sitemap service was being used to gather all the pages for SSG. Specifically, in the lib
folder there was a plugin named grpahql-sitemap-service.ts
.
In the plugin we saw a class called GraphqlSitemapServicePlugin
and within that plugin there was a return
with the following code:
return process.env.EXPORT_MODE
? this._graphqlSitemapService.fetchExportSitemap(config.defaultLanguage)
: this._graphqlSitemapService.fetchSSGSitemap(context?.locales || []);
This code stated that all locales were used to generate the SSG sitemap. That means that all locales defined in our next.config
would be generated.
To address this, we added a new variable in our .env
called SSG_ALLOWED_LOCALES
and set only the languages that we wanted to be statically generated:
SSG_ALLOWED_LOCALES=en,es-mx
We updated the code to:
return process.env.EXPORT_MODE
? this._graphqlSitemapService.fetchExportSitemap(config.defaultLanguage)
: this._graphqlSitemapService.fetchSSGSitemap(
process.env.SSG_ALLOWED_LOCALES?.split(',') ?? (context?.locales || [])
);
Now we were only generating content for these two languages specified and our build time greatly reduced. Pages that weren't built during build time would build on initial page load and then enter into our Incremental Static Regeneration (ISR) settings like any other page.
The final code for grpahql-sitemap-service.ts
:
import {
MultisiteGraphQLSitemapService,
SiteInfo,
StaticPath,
constants,
} from '@sitecore-jss/sitecore-jss-nextjs';
import clientFactory from 'lib/graphql-client-factory';
import { siteResolver } from 'lib/plugins/site-resolver';
import { GetStaticPathsContext } from 'next';
import config from 'temp/config';
import { SitemapFetcherPlugin } from '..';
class GraphqlSitemapServicePlugin implements SitemapFetcherPlugin {
_graphqlSitemapService?: MultisiteGraphQLSitemapService;
constructor() {
this._graphqlSitemapService =
process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED
? undefined
: new MultisiteGraphQLSitemapService({
clientFactory,
sites: [...new Set(siteResolver.sites.map((site: SiteInfo) => site.name))],
});
}
async exec(context?: GetStaticPathsContext): Promise<StaticPath[]> {
if (!this._graphqlSitemapService || process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
return [];
}
return process.env.EXPORT_MODE
? this._graphqlSitemapService.fetchExportSitemap(config.defaultLanguage)
: this._graphqlSitemapService.fetchSSGSitemap(
process.env.SSG_ALLOWED_LOCALES?.split(',') ?? (context?.locales || [])
);
}
}
export const graphqlSitemapServicePlugin = new GraphqlSitemapServicePlugin();
Conclusion
XM Cloud is easy to modify and fine tune the code and plugins to your liking. With a simple change to what content we SSG we were able to drastically reduce our build time and keep our project performant for key traffic languages.