1. Sitecore JavaScript Services SDKs (JSS) 22.x

Upgrade JSS 22.1 Angular apps to version 22.3 for SitecoreAI

Version:

The release of JSS 22.3 includes the first edition of an Angular starter kit for SitecoreAI. Using this kit and the underlying add-ons, Sitecore developers can now integrate their Angular apps with SitecoreAI to take advantage of features such as metadata editing in Pages, page personalization, component A/B/n testing, internationalization (i18n), and more.

This topic covers most of the changes you must make to your existing JSS 22.1 Angular applications for Experience Platform (XP) to integrate those apps with SitecoreAI. However, because of the nature of JavaScript and Angular application development, this topic doesn't account for all the customization you might have in your existing application.

A JSS 22.3 application built using the XM Cloud Angular starter kit uses the following templates and add-ons:

  • angular 

  • angular-xmcloud

You'll also need to include the Node XM Cloud proxy; the method for doing so is explained in this guide.

XM Cloud is now SitecoreAI

Some code examples, images, and UI labels may still use XM Cloud while engineering assets are being updated.

Before you begin
  • If you haven't already done so, upgrade your app to JSS 22.1.

  • Next, follow the 22.3 upgrade guide for XP, which contains changes required in addition to the SitecoreAI specific ones described in this topic. You can do this afterwards instead if you prefer.

  • Familiarize yourself with the changelog. If your application is heavily customized, the changelog can provide guidance on what additional changes you need that are not covered in this topic.

This topic describes how to:

Create a JSS 22.3 Angular application

To simplify the upgrade process as much as possible, create a JSS 22.3 Angular application with the XM Cloud add-on. You can then copy some files from this app into your existing app during the next section of the guide.

To create a JSS 22.3 Angular application with the XM Cloud add-on included:

  1. In a console, run the following command:

    npx [email protected] angular
  2. If prompted to install the [email protected] package, answer y.

  3. Enter the folder path for the JSS 22.3 Next.js app. For example, enter ./jss223, to create the app folder in your current working directory.

  4. When asked if you are building for Sitecore XM Cloud, answer y to install the XM Cloud add-on.

  5. When asked where you want the JSS XM Cloud Node proxy app to be created, a subdirectory in the parent directory of your Angular app is suggested by default. We recommend you choose this option, as the proxy is best placed in a directory adjacent to your Angular app.

The script then installs the application dependencies.

XM Cloud is now SitecoreAI

Some code examples, images, and UI labels may still use XM Cloud while engineering assets are being updated.

Update the Angular template files in your existing app

This explains how to synchronize files in your existing application with corresponding files from your new JSS 22.3 app.

To update the Angular template files:

  1. If your existing app's parent directory does not already contain a copy of the JSS XM Cloud Node proxy app, such as the one installed when you created an Angular starter app in the previous section, make a copy in that parent directory, such as:

    parent
    ├── angular-xmcloud
    └── node-xmcloud-proxy
  2. Replace the contents of your app's components folder with those of src/app/components from the sample app.

  3. If you’re using the plugins architecture for generate-component-factory and config, you need to pull the Angular XM Cloud specific plugins from the angular-xmcloud add-on.

    XM Cloud is now SitecoreAI

    Some code examples, images, and UI labels may still use XM Cloud while engineering assets are being updated.

  4. In package.json, do the following:

    • Update the build:client script to explicitly use the production configuration, such as:

      "build:client": "cross-env-shell ng build --configuration=production --base-href $npm_package_config_sitecoreDistPath/browser/ --output-path=$npm_package_config_buildArtifactsPath/browser/"
    • Add dependencies for the Cloud SDK:

      "@sitecore-cloudsdk/core": "^0.4.2",
      "@sitecore-cloudsdk/events": "^0.4.2",
  5. If you've not customized the /scripts/bootstrap.ts file, replace it with the 22.3 version. Otherwise, add the following statement to generate an integration for metadata-based editing. This assumes your app already has a generate-metadata.ts file from the angular-xmcloud add-on:

    /*
    METADATA GENERATION
    */
    require('./generate-metadata');
  6. If you are not using plugins architecture for generate-component-factory, make the following change:

    • If you've not customized the /scripts/generate-component-factory.ts file, replace it with the 22.3 version. Otherwise, implement the following to generate a list of component names for metadata-based editing:

      ...
      import { AppComponentsSharedModule } from './app-components.shared.module';
      ${imports.join('\\n')}
      
      export const components = [
          ${components.map((c) => `'${c}'`).join(',\\n  ')}
      ];
      
      @NgModule({
      ...
  7. If you've not customized the /src/app/lib/grapqhl-client-factory.ts file, replace it with the /src/app/lib/grapqhl-client-factory folder from the 22.3 sample app. Otherwise, make the following changes:

    Note

    These changes are necessary to separate the GraphQL client factory configuration from the client factory itself, so you have a single source of GraphQL endpoint resolution that can be used in places such as node-xmcloud-proxy, scripts/update-graphql-fragment-data.ts, and so on.

    • Create a new folder named /src/app/lib/grapqhl-client-factory. Within this folder, you need to restructure your existing /src/app/lib/grapqhl-client-factory.ts into two new files named config.ts and index.ts.

    • Your /src/app/lib/graphql-client-factory/config.ts file must expose the getGraphQLClientFactoryConfig that returns the configuration object for the GraphQL client factory. An example of this for connected and dev setup might look like this:

      import { GraphQLRequestClientFactoryConfig } from '@sitecore-jss/sitecore-jss-angular/cjs';
      import { environment as env } from '../../../environments/environment';
      
      export const getGraphQLClientFactoryConfig = () => {
        let clientConfig: GraphQLRequestClientFactoryConfig;
      
        if (env.graphQLEndpoint && env.sitecoreApiKey) {
          clientConfig = {
            endpoint: env.graphQLEndpoint,
            apiKey: env.sitecoreApiKey,
          };
        }
        ...
        return clientConfig;
      };
      Note

      For a full overview of this, you can look at the full code snippet with Edge endpoint initialization in the the angular-xmcloud add-on.

    • Your /src/app/lib/graphql-client-factory/index.ts file must contain the default export that returns the GraphQL client factory. For example:

      import { GraphQLRequestClient } from '@sitecore-jss/sitecore-jss-angular/cjs';
      import { getGraphQLClientFactoryConfig } from './config';
      
      const createGraphQLClientFactory = () => {
        const clientConfig = getGraphQLClientFactoryConfig();
      
        return GraphQLRequestClient.createClientFactory(clientConfig);
      };
      
      export default createGraphQLClientFactory();
    • Make sure that variables are being imported from @sitecore-jss/sitecore-jss-angular/cjs, and not @sitecore-jss/sitecore-jss-angular.

    Important

    Whether you restructured your existing file or copied files from the sample app, update all references to the GraphQL client factory in your application to use this new structure.

  8. If you've not customized the /scripts/update-graphql-fragment-data.ts file, replace it with the 22.3 version. Otherwise, make the following changes:

    • Update the file to use the GraphQL client factory and client factory configuration. You can see an example of this in your 22.3 sample app.

    • Remove the isomorphic-fetch import statement, and remove the same dependency from your package.json.

  9. If you've not customized the /scripts/generate-config.ts file, replace it with the 22.3 version. Otherwise, add the following import statement:

    import 'dotenv/config';
  10. If you've not customized the /server.bundle.ts file, replace it with the 22.3 version. Otherwise, you need to expose new properties in one of the following two ways:

    • If you want to expose these new properties in the existing file, add them there:

      import { environment } from './src/environments/environment';
      import clientFactory from './src/app/lib/graphql-client-factory';
      import { getGraphQLClientFactoryConfig } from './src/app/lib/graphql-client-factory/config';
      import { dictionaryServiceFactory } from './src/app/lib/dictionary-service-factory';
      import { layoutServiceFactory } from './src/app/lib/layout-service-factory';
      import { components } from './src/app/components/app-components.module';
      import metadata from './src/environments/metadata.json';
      
      ...
      const defaultLanguage = environment.defaultLanguage;
      const sitecoreSiteName = environment.sitecoreSiteName;
      const personalizeScope = environment.personalizeScope;
      const getClientFactoryConfig = getGraphQLClientFactoryConfig;
      
      export {
        ...
        clientFactory,
        getClientFactoryConfig,
        dictionaryServiceFactory,
        layoutServiceFactory,
        defaultLanguage,
        sitecoreSiteName,
        personalizeScope,
        components,
        metadata
      };
    • Alternatively, we recommend you create a separate /server.exports.ts file, which you can use to import and export these properties and then re-export them from /server.bundle.ts. For an example of how to implement this, refer to your new 22.3 sample app.

  11. Angular JSS apps for SitecoreAI support only GraphQL for data fetching, so make sure that your app's FETCH_WITH environment variable is set to GraphQL instead of REST. Alternatively, because GraphQL is the default method for Angular SitecoreAI apps, you can delete this environment variable.

  12. If you've not customized the /src/app/lib/dictionary-service-factory.ts file, replace it with the 22.3 version. Otherwise, add the new useSiteQuery property as shown in the following example:

    new GraphQLDictionaryService({
      clientFactory,
      siteName: env.sitecoreSiteName,
      useSiteQuery: true,
      ...
  13. To enable metadata editing integration, make sure your Layout renders a new sc-editing-scripts component (which is exposed by JssModule), as shown in the following example:

    <sc-editing-scripts></sc-editing-scripts>
    Note

    You might need to introduce a separate Scripts module to achieve this; you can find an example of how to do this in the src/app/routing/scripts/scripts.module.ts file in your 22.3 sample app.

  14. To use SitecoreAI forms, you need to register a Form component and add the required configuration. If you've not customized the scripts/generate-component-factory/plugins/packages.ts file, replace it with the 22.3 version. Otherwise, make the following changes:

    • Register the Form component. For example:

      const packages = [
        {
          name: '@sitecore-jss/sitecore-jss-angular',
          components: [{ componentName: 'Form', moduleName: 'FormComponent' }],
        },
      ]
      Important

      Don't push components like this to the declarations list, because the related module is part of the imports list.

    • In the providers list, add an injection token using EDGE_CONFIG to allow Form components to fetch data from Experience Edge. For example:

      import { EDGE_CONFIG } from '@sitecore-jss/sitecore-jss-angular';
      import { environment } from '../../environments/environment';
      ...
      providers: [
        {
          // This configuration is used to be able to integrate sitecore-jss-angular SDK with Sitecore Edge
          provide: EDGE_CONFIG,
          useValue: {
            sitecoreEdgeUrl: environment.sitecoreEdgeUrl,
            sitecoreEdgeContextId: environment.sitecoreEdgeContextId,
          },
        },
      ],
  15. In SitecoreAI, client-side event tracking is done via the Cloud SDK, so you need to make sure that it's initialized before any events are sent.

    • The following example shows a component that is correctly configured to do this:

      import { take } from 'rxjs/operators';
      import { CloudSDK } from '@sitecore-cloudsdk/core/browser';
      import '@sitecore-cloudsdk/events/browser';
      import { environment } from '../../../environments/environment';
      import { isServer } from '@sitecore-jss/sitecore-jss-angular';
      import { JssContextService } from '../../jss-context.service';
      import { JssState } from '../../JssState';
      ...
      
      ngOnInit(): void {
        if (!isServer() && environment.production) {
          // to ensure that CloudSDK initialization logic runs only once in the browser, take only the first emitted value of state
          this.jssContext.state.pipe(take(1)).subscribe((newState: JssState) => {
            const {
              route,
              context: { pageState },
            } = newState.sitecore;
      
            // Do not initialize CloudSDK in editing or preview mode or if missing route data
            if (pageState !== LayoutServicePageState.Normal || !route?.itemId) {
              return;
            }
      
            CloudSDK({
              siteName: environment.sitecoreSiteName,
              sitecoreEdgeUrl: environment.sitecoreEdgeUrl,
              sitecoreEdgeContextId: environment.sitecoreEdgeContextId,
              cookieDomain: window.location.hostname.replace(/^www\\./, ''),
              enableBrowserCookie: true,
            })
            .addEvents()
            .initialize();
          });
        }
      }
      Important

      For another example, refer to cloud-sdk-init.component.ts in your 22.3 sample app.

    • Add the component to scripts.component.html before any other scripts that use it.

      <app-cloud-sdk-init></app-cloud-sdk-init>
  16. To track page view events in SitecoreAI, add a component that executes the page view event, and then render it in the scripts section. In SitecoreAI, client-side event tracking is done via the Cloud SDK, so you need to make sure that it is initialized before any tracked event occurs.

    • The following example shows a component that is correctly configured to do this:

      import { JssContextService } from '../../jss-context.service';
      import { JssState } from '../../JssState';
      import { pageView, PageViewData } from '@sitecore-cloudsdk/events/browser';
      ...
      
      ngOnInit(): void {
        if (!isServer()) {
          this.contextSubscription = this.jssContext.state.subscribe((newState: JssState) => {
            ...
            // prepare the required data
            ...
            
            const pageViewData: PageViewData = {
              channel: 'WEB',
              currency: 'USD',
              page: route.name,
              pageVariantId,
              language,
            };
      
            pageView(pageViewData).catch((err) => console.debug(err));
          });
        }
      }
      Important

      For another example, refer to cdp-page-view.component.ts in your 22.3 sample app.

    • Add the component to scripts.component.html after the CloudSdk initializer component. For example:

      <app-cloud-sdk-init></app-cloud-sdk-init>
      <app-page-view></app-page-view>

Update the Node headless SSR proxy app

To update your Node headless SSR proxy app:

  1. Update the import statement in /src/index.ts as follows.

    // from
    import scProxy, { ProxyConfig, ServerBundle } from '@sitecore-jss/sitecore-jss-proxy';
    // to
    import { headlessProxy } from '@sitecore-jss/sitecore-jss-proxy';
    ...
    server.use(
      '*',
      headlessProxy.middleware(
        config.serverBundle.renderView,
        config,
        config.serverBundle.parseRouteUrl
      )
    );
    Note

    This makes middleware, ProxyConfig, and ServerBundle available to your app via the headlessProxy object.

  2. express is now a peer dependency, so set it to the required version ^4.19.2.

  3. If your current proxy app doesn't already have a .gitignore file, copy the one from your sample proxy app.

Next steps

To finalize the upgrade process, make sure you resolve any errors and warnings you encounter. Enable debug logging for JSS specific issues to assist you if necessary.

If you have suggestions for improving this article, let us know!