Sitecore Headless Multi-site with NPM Workspaces (updated for Sitecore 10.3.X and NextJS 13.X)

Published on
Authors

This post is an update to this post which covers the concepts and approach however Sitecore JSS/Headless has had some significant changes for Sitecore 10.3.X and XM Cloud to enable a bunch of new capabilities so I wanted to share these updates quickly and include the steps to achieve this in the newer world.

If you are looking to set up a Multi-headed Multi-site solution and you're using XM Cloud or Sitecore 10.3.x when you look at the out of the box NextJS project set up you will see a bunch of changes to what was there in 10.2 when I wrote the last post on this topic.

The set up of NPM Workspaces remains the same and the only 2 changes we are going ot make to the setup are within the next.config.js file in each project to enable the transpilation and to the scripts which generate the Sitecore JSS component manifest file and also to the sitecore JSS component registration/manifest output file generation script. Happily everything else remains the same.

NextJS 13 Updates

In the previous version, we needed to install 2 additional modules to support Transpilation in our solution. NextJS 13 now has baked this into the main product which is nice as there's fewer moving parts and things to manage now.

next-transpile-modules module has been deprecated which you can read about here.

next-compose-modules module has been deprecated which you can read about here and here.

If you are upgrading, you'll want to remove these modules, otherwise we just don't need them now..

package.json versions image

So we now need to make some changes to the next.config.js file to allow for our tranpilation to work so we can add a dependency for our 'shared' libaries/apps in the packages.json file.

The changes are pretty straight forward. There is a new property available to set called transpilePackages in our example we're adding the shared application as we were before.

We can also simplify the exports area now. The changes which show the old and new are below:

next.config.js updates

The Scripts folder which we need to make some changes within now looks like this:

Sitecore scripts updates

As we can see there are a bunch of additions/changes to this area. The file we care about in this new layout is located here (relative to the root of your aplication) /scripts/generate-component-builder/plugins/components.ts. In this file, you'll see some comments from the Sitecore team about ways in which to use the file which is now expecting modifications (hurray!).

We still have the same problem to solve with the pathing to the shared components in this file being relative to the file and the output paths needing to be relative to the temp folder's location so we're still going to run our replace to re-path all the components so they work in the generated output file.

You can see you can either point to a directory which will take ALL the components in there or you can specify specific components via path by populating the necessary object properties and passing that in. This allows us to share only what we care about to each app which is going to be including shared components.

Sitecore components.ts file updates
import { ComponentBuilderPlugin, ComponentBuilderPluginConfig } from '..';
import { ComponentFile, getComponentList } from '@sitecore-jss/sitecore-jss-dev-tools';
/**
 * Provides custom components configuration
 */
class ComponentsPlugin implements ComponentBuilderPlugin {
  order = 0;

  exec(config: ComponentBuilderPluginConfig) {
    /**
     * You can specify components which you want to import using custom path in format:
     * {
     *   path: string; // path to component
     *   moduleName: string; // module name to import
     *   componentName: 'component name'; // component rendering name
     * }
     *
     * Or you can register all components from a path using the below approach:
     * import { getComponentList } from '@sitecore-jss/sitecore-jss-dev-tools';
     * ...
     * const componentsPath = 'src/extra';
     * config.components = getComponentList(componentsPath);
     */

    config.components = [
      ...getComponentList('../shared/src/components/Promo'),
      ...getComponentList('../../packages/ui/src/components'),
    ];

    const repathedSharedComponents = config.components.map((comp: ComponentFile) => {
      comp.path = comp.path.replace('../shared', '@aceik-demo/shared');
      comp.path = comp.path.replace('../../packages/ui', '@aceik-demo/ui');
      return comp;
    });

    config.components = repathedSharedComponents;

    return config;
  }
}

export const componentsPlugin = new ComponentsPlugin();

That's it! Things are moving fast in this space and I wanted to capture the updates to the simple NPM Workspaces/mono-repo set up.