Override the default directory used by the disk-based editing cache implementation
The disk-based cache used for integrating JSS Next.js apps with advanced Sitecore content and layout editors uses, by default, the operating system temp
directory. When hosting your Next.js application on Vercel, the default temp
directory works fine. However, on other platforms, using the default temp
directory can cause the editing data middleware to malfunction, resulting in intermittent 500 errors in Experience Editor.
You must override the directory used for the disk-based cache to resolve the errors.
To override the default temp
directory:
-
In a new file, for example,
/src/lib/editing.ts
, create an editing data disk cache, overriding the defaulttemp
directory with one of your choosing and a new editing data service that uses the new cache:RequestResponseimport { EditingDataDiskCache, BasicEditingDataService, ServerlessEditingDataService } from '@sitecore-jss/sitecore-jss-nextjs/editing'; // Override the default editingDataDiskCache with an accessible temp directory export const myEditingDataDiskCache = new EditingDataDiskCache('C:\\temp'); // Override default editingDataService to use myEditingDataDiskCache for BasicEditingDataService export const myEditingDataService = process.env.VERCEL ? new ServerlessEditingDataService() : new BasicEditingDataService({ editingDataCache: myEditingDataDiskCache, });
-
In the
/src/pages/api/editing/data/[key].ts
file, update theEditingDataMiddleware
handler to use the new editing data disk cache:RequestResponseimport { EditingDataMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/editing'; import { myEditingDataDiskCache } from 'lib/editing'; /** * This Next.js API route is used to handle Sitecore editor data storage and retrieval by key * on serverless deployment architectures (such as Vercel) via the `ServerlessEditingDataService`. * The `EditingDataMiddleware` expects this dynamic route name to be '[key]' by default but can * be configured to use something else with the `dynamicRouteKey` option. */ // Bump body size limit (1mb by default) and disable response limit for Sitecore editor payloads // See https://nextjs.org/docs/api-routes/request-helpers#custom-config export const config = { api: { bodyParser: { sizeLimit: '2mb', }, responseLimit: false, }, }; // Wire up the EditingDataMiddleware handler const handler = new EditingDataMiddleware({ editingDataCache: myEditingDataDiskCache, }).getHandler(); export default handler;
-
In the
/src/pages/api/editing/render.ts
file, update the existing handler with a new instance of theEditingRenderMiddleware
class that uses the new editing data service:RequestResponseimport { EditingRenderMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/editing'; import { myEditingDataService } from 'lib/editing'; /** * This Next.js API route handles POST requests from Sitecore editors. * This route should match the `serverSideRenderingEngineEndpointUrl` in your Sitecore configuration, * which is set to "http://localhost:3000/api/editing/render" by default (see \sitecore\config\nextjs-app.config). * * The `EditingRenderMiddleware` will * 1. Extract editing data from the Sitecore editor POST request * 2. Stash this data (for later use in the page render request) via an `EditingDataService`, which returns a key for retrieval * 3. Enable Next.js Preview Mode, passing our stashed editing data key as preview data * 4. Invoke the actual page render request, passing along the Preview Mode cookies. * This allows retrieval of the editing data in preview context (via an `EditingDataService`) - see `SitecorePagePropsFactory` * 5. Return the rendered page HTML to the Sitecore editor */ // Bump body size limit (1mb by default) and disable response limit for Sitecore editor payloads // See https://nextjs.org/docs/api-routes/request-helpers#custom-config export const config = { api: { bodyParser: { sizeLimit: '2mb', }, responseLimit: false, }, }; // Wire up the EditingRenderMiddleware handler const handler = new EditingRenderMiddleware({ editingDataService: myEditingDataService, }).getHandler(); export default handler;
-
Update the
src/lib/page-props-factory/plugins/preview-mode.ts
file so that thePreviewModePlugin
class uses the new editing data service:RequestResponseimport { myEditingDataService } from 'lib/editing'; import { SitecorePageProps } from 'lib/page-props'; import { GetServerSidePropsContext, GetStaticPropsContext } from 'next'; import { Plugin } from '..'; class PreviewModePlugin implements Plugin { order = 0; async exec(props: SitecorePageProps, context: GetServerSidePropsContext | GetStaticPropsContext) { if (!context.preview) return props; // If we're in preview (editing) mode, use data already sent along with the editing request const data = await myEditingDataService.getEditingData(context.previewData); if (!data) { throw new Error( `Unable to get editing data for preview ${JSON.stringify(context.previewData)}` ); } props.locale = data.language; props.layoutData = data.layoutData; props.dictionary = data.dictionary; return props; } } export const previewModePlugin = new PreviewModePlugin();