Insights

Demystifying the Sitecore Component Factory and Optimizing Your Sitecore Project

A deep dive in the Sitecore Component Factory, how it affects your Sitecore solution and empowering yourself to optimizing your build

A Mistake No One Should Experience

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.

Diagram showing JSON rendering linked to simple reusable components for headings and body text.

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.

Code snippet displaying 'components.set' function calls registering types in the component factory.

Another grave example of custom hooks and graphql files that got into the componentFactory .

Code excerpt showing various non-Sitecore files being registered in the component factory.

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.

Screenshot of a Sitecore interface showing component name matching with filename.

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.

  1. Disable the Dynamic Component Builder and rely on manually adding each Sitecore Component.
  2. 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



Meet John Flores

Front-End Developer

🪴🐩📷

John is a Front-End Developer who is passionate about design and development. Outside of work, John has wide range of hobbies, from his plant collection, being a dog daddy, and a foodie.

Connect with John