Standard service - a fixed amount of work that is performed at a fixed price.  Post Service

  

Saturday, 27 October 2018 18:27

Spartacus, Angular-based Javascript Storefront for SAP Commerce Cloud

Written by  https://hybrismart.com/2018/10/28/pwa-and-sap-spartacus-overview/
Rate this item
(0 votes)

In this article, you will find a review of the new product from SAP, a single-page storefront for SAP Commerce Cloud, known as Spartacus.

Until recently, SAP Commerce Cloud has been

offering two toolsets for mobiles, a Mobile SDK (iOS and Android) and responsive storefront template. Spartacus is the next step in this direction towards better customer experience.

Spartacus was officially introduced at SAP CX Live Barcelona. However, the idea of the single-page storefront for Commerce was new for SAP. For example, many years ago SAP released a very basic, but functional SPA template for YaaS (AngularJS). It was initially designed as a separate and experimental stream.

This article couldn’t have happened without the great help of Igor Sokolov, a solution architect at EPAM Systems. Huge thanks and enormous gratitude.

Before going into technical details of Spartacus, I need to make a short overview of the technologies and concepts used in mobile web development today.

Short Overview of Multi-Platform Mobile Frameworks

It was long believed that a native application is a good companion to the mobile and desktop version of the website. That means the developer had to maintain at least four different systems: the mobile apps for iOS and Android, and web apps, separately for mobiles and desktop. This is how Hybris looked like years ago. We had a separate folder for mobile templates, desktop templates and an SDK to create iOS and Android applications.

Later, mobile and desktop versions were merged into a single responsive website, which was able to render the website differently for different device types and screen resolutions. That reduced the number of different code bases from four to three, which was not a big win. With time, many apps were abandoned or outdated, because it was too expensive to get all these products in sync.

Installing new apps is a challenge for many people, and the number of installations was too small while the cost of getting them in sync with the web version was high. Eventually, only large e-stores could afford separate native apps for Android and iOS, but even they were continuously looking for better options.  Despite the fact that users spend more time with mobile apps than in the browser, half of U.S. smartphone users download zero apps per month, according to Comscore.

So, we came to a point that native apps too complex and expensive in support and development. This is why more and more developers use cross-platform development tools for native apps, such as PhoneGapApache Cordova,  React NativeXamarin or Flutter.

The common belief was that native apps are much faster than javascript mobile sites lost its position when WebAssembly was announced. It enables executing code nearly as fast as running native machine code, and it was envisioned to complement JavaScript to speed up performance-critical parts of web applications and later on to enable web development in languages other than JavaScript. The critical fragments can be rewritten in C/C++ and converted into Javascript using Emscripten. Some components having heavy calculations can now be executed on the device rather than on the server.  A good demonstration of this is AutoCAD Online. For mobile versions of the e-commerce websites, such performance is not required, of course. However, AR/VR and audio and video processing may change the scenery. For example, Tensorflow.js allows you to use machine learning algorithms in Javascript, even if your device is not connected.

Another argument for native apps is the limitations of the web browser in accessing hardware. Last years, some interesting technologies were introduced by Google, Microsoft and Mozilla.

  • Clipboard API is to work with the clipboard,
  • Presentation API can detect if the external display is on,
  • Web Share API is for sharing in the sharing the page in the social networks
  • Web Bluetooth API is available for integrating with the physical devices nearby. IoT solutions can use it, for example.
  • Generic Sensor API is used to work with the sensors, such as an accelerometer, gyroscope, light sensor, compass and other.

https://whatwebcando.today/ is a great resource to have a list of the latest implemented features in the browsers. I believe, that the web applications will take more and more from the native apps. 

There is a similar technology for multi-platform desktop software: Electron. For example, Skype and Atom are built with Electron. Electron accomplishes this by combining Chromium and Node.js into a single runtime and apps can be packaged for Mac, Windows, and Linux.

Back in late 2015, Google went public with an exciting new approach to app development that would herald a departure from the limited functionality and platform-locked design that was prevalent in the industry. This new method was fittingly referred to as a “progressive web app“, or PWA.

Progressive Web Applications

This concept brought the promise of providing an experience that combined the very best qualities of the web with native apps.

PWA is not a framework or toolset, it is a concept, a set of features you need to implement in your app to get customer experience on the new level. There are good implementations and bad implementations, complete and incomplete.  

So, there is no exact definition of what is PWA, and nobody will say if your app is PWA-enabled or not. The PWA has “analog” nature: the website can be PWA to some degree. The more features from the PWA checklist it meets, the closer to this concept it is. In order words, the developer is given the tools (Service Worker, Push Notifications etc.) and goals (fast, reliable, engaging), and how far the developers are able to go depends entirely on them, and this determines the PWA-ness.

The key features of PWA are:

  • Progressive enhancement: The app runs in as many environments as possible. If it needs a service, it should use whatever is available and degrade gracefully if nothing is there.
  • Responsive user interface:The app adapts to various input methods (touch, speech, etc.) and output methods (different screen sizes, vibration, audio, braille displays, etc.).
  • Connectivity-independence:The app works well offline and with intermittent or low-bandwidth connectivity.
  • App-like UI:The app adopts UI elements of native platforms, including a fast-loading user interface (which can be achieved by caching important assets via service workers).
  • Continuous updates (“freshness”): The service worker API defines a process for automatically updating apps to new versions.
  • Secure communication:The app is served and communicates via HTTPS, to prevent snooping and attacks.
  • App discovery:Meta-data such as W3C web app manfests enables search engines to find web apps.
  • Push interaction (“re-engagement”):Features such as push notifications actively keep users up-to-date.
  • Natively installable: On some platforms, you can install a web app so that it feels like a native app (icon on home screen, a separate entry in the app switcher, browser chrome optional). All without going through a native app store.
  • Linkability:Easily share apps via URLs and run them without installation.

Some consider, however, that the only feature that makes the web app PWA is app install banners, which developers can get by hitting the right heuristics, and all the rest is basically marketing.

The PWA started in Google, so it is better supported by Android than iOS. In Samsung Internet, there is a feature called ‘ambient badging’. If the browser detects the page is PWA, it will dynamically update the usual bookmark icon in the URL bar, to a special ‘+’ icon, giving your users an easy shortcut to add it to their homescreens. And in Chrome for Android now, you actually get a real Android app — with their new WebAPK feature. When you install a PWA on your homescreen, it automatically creates a lightweight Android app wrapper, so your app actually appears in the Apps list and is a true first-class citizen.

The heart of PWA is a Service Worker. This is a proxying layer between a browser and server. All browser requests go through it. Service Workers can access to a Cache Storage for web resources and IndexDB for data. For example, the system can receive a browser request, then check the network state, then retrieve the data from the storage, then process them somehow and return the result back to the browser. The browser will think it works with the network resource, but in fact, it was intercepted and the result was retrieved from the storage instead. You can check the readiness of different browsers at isServiceWorkersReady.

With iOS 11.3 (March, 30th 2018), Apple has silently added support for the basic set of new technologies behind the idea of “Progressive Web Apps” (PWAs). Specifically, iOS supports Service Workers and Web App Manifest specs. However, from an Apple’s perspective, PWAs are just “web apps from the home screen,” and the icon is something referred as a WebClip.

If you need to have a native app having only the PWA, you can create it from PWA using https://www.pwabuilder.com/. For Windows, it generates .appx, and you can send it to Windows Dev Center. For Google, it creates a Java wrapper app, which includes your PWA. You compile this project in Android Studio, and upload the package to Android Dev Center. For Apple, it generates an XCode project. After compiling, you can send the package to Apple Store.

PWA Storefronts

Of course, any e-commerce solution can be implemented from scratch using any PWA-ready framework or mobile UI library. However, such approach will definitely take more time and resources than using specialized products.

Specialized solutions help you to release a product faster. For simple cases, you can launch your solution in weeks.  

  • SAP Spartacus. Developed by SAP specifically for SAP Commerce Cloud. Officially presented in October 2018. The product is just released as pre-alpha. It doesn’t cover all PWA features yet, but SAP promises that it will be production ready in the first half of 2019.
  • Google Polymer Storefront. Actually, the polymer framework is a powerful tool, but the storefront implementation is very basic and trivial. It only serves as a demonstration of the Polymer library for building web applications using Web Components. Demo is available: https://shop.polymer-project.org/

SAP Spartacus in Detail

Spartacus is a framework for PWA apps developed by SAP for their Commerce platform. It is still in pre-alpha status, but once it was officially announced, I decided to look closer on the internals.

This Angular storefront is supposed to replace JSP-based Accelerator in future.

The strong point of the solution that the new storefront is no longer part of the e-commerce platform. Being decoupled you can upgrade both the platform and the storefront code separately without a need of rewriting the templates, because API interfaces will be the same.

Architecture

As for now Spartacus is based on the following technology stack:

  • Angular 6.1.8, TypeScript 2.9, and Sass 3
  • RxJS 6.3.3, Ngrx 6.1, and Bootstrap 3.2.2
  • Jasmine, Karma and Protactor
  • Github, webpack and npm

For each website page, you need to have an angular template.
In other words, if you create a page in CMS Cockpit or SmartEdit, you will need to ask developers to add this page in the Angular code too.

The system is not capable yet to pull new pages from the WCMS automatically. 

The client (Angular app) requests a CMS page, parses JSON and render the page based on the page description in the payload.

/rest/v2/electronics/cms/pages
?pageType=ContentPage
&pageLabelOrId=faq
&lang=en
&curr=USD

The full specification of the available services can be found by requesting swagger UI of the service:

https://storefront.c39j2-walkersde1-d2-public.model-t.cc.commerce.ondemand.com/rest/v2/swagger-ui.html

And this way works all the pages with certain grouping, i.e. multi-step checkout is treated as one page, one template and all checkout steps transitions are handled by the client logic (Angular app code).

The response contains a list of content slots and components in them. The components are managed in the Commerce Cloud Content Management, CMS Cockpit or SmartEdit.

The template for a home page (as well as for other pages too) is hardcoded in Angular:

Home-page.component.html:

This template refers to the landing-page-layout component.

landing-page-layout.component.html:  

The layout contains the slot definitions. The banner will be placed into Section4.

The Angular component y-dynamic-slot injects the components into according to the CommerceCloud component <-> Angular component mapping.

Spartacus has a built-in mapping configuration that helps a dynamic renderer to map Hybris traditional WCMS components/page templates names in REST response (i.e. /some-pages) into Angular components.

This mapping is a class that implements interface CMSComponentMappingConfig (storefrontlib/src/lib/cms/cms-module-config.ts) which then is extended and combined together with all other configs into one major configuration interface StorefrontModuleConfig (storefrontlib/src/lib/storefront-config.ts). We can re-configure this mapping, add our own entries to here. See the section below about adding a component.

For our example, SimpleResponsiveBannerComponent is mapped into responsive-banner component (with the selector = “y-responsive-banner”).

The Angular template of this component is the following:

For example, the URL for the link is taken from the XML generated by Commerce Cloud (see above), from the attribute ‘urlLink’.

If you add a new component in Commerce Cloud, you need to implement the angular part too, add it to the mapping.

Let’s take another component, Product Carousel.

The information about these products is delivered with the page information XML:

The component ProductCarouselComponent is mapped to y-product-carousel selector, product-carousel component. This component fetches data about the products listed in productCodes:

fetchData is executed for each component as part of the initialization. For some components, it is empty if there is no need to fetch data for the component. For this one, the system generates 11 calls to the server to get the detailed product information for each of the 11 products listed in the carousel component definition. It is worth to notice that all those calls are done in an async manner. Specifically, they are done using RxJS (you can see “subscribe” function this is a part of react JS library RxJS).

Currently, if you have N carousel components on the page having the same products, the system will request the product information N times. However, both the browser and server caching should make this point minor.  

To draw a bottom line in this section let’s compare JSP-based CMS approach (a legacy storefront) and Angular-base. If do that then we will find a lot of similarities:

  • For Page template, we need a JSP file with an HTML template, the same thing in Spartacus, we need to have an Angular component to provide an HTML template. As we understand SAP made decision to divide responsibilities in this case into two Angular components: page component itself and page layout component. For example, LoginPageComponent is an Angular page component with a template defined in login-page.component.html that includes layout component LoginPageLayoutComponent using a tag ‘y-login-page-layout‘. The layout page template defines the backbone of HTML page in login-page-layout.component.html.
  • For WCMS components we still need a persistent model to represent a configured state of the component. The JSP based approach assumes you have a controller and a template, quite similar approach in Spartacus you will need an Angular component to be created in the storefront and there is a mapping object between WCMS component and Angular component as it mentioned above in the file cms-module-config.ts. For example, BannerComponent is an Angular part of the simple, non-responsive banner WCMS component, the TypeScript class BannerComponent is defined as a subclass of abstract AbstractCmsComponent. The component layout is defined in banner.component.html. The parent class AbstractCmsComponent gives a field ‘component‘ that will be populated by Spartacus platform based on the response from OCC. In more details you will see how it works below in the section ‘Adding custom components’. Giving back to parallels between JSP and Angular-based approaches, we can say that the role of component controller in Spartacus plays class BannerComponent.

The next couple of section will demonstrate our understanding how Spartacus can be extended and customized using several typical scenarios.

  • Creating a custom static page
  • Adding a custom component
  • Changing the existing component template or its part

Creating a Custom Static Page

You need to have this page configured on the server side. Use SmartEdit or WCMS for that. In the examples below, I will use “faq” page instead to make the examples work without this step. Change ‘faq’ to your page label.

We create two components, my-page and static-page-layout. The second component can be used for other static pages too. It is here just as a demonstration of the layout component. 

My-page.component.html:

<y-static-page-layout>
<h2class="y-page__title">Specific My page subtitle</h2>
<y-dynamic-slot[position]="'Section1'"></y-dynamic-slot>

<divclass="y-landing-page-layout__container">
<y-dynamic-slot[position]="'Section2A'"class="y-landing-page-layout__slot-2"></y-dynamic-slot>
<y-dynamic-slot[position]="'Section2B'"class="y-landing-page-layout__slot-2"></y-dynamic-slot>
</div>

<y-dynamic-slot[position]="'Section2C'"></y-dynamic-slot>
<y-dynamic-slot[position]="'Section3'"></y-dynamic-slot>

<y-dynamic-slot[position]="'Section4'"class="y-landing-page-layout__slot-4"></y-dynamic-slot>
<y-dynamic-slot[position]="'Section5'"></y-dynamic-slot>

</y-static-page-layout>

The slot names should be the same as used on the server side (WCMS). For each slot, the storefront retrieves the content (in form of the JSON structure).  The FAQ page we use in this demo is built with the template where these slots are used. 

My-page.component.ts defines the template

import{ Component } from '@angular/core';

@Component({
selector:'y-my-page',
templateUrl:'./my-page.component.html'
})
exportclass MyPageComponent {
constructor(){}
}

My-page.module.ts defines the page label and a path:

import{ NgModule } from '@angular/core';
import{ CommonModule } from '@angular/common';
import{ Routes, RouterModule } from '@angular/router';

import{ MyPageComponent } from './my-page.component';
import{ StaticPageLayoutModule } from '../static-page-layout/static-page-layout.module';
import{ CmsModule, CmsPageGuards } from '@spartacus/storefront';

const routes: Routes =[
{
path:'my',
canActivate:[CmsPageGuards],
data:{ pageLabel:'faq'},
component: MyPageComponent
}
];

@NgModule({
imports:[CommonModule, CmsModule, StaticPageLayoutModule, RouterModule.forChild(routes)],
declarations:[MyPageComponent],
exports:[MyPageComponent]
})
exportclass MyPageModule {}

It refers to StaticPageLayoutModule. This component has a template:

<divclass="y-page">
<headerclass="y-page__header">
<h1class="y-page__title">Generic Static page title</h1>
</header>
<divclass="y-container">
<ng-content></ng-content>
</div>
</div>

and a module:

import{ NgModule } from '@angular/core';
import{ CommonModule } from '@angular/common';

import{ StaticPageLayoutComponent } from './static-page-layout.component';
import{ CmsModule } from '@spartacus/storefront';

@NgModule({
imports:[CommonModule],
declarations:[StaticPageLayoutComponent],
exports:[StaticPageLayoutComponent]
})
exportclass StaticPageLayoutModule {}

and a standard component code:

import{ Component } from '@angular/core';

@Component({
selector:'y-static-page-layout',
templateUrl:'./static-page-layout.component.html'
})
exportclass StaticPageLayoutComponent {
constructor(){}
}

This is how our page looks in the browser (http://localhost:4200/my):

However, better handling of routes is on the roadmap.

Adding Custom Components

In this section you will learn how to add a new component to the storefront. Of course, adding a UI component is a trivial thing, it is Angular’s standard feature. The thing is how to connect the Angular component to the SAP Commerce component.

Above I mentioned that the component structure is managed via CMSCockpit or SmartEdit, and SAP Commerce provides the webservices to deliver the information about the component configuration to the Angular storefront. This information contains a list of components and their details grouped by the content slots.

Spartacus renders the components in the browser, so it should know what SAP Commerce component corresponds to what Angular component. This mapping is pre-configured for the list of standard out-of-the-box components.

For the demonstration purpose we have choose an example of a simple custom component to print a copyright with automatically updated current year. The First step is to define a new WCMS component, called CopyrightComponent.

<items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="items.xsd">
<itemtypes>
<typegroup name="Components">
<itemtype code="CopyrightComponent"extends="SimpleCMSComponent" jaloclass="com.epam.mycomponents.jalo.CopyrightComponent">
<description>It represents product references component, that is the component that displays configured references to the specified product.</description>
<attributes>
<attribute qualifier="template" type="java.lang.String">
<persistence type="property"/>
<modifiers optional="false"/>
<defaultvalue>Copyright © 2000-${currentYear} by ABC, Inc., or related companies. All rights reserved.</defaultvalue>
<description>Copyright text template</description>
</attribute>
</attributes>
</itemtype>
</typegroup>
</itemtypes>
</items>
Read 70 times

Leave a comment

Make sure you enter all the required information, indicated by an asterisk (*). HTML code is not allowed.