Modifying the component registration Next.js & Sitecore
In this article a solution for excluding *.stories.tsx and *.tests.tsx files in Sitecore headless with next.js JSS version 21 is discussed.
December 09, 2023 • 4 min read • Sitecore
Introduction
When working with Sitecore headless, in some form or another there is some code in your repository which controls how your components are registered in such a manner that it can respond to the LayoutService response.
You might know it as the componentFactory file or as the componentBuilder file. In any case this file is generated by some other piece of code, which coincidently is also a part of your repository.
Before JSS 21 came along that code was 100% a part of your (local) repository, namely in the scipts folder you had 2 files of interest: generate-component-factory.ts
(or generate-component-builder.ts
) and utils.ts
.
Within the utils.ts file was a function of interest, namely the getItems<Item>
function. That function relies on a RegExp which scans a folder and any sub-folders for files which end in js / jsx / ts / tsx.
This however poses a problem for frontend developers who are used to grouping their tests and storybook files together with the components.
Because you had acces to the generator code in your local repo before JSS 21 you could easily modify it to your own needs. With the introduction of version 21 that code is no longer locally available.
It has instead moved over to the @sitecore-jss/sitecore-jss-dev-tools
package. This isn't a bad thing in and of itself, but I sure wish the Sitecore team had the foresight to give developers control over the RegExp.
Because this currently isn't the case just yet you'll have to make do with a bit of code duplication if you are after controlling which files get included.
Let's code!
The solution
Before you dive in, a small disclaimer: this has been written for version 21.5.0 and at the time of writing there are canary releases for 21.7 which might result in small changes. With that out of the way, here's how I did it:
As mentioned previously the getItems<Item>
function is the one we're interested in and as such the one we're going to overwrite.
The problem lies in the fact that the only exported members from the @sitecore-jss/sitecore-jss-dev-tools/nextjs
package are generateComponentBuilder and getComponentBuilderTemplate.
This makes for a lot of code duplication in your local repo, which I'm not too happy about, but for now it's the only way to achieve what we want.
I'm taking the xmcloud-foundation-head repository as a base, which can be found here.
In this repository (which you likely have cloned for starting headless development with xmcloud) you want to locate a couple of files:
packages/sitecore-jss-dev-tools/src/templating/nextjs/generate-component-builder.ts
packages/sitecore-jss-dev-tools/src/templating/utils.ts
packages/sitecore-jss-dev-tools/src/templating/components.ts
copy those over, I decided to make my folder structure as follows:
generate-component-builder/
├─ overwrites/
│ ├─ components.ts
│ ├─ generate-component-builder.ts
│ ├─ utils.ts
If you decide to adhere to that same structure, make the changes to your imports in the generate-component-builder.ts file as follows:
import path from 'path';
import fs from 'fs';
import { getComponentBuilderTemplate } from '@sitecore-jss/sitecore-jss-dev-tools/nextjs'
import { ComponentFile, PackageDefinition, getComponentList } from './components';
import { watchItems } from './utils';
And on line 43 of the utils file change the RegExp to:
fileFormat = new RegExp(/(.+)(?<!\.d|\.test|\.spec|\.stories)\.([jt]sx?)$/),
Breakdown
There is a lot happening in the code provided by the Sitecore team, but luckily we can leave a lot as is. I must reiterate though that I think it's a shame we are forced to duplicate the code provided because they do not give us access to it.
Conclusion
I do hope that the Sitecore team decides to give us more control over the generation of this file in the future again and I have 2 suggestions for this: Either export more members than just the generateComponentBuilder and getComponentBuilderTemplate functions for consumption by developers, so that we can access the RegEx. Or change the code so that the fileFormat RegEx is read from a config somewhere.
Personally I like the second option the best, making this code obsolete. Untill then I hope this suits your needs!