We had a hands on experience of how this can affect your Sitecore environment. We started analyzing and breaking down requirements on a project with smaller simpler reusable components but had no idea of how it can impact the build since we just wanted to make everything reusable and organized. We ended up creating a subfolder inside the components
folder and naming it Shared
. At an early state of the project we noticed how slow the Experience Editor was which doesn’t make sense since starting from the ground up would mean there’s basically a minimal number of Sitecore Renderings present.
After some investigation we noticed all the broken down components were registered into the componentFactory
and it was bloating it with components that don’t have a corresponding JSON Rendering. This can be easily resolved by understanding how the componentFactory
works and looking at different ways on how we can filter out what we need to add to it.
You’ll soon realize that how this file is created is very sensitive to any files within the components
folder. Here we have a simple type.ts
file that got registered into the componentFactory
.
Another grave example of custom hooks and graphql files that got into the componentFactory
.
Understanding the Generated Component Factory
This script generates the src/temp/componentFactory.ts
or on recent releases it’s also named componetBuilder
which maps your JSS React components to Sitecore renderings. Let’s think back and remember the requirement of matching the Component Name field on our JSON Rendering in Sitecore with the filename we have in our components in our components folder on the frontend. For example if we have HeroBanner
then our Next.js component should be called HeroBanner.tsx
regardless if we name our exports differently.
This can be seen evidently in out componetBuilder.ts
file with the import code of all the valid files in the components
folder and adding it into the map with numerous lines similar to the code below.
import * as HeroBanner from 'src/components/HeroBanner';
...
components.set('HeroBanner', HeroBanner);
You can also observe this if you are using Docker by checking the rendering
container when starting will have a couple of lines that look like this.
Writing site-resolver plugins to C:\app\src\temp\site-resolver-plugins.ts
Registering JSS component CdpPageView
Registering JSS component FEaaSWrapper
...
Optimizing the Component Factory
Below you will see two ways in how we can handle this problem.
- Disable the Dynamic Component Builder and rely on manually adding each Sitecore Component.
- Store any non-Sitecore Component in a separate folder.
Manually Managing the Component Factory
On recent versions from JSS 21.2.0
the script folder is setup differently. The file handling the dynamic mapping is located at scripts/generated-component-builder/plugins/component-builder.ts
. Simply deleting this file will stop observing the components
folder. To manually add each component, you will have to refer to the next file scripts/generated-component-builder/plugins/components.ts
and here you are given two choices on how you would like to handle registering your components. You can manually add each one.
{
path: string; // path to component
moduleName: string; // module name to import
componentName: 'component name'; // component rendering name
}
Or you can customize what folder you would want to have be observed using a special function provided by Sitecore. We can even rename it to src/json-renderings
to match what the files are in Sitecore.
import { getComponentList } from '@sitecore-jss/sitecore-jss-dev-tools';
...
const componentsPath = 'src/extra';
config.components = getComponentList(componentsPath);
For older versions you might not see the generated-component-builder
folder inside scripts
and instead you will see a file named generate-component-factory.ts
. You can search for a variable named componentRootPath
to modify the path you would want to watch instead of the default value of src/components
.
Using a Separate Folder for Non-Sitecore Components
Another solution would be to moving all components that do not have a corresponding JSON Rendering on Sitecore to another folder. You can get an idea about it on this blog. It will talk about a general overview of what we have here and a good way on how your separate folder should be.
Is This Really Necessary?
You might wonder why we are taking extra steps in order to re-organize our components and the hassle involved with it. How painful are a couple of components. Well let’s imagine when you have around 10 JSON Renderings and to optimize the code within each file we breakdown the code into smaller reusable files like buttons, banners, containers. What if from those 10 components we create another 10 smaller files. This will end up with registering 20 components in total! Now let’s create a larger size project which now houses around maybe 25 JSON Renderings, at the minimum maybe it accidentally adds 25 more files not including if you accidentally add in your files that only stores types, hooks, utils. **Now your whole map is bloating and you will have unexpected behavior on local development and in production. We would want to try and minimize this from happening.
Resources
Here is a Sitecore Documentation that talk a bit about carefully structuring your files.
Sitecore Developers - React/Next.js Component Structure