CRM and CX Blogs by SAP
Stay up-to-date on the latest developments and product news about intelligent customer experience and CRM technologies through blog posts from SAP experts.
cancel
Showing results for 
Search instead for 
Did you mean: 
alex_alvarez
Product and Topic Expert
Product and Topic Expert
4,821

Overview

Migrate your accelerator-based storefront to Composable Storefront

If you've read the "Five reasons to move to a project Spartacus javascript storefront " and "Getting started with SAP Commerce Cloud Project Spartacus" you may be wanting to migrate to a stateless high-performance architecture and now wonder how to actually prepare for migration. In this article we will discuss an approach suitable for small storefronts, but with a process that can also help larger migrations, where a full re-implementation is recommended.

To Migrate or Not?

Although the recommendation is to use the move to Composable Storefront (a.k.a. Spartacus) as an opportunity to start fresh and rethink your storefront experience, you may have requirements to migrate to Composable Storefront and maintain the same experience. Depending on the number and method of customizing your accelerator-based storefront, you made find trying to migrate your existing experience over to Composable Storefront to be something simple or difficult. If you're unsure, you can use the steps below to go through an exercise to identify the number of changes without necessarily spending the time to implement. This can give you an idea of how much work may be required to migrate vs. starting with a greenfield approach.

As mentioned in "Getting started with SAP Commerce Cloud Project Spartacus" you can run your Accelerator and Composable Storefronts at the same time to reduce risk, though it is recommended to not do this for a prolonged period. Maintaining two storefronts on two technology stacks can make development and testing quite difficult, not to mention you may be giving your customers an inconsistent user experience depending on which storefront page they are hitting.

Prerequisites

It's recommended that you start your migration to a Composable Storefront after upgrading to SAP Commerce 1905 or later, as the way Omni Commerce Connect (OCC) application programming interfaces (APIs) are installed has been simplified (they are now available as extensions instead of AddOns).

To get started you will also need the following:

Initial Setup

Review the What's New in SAP Commerce Cloud, composable storefront and Roadmap for Composable Storefront to ensure you are aware of which features have parity, which may have changed and which may be missing

Upgraded your existing storefront to use at least SAP Commerce 2011

Any existing OCC Addons have been converted into regular extensions (if using SAP Commerce 2005 or later)

You have gone through the steps of "Build and Deploy Your First SAP Commerce Cloud Project". You may also want to review the content covered in Setting Up SAP Commerce Cloud for use with Composable Storefront, and ensure you have configured and performed the Building the Composable Storefront From Libraries

Front-End Team

The front-end team will build the storefront User Interface composed of layout and Angular Modules. The core skills of the developers will be:

    • Angular
    • RxJS
    • Composable Storefront
    • HMTL5


Back-End Team

The back-end team will build the OCC APIs needed by the front-end team. The core developer skills needed are:

    • SAP Commerce
    • OCC

Anatomy of a Composable Storefront

Before you begin your migration, you should be familiar with how a Composable Storefront works. Start by visiting the Composable Storefront Documentation and taking a look at the Modules and Components directory. It will look like this:


Navigate the Modules and Components and get acquainted with the functionality offered by Composable Storefront. Pay special attention at Modules that provide a default which define the Mapping between standard CMS Components and Composable Storefront Components. In the example below, the BannerComponent provides mappings to SimpleResponsiveBannerComponent, BannerComponent and SimpleBannerComponent.

BannerModule


@NgModule({

  imports: [CommonModule, RouterModule, GenericLinkModule, MediaModule],

  providers: [

    provideDefaultConfig(<CmsConfig>{

      cmsComponents: {

        SimpleResponsiveBannerComponent: {

          component: BannerComponent,

        },

        BannerComponent: {

          component: BannerComponent,

        },

        SimpleBannerComponent: {

          component: BannerComponent,

        },

      },

    }),

  ],

  declarations: [BannerComponent],

  entryComponents: [BannerComponent],

  exports: [BannerComponent],

})

export class BannerModule {}

To see the which API endpoints are available in your local installation, navigate to the OCC Swagger documentation. You may need to install additional extensions if a given endpoint is missing.

 

VersionURL
2005 and abovehttps://localhost:9002/occ/v2/swagger-ui.html
1905 and belowhttps://localhost:9002/rest/v2/swagger-ui.html


Accelerator Storefront vs Composable Storefront

You might be familiar with the standard Spring-MVC based accelerator on the left side of the picture below, but look carefully to the description of the Composable Storefront on the right to understand the key differences.

 

Accelerator Storefront


In the traditional storefront, the browser makes requests to the server which retrieve the page structure and executes controllers, facades and services to process and retrieve the information needed to render the view.

Most of the state is kept on the server-side, inside the HttpSession, which may be replicated across containers.
alex_alvarez_0-1709281543844.png

 

 

Composable Storefront


In the headless storefront the front-end is loaded on the browser, and the page structure and layout is retrieved from the server (unless it has a static layout). The Composable Storefront Components (see Modules and Components above) are used to build the page on the client side, and they execute OCC Calls to the server (see OCC APIs above) to retrieve data needed for rendering. The initial page might, however, be built initially on the Server (using a technology known as Server Side Rendering - SSR), for performance and SEO purposes.

State is kept on the Client side, inside the Browser Local / Session Storage.

During the migration, you will break down the existing accelerator Controller functionality into individual Composable Storefront Angular Components (also including the view/template logic) and OCC APIs, as indicated by the dotted lines. Be aware in some cases it might be necessary to also modify existing underlying Facades and Services.

Changes to the Content Catalog will also be required, the Composable Storefront documentation gives a good overview of the differences between the accelerator and Composable Storefront sample data.

Finally, you can analyze a sample call for the Product Details Page with the help of Chrome Developer Tools, to see how everything comes together. Use the Network Tab to see the requests generated by Composable Storefront.


Going through the calls above in more detail, using the Swagger API documentation as reference, you can see:

Call ParametersPurposeOCC Controller
/occ/v2/electronics-spa/cms/pagesng=en&curr=USDRequests the product details page including all WCMS Slots and Components.

Using the Component list in the response, Composable Storefront will use the CMSConfig mappings (see BannerModule example above) and will instantiate an Angular Component for each CMS Component and build the page using the structure provided by the slots, on the customer's browser.
de.hybris.platform.cmsocc.controllers.PageController
/sockjs-node/infoinfo?t=1597322562030Only used during development, this socket is used to update the web app when the backend rebuilds 
/occ/v2/electronics-spa/products/300938300938?fields=name,purchasable,baseOptions(DEFAULT…iantOptions(DEFAULT),variantType&lang=en&curr=USDReturns details of a single product according to the product code 300938
                
de.hybris.platform.commercewebservices.core.v2.controller.ProductsController
/occ/v2/electronics-spa/cms/componentscomponents?fields=DEFAULT&productCode=300938&curre…nk%2CBlankVideotapesCategoryLink&lang=en&curr=USDRequests a list of the provided CMS componentsde.hybris.platform.cmsocc.controllers.ComponentController
/occ/v2/electronics-spa/languageslanguages?lang=en&curr=USDGets a list of available languagesde.hybris.platform.commercewebservices.core.v2.controller.MiscsController
/occ/v2/electronics-spa/currenciescurrencies?lang=en&curr=USDGets a list of available currenciesde.hybris.platform.commercewebservices.core.v2.controller.MiscsController
/occ/v2/electronics-spa/cms/componentscomponents?fields=DEFAULT&productCode=300938&curre…ink%2CFacebookLink%2CTwitterLink&lang=en&curr=USDRequests additional CMS componentsde.hybris.platform.cmsocc.controllers.ComponentController
/occ/v2/electronics-spa/users/anonymous/consenttemplatesconsenttemplates?lang=en&curr=USDFetches the list of consentsde.hybris.platform.commercewebservices.core.v2.controller.ConsentsController
/occ/v2/electronics-spa/cms/componentscomponents?fields=DEFAULT&productCode=300938&curre…eviewsTabComponent%2CdeliveryTab&lang=en&curr=USDRequests additional CMS componentsde.hybris.platform.cmsocc.controllers.ComponentController
/occ/v2/electronics-spa/products/300938300938?fields=code,name,summary,price(formattedVal…nfiguratorType,configurable,tags&lang=en&curr=USDRequests additional fields for product code 300938de.hybris.platform.commercewebservices.core.v2.controller.ProductsController
/occ/v2/electronics-spa/products/300938/references

references?fields=DEFAULT%2Creferences(target(images(FULL)))

&referenceType=SIMILAR&lang=en&curr=USD
Requests product references for product code 300938de.hybris.platform.commercewebservices.core.v2.controller.ProductsController
/occ/v2/electronics-spa/products/300938300938?fields=classifications&lang=en&curr=USDRetrieves classifications for the product code 300938de.hybris.platform.commercewebservices.core.v2.controller.ProductsController
/occ/v2/electronics-spa/products/300938/reviewsreviews?lang=en&curr=USDRetrieves customer reviews for this productde.hybris.platform.commercewebservices.core.v2.controller.ProductsController


Using the Augury Chrome Plugin you can see the resulting component hierarchy after the page has been built in the browser.

Starting the Migration


Now that you understand how Composable Storefront works on a technical level, you are ready to proceed with the migration.

Step 1 - Make an Inventory of your CMS Components and Pages

It is important to make an inventory of the pages and components used in your current storefront, like in the table below. For each page, list the controllers and custom CMS Components that are used, and for each component, figure out which data it needs to display or process. Some of the information needed might not be visible at first sight, such as dropdown boxes or pop-up windows.

You can filter requests to /pagescontentslotscomponents in SmartEdit while editing a given page in your existing storefront to retrieve the component details.

Components used in the Accelerator Product Details Page

0: {componentId: "SiteLogoComponent",…}

1: {componentId: "HomepageNavLink",…}

2: {componentId: "OrderComponent",…}

3: {componentId: "MiniCart",…}

4: {componentId: "ElectronicsCategoryNavComponent",…}

5: {componentId: "breadcrumbComponent",…}

6: {componentId: "TabPanelContainer",…}

7: {componentId: "FooterNavigationComponent",…}

8: {componentId: "MyAccountComponent",…}

9: {componentId: "MyCompanyComponent",…}

10: {componentId: "SearchBox",…}

11: {componentId: "VariantSelector",…}

12: {componentId: "AddToCart",…}

13: {componentId: "Similar",…}

14: {componentId: "CookieNotificationComponent",…}

15: {componentId: "AnonymousConsentManagementComponent",…}

16: {componentId: "AssistedServiceComponent",…}

17: {componentId: "ProfileTagScriptComponent",…}

18: {componentId: "PersonalizationScriptComponent",…}

19: {componentId: "BundleCarouselComponent",…}


You may find it helpful to make screenshots of your storefront and annotate the components, like so:

 


Out-of-the-box Composable Storefront supports almost all responsive B2C CMS components, so you will only need to focus on your custom components, as well as those coming from third party addons or marketplace extensions not covered in the standard library. Group and classify them according to the functional area, using a component inventory like the one below. Be aware that unlike the Accelerator Page approach, everything needs to be a component in Composable Storefront, so you might need to componentize parts of an existing Jakarta Server Page (JSP) layout.

The following queries give you an overview of the Components, PageTemplates and Pages used in your storefront:

Useful Flexible Search Queries 

// Component list

select

    {ct.code},

    {c.id},

    {ct.extensionName},

    count(*) as cnt

from {

    AbstractCMSComponent as acc

    join ComposedType as ct on {ct.pk} = {acc.itemtype}

    join CatalogVersion as cv on {cv.pk} = {acc.catalogversion}

    join Catalog as c on {cv.catalog} = {c.pk}

}

where {c.id} LIKE '%ContentCatalog' and {cv.version} = 'Online'

group by {ct.code}, {cv.version}, {c.id},{ct.extensionName}

order by cnt desc

// Page Templates

select

    {ct.code},

    {c.id},

    {pt.name},

    {pt.frontendTemplateName}

from {

    PageTemplate as pt

    join ComposedType as ct on {ct.pk} = {pt.itemtype}

    join CatalogVersion as cv on {cv.pk} = {pt.catalogversion}

    join Catalog as c on {cv.catalog} = {c.pk}

}

where {c.id} LIKE '%ContentCatalog' and {cv.version} = 'Online'

order by {ct.code}

// Pages

select

    {ct:code},

    {c:id},

    {ap:name[de]},

    {ap:uid}

from {

    AbstractPage  as ap

    join ComposedType as ct on {ct.pk} = {ap.itemtype}

    join CatalogVersion as cv on {cv.pk} = {ap.catalogversion}

    join Catalog as c on {cv.catalog} = {c.pk}

}

where {c.id} LIKE '%ContentCatalog' and {cv.version} = 'Online'

order by {ct.code}

// Pages, Components and Slots

select

    {c.id},

    {cv.version},

    {p.uid}              as "Page",

    {pt.uid}             as "Template",

    {s4p.position}       as "Template assigned position",

    {st.uid}             as "content slot id 4t",

    {st.active}          as "content slot 4t active",

    {sn.templatePOS}     as "pos",

    {sn.name}            as "template available position",

    {comp.uid},

    {compt.code},

    {comp.visible}

from {

    AbstractPage as p

    join CatalogVersion as cv on {cv.pk} = {p.catalogVersion}

    join Catalog as c on {c.pk} = {cv.catalog}

    join PageTemplate as pt on {pt.pk} = {p.masterTemplate}

    join ContentSlotForPage as s4p on {s4p.page} = {p.pk}

    join ContentSlot as st on {st.pk} = {s4p.contentSlot}

    left join ContentSlotName as sn on {sn.template} = {pt.pk} and {sn.name} = {s4p.position}

    join ElementsForSlot as e2s on {st.pk} = {e2s.source}

    join AbstractCMSComponent as comp on {comp.pk} = {e2s.target}

    join ComposedType as compt on {compt.pk} = {comp.itemtype}

} where

{cv.version} = 'Online' and {c.id} like '%ContentCatalog'

order by {cv.version},{c.id},{p.uid},{sn.templatePOS},{comp.uid}


// Templates, components and slots

select

    {c.id},

    {cv.version},

    {p.uid},

    {pt.uid},

    {s4t.position}       as "template assigned position",

    {st.uid}             as "content slot id 4t",

    {st.active}          as "content slot 4t active",

    {s4t.allowOverwrite} as "template allow overwrite",

    {sn.templatePOS}     as "pos",

    {sn.name}            as "template available position",

    {comp.uid},

    {compt.code},

    {comp.visible}

from {

    AbstractPage as p

    join CatalogVersion as cv on {cv.pk} = {p.catalogVersion}

    join Catalog as c on {c.pk} = {cv.catalog}

    join PageTemplate as pt on {pt.pk} = {p.masterTemplate}

    join ContentSlotForTemplate as s4t on {s4t.pageTemplate} = {pt.pk}

    join ContentSlot as st on {st.pk} = {s4t.contentSlot}

    left join ContentSlotName as sn on {sn.template} = {pt.pk} and {sn.name} = {s4t.position}

    join ElementsForSlot as e2s on {st.pk} = {e2s.source}

    join AbstractCMSComponent as comp on {comp.pk} = {e2s.target}

    join ComposedType as compt on {compt.pk} = {comp.itemtype}

} where

{cv.version} = 'Online' and {c.id} like '%ContentCatalog'

order by {cv.version},{c.id},{p.uid},{sn.templatePOS},{comp.uid}

 

Component Inventory

IDPageComponentImplementationRender in SSRNestedData NeededNotesComponent Screenshot
10.1PDPFinancingWidgetComponentFinancingWidgetControllerYesNoUser, Cart, FinancingPreferencesCustom Layout 
10.2PDPPersonalizedRecommendationsComponentPersonalizedRecommendationsControllerNoNoRecommendationListRecommendation Engine could be queried directly 
10.3PLPLastPurchases.jspJSPYesNoPrevious OrdersNew Component needed 


In the standard accelerator, a PageController (based on AbstractPageController) prepares the context needed to render a page. In Composable Storefront most of this work is already performed by the framework, but it's a good idea to manually check for logic that might need to be moved to a custom OCC extension or an individual component.

Step 2 - Perform a GAP Analysis

For each component, identify if there is a corresponding OCC API that provides the needed data (and corresponding Injectable Service), otherwise describe the OCC Extensions that will be needed. Also, set a development priority (or importance) for each component.

Component GAP Analysis

 

IDPriorityPageComponentDescriptionData NeededExisting OCCMissing OCC
10.1APDPFinancingWidgetComponentCalculates Product finance optionsCustomer, Cart, FinancingPreferencesCart, UsersFinancingPreferences
10.2BPDPPersonalizedRecommendationsComponentUsing Analytics recommends best rated productsRecommendationListN/ARecommendations
10.3BPLPLastPurchases.jspDisplays the last 3 online purchasesPrevious OrdersOrders 

 

Step 3 - Start the API Implementation

Using an API First approach, create missing OCC Extensions and define the interfaces based on the semantics of existing OCC services. Start with empty (or mock) implementations as this will allow the front-end team to start work in parallel in the next step.

Use Swagger CodeGen to automatically generate the Typescript Angular client code needed in the front-end. Augment DTOs with necessary missing fields.

Step 4 - Implement the CMS Pages and Components

Create a base web content management system (WCMS) structure that duplicates your current storefront and launch your Composable Storefront application. Open your Console Tab in Chrome Developer Tools and you will see a warning for every CMS Component that does not have a corresponding Angular Component, there will also be a warning for the available CMS Slots.

Verify that this information matches your CMS Component Inventory

Composable Storefront

In the headless storefront the front-end is loaded on the browser, and the page structure and layout is retrieved from the server (unless it has a static layout). The Composable Storefront Components (see Modules and Components above) are used to build the page on the client side, and they execute OCC Calls to the server (see OCC APIs above) to retrieve data needed for rendering. The initial page might, however, be built initially on the Server (using a technology known as Server Side Rendering - SSR), for performance and SEO purposes. State is kept on the Client side.


Proceed to re-implement the new CMS components and Pages in Angular. Use the CMS Component Schematic add-cms-component command to generate skeleton classes (see also: Creating Pages and Components and Create a new page in Spartacus ) and add your custom logic.

Conclusion

This article provided a more technical introduction to Composable Storefront and the techniques needed to migrate an existing accelerator storefront. A migration can involve a significant amount of re-engineering but there are tangible performance and maintenance benefits that make it worth it. Careful preparation is key to a successful migration.

If you have any questions, please do not hesitate to reach out to sapcx-services@sap.com . If you have technical questions as you develop on Composable Storefront we encourage you post your question to StackOverflow with the spartacus-storefront tag.

2 Comments