SAP Commerce Spartacus mit Angular Step-By-Step Tutorial

25.03.2021Ricky Elfner
E-Commerce SAP Commerce Angular Open source TypeScript Hands-on

Diese Woche beschäftigen wir uns mit Spartacus, dem Angular basiertem JavaScript Storefront für die SAP Commerce Cloud. Dabei kommuniziert die Angular Applikation über die Commerce API von SAP Commerce Cloud. Spartacus ist ein Open-Source-Projekt, welches auf GitHub frei zur Verfügung steht.

Wir werden zusammen lokal einen exemplarischen Beispiels-Store aufsetzen. Dabei werden wir Angular als Frontend-Framework nutzen und ein von SAP-gehosteten SAP Commerce Cloud-Store im Backend ansprechen.

Das Storefront ist mittlerweile in der Version 3.1 verfügbar. Um diese Version auch nutzen zu können, sind folgende Voraussetzungen zu erfüllen:

Inbetriebnahme des Beispiel Stores

Um Spartacus zu testen, erst erstellen wir zuerst eine neue Angular App. Dabei können Sie die App, wie in dem Beispiel von Spartacus selbst mystore nennen.

1
ng new mystore --style=scss

Sobald Sie den Befehl ausgeführt haben, werden Sie gefragt, ob die App Angular Routing verwenden soll. Die Dependency können Sie zwar zunächst hinzufügen, benötigen diese jedoch für den Anfang noch nicht.

Sobald dieser Vorgang erfolgreich abgeschlossen ist, können Sie innerhalb des Terminal in das Verzeichnis mystore wechseln und mit code . VS Code öffnen.

In manchen Fällen ist es besser, anschliessend noch ein yarn install durchzuführen, um sicher zugehen, dass alle Dependencies auch richtig installiert wurden. Um sicherzugehen, dass Ihre Applikation läuft, können Sie mit yarn start diese zuvor einmal starten. Für das weitere Vorgehen sollten Sie jedoch den Server anschliessend wieder stoppen.

Wenn alles wie gewünscht funktioniert, können wir nun ein Beispiel von Spartacus selbst verwenden, denn SAP stellt dabei ein funktionsfähiges Backend zur Verfügung.

Durch Spartacus Schematics ist es möglich, dass Sie die Spartacus Libraries innerhalb Ihres Projekts installieren können. In dem bereitgestellten Beispiel werden vier Optionen verwendet. Für diejenigen, die bereits mit SAP Hybris oder ähnlichen gearbeitet haben, werden die beiden Optionen baseUrl und baseSite bereits ein Begriff sein. Denn diese geben Auskunft über das Backend des Shops. Mit der dritten Option können Sie festlegen, dass die Server-Side-Rendering Funktion aktiviert wird und mit der vierten, werden die Voreinstellungen für eine Progressive Web App ebenfalls hinzugefügt.

1
2
3
4
5
ng add @spartacus/schematics 
  --baseUrl https://spartacus-demo.eastus.cloudapp.azure.com:8443/ 
  --baseSite=electronics-spa 
  --ssr
  --pwa

Durch die unterschiedlichen Dependencies die verwendet werden, kann es bei der Installation öfters zu Dependency Problemen kommen. Diese sollten Sie zuerst beheben, bevor Sie weiter machen können. Deshalb stellen wir Ihnen über GitHub das Projekt zur Verfügung, damit Sie sehen können, mit welchen Versionen wir dieses Tutorial erstellt haben.

Sofern Sie die Installation erfolgreich beendet haben, wurden alle notwendigen Files automatisch angepasst.

Innerhalb von app.module.ts, können Sie die zuvor übergebenen Einstellungen für baseSite und baseUrl finden. In diesem Schritt ist noch zu erwähnen, dass Sie das Modul AppRoutingModule aus den Import entfernen sollten, falls Sie Angular Routing, beim erstellen des Projekts hinzugefügt haben. Da Sie sonst ohne weitere Einstellungen nichts angezeigt bekommen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//app.module.ts
...
imports: [
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    B2cStorefrontModule.withConfig({
      backend: {
        occ: {
          baseUrl: 'https://spartacus-demo.eastus.cloudapp.azure.com:8443/'
        }
      },
      context: {
        currency: ['USD'],
        language: ['en'],
        baseSite: ['electronics-spa']
      },
      i18n: {
        resources: translations,
        chunks: translationChunksConfig,
        fallbackLang: 'en'
      },
      features: {
        level: '3.1'
      }
    }),
    BrowserTransferStateModule
  ],
 ...

Eine weitere wichtige Änderung, die automatisch vorgenommen wurde, ist innerhalb der app.component.html zu sehen. Denn dort wurde der gesamte Inhalt gelöscht und durch ein einziges HTML-Tag ersetzt.

1
<cx-storefront></cx-storefront>

Nun können Sie mit yarn start den Server wieder starten. Nun sollten Sie über die Adresse http://localhost:4200/ den von SAP zur Verfügung gestellten Beispiel Store sehen.

Anpassen einer Komponente

Natürlich haben Sie auch die Möglichkeit, bestehende Komponenten, die bereits über das Backend zur Verfügung gestellt werden, anzupassen. Als Beispiel werden wir nun eine Produktdetailseite überarbeiten.

Da Spartacus ein Open-Source-Projekt ist, findet man innerhalb von GitHub auch die notwendigen Informationen. Dort können Sie beispielsweise die vorgegebenen Slots für das ProductDetailsPageTemplate nachschauen. Die Komponenten kommen jedoch über die Backend Seite.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 ...
    ProductDetailsPageTemplate: {
      lg: {
        pageFold: 'UpSelling',
      },
      pageFold: 'Summary',
      slots: [
        'Summary',
        'UpSelling',
        'CrossSelling',
        'Tabs',
        'PlaceholderContentSlot',
      ],
    },
 ...

Hierfür können Sie innerhalb des Browsers das Network-Tab über die Entwickler-Konsole öffnen und eine Produktseite des Stores aufrufen. Innerhalb des Calls pages?pageType=ProductPage… können Sie nun alle Komponenten sehen, die verwendet werden. Anhand der Component 16, sehen Sie die BeschreibungPostion: Summary, welche dem ersten Slot entspricht. Dieser Slot entspricht dem Slot, welchen Sie in GitHub für das ProductDetailsPageTemplate sehen können, bzw. in dem vorherigen Bild.
Als Beispiel Komponente, die angepasst werden soll, wird nun die ProductIntroComponent genutzt. Hierbei wird das Attribut flexType zur Identifikation verwendet.

Nun kommen wir wieder zum Praxisteil innerhalb von VS Code.
Zunächst müssen Sie ein Modul erstellen. Dies können Sie am besten über das Terminal machen. Der Name für das Modul ist an den Standardabkürzung von Spartacus angelehnt, nämlich Product-Detail-Page.

1
ng g m custom-pdp

Im zweiten Schritt müssen Sie nun noch eine Komponente innerhalb dieses Modules erstellen.

1
ng g c custom-pdp/custom-product-intro

Dadurch haben Sie nun folgende Ordnerstruktur:

Innerhalb des withConfig-Teils wird festgelegt, dass es sich um eine CMS-Komponente handelt. Dabei soll die ProductIntroComponent ersetzt werden. Diese Komponente können Sie anhand des flexTypes ausfindig machen. Die Komponente, die stattdessen verwendet wird, ist die, die Sie zuvor erstellt haben.

Config Typing hilft Ihnen dabei, die richtigen Attribute zu nutzen, in diesem Beispiel wird CmsConfig verwendet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
...
import { CustomProductIntroComponent } from './custom-product-intro/custom-product-intro.component';
import { CmsConfig, ConfigModule } from '@spartacus/core';

@NgModule({
  declarations: [CustomProductIntroComponent],
  imports: [
    CommonModule,
    ConfigModule.withConfig({
      cmsComponents:{
        ProductIntroComponent: {
          component: CustomProductIntroComponent
        }
      }
    } as CmsConfig)
  ]
})
export class CustomPdpModule { }

Damit diese Komponente auch in der App verwendet werden kann, müssen Sie das Modul CustomPdpModule noch in dem File app.module.ts innerhalb des Import-Statements hinzufügen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { CustomPdpModule } from './custom-pdp/custom-pdp.module';
...

@NgModule({
  ...
  imports: [
    ...
    CustomPdpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Sobald Sie die Änderung speichern und alles neu gebuildet wurde, sehen Sie auf der Product-Detail-Page (kurz PDP) nun den Standardtext einer Komponente, die über ng erstellt wurde, nämlich: “custom-product-intro works!“

Nun wollen Sie natürlich auch die Möglichkeit haben, auf Produktinformationen zuzugreifen, um diese auf Ihre eigene Art und Weise anzeigen zu können. Dazu müssen Sie einige Dinge innerhalb von custom-product-intro.component.ts anpassen. Innerhalb des Constructors bestimmen Sie zuerst den CurrentProductService, welchen Sie von Spartacus Storefront zur Verfügung gestellt bekommen und selbstverständlich importieren müssen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
//custom-product-intro.component.ts

import { Component, OnInit } from '@angular/core';
import { Product } from '@spartacus/core';
import { CurrentProductService } from '@spartacus/storefront';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-custom-product-intro',
  templateUrl: './custom-product-intro.component.html',
  styleUrls: ['./custom-product-intro.component.scss']
})
export class CustomProductIntroComponent implements OnInit {

  product$: Observable<Product> = this.currentProductService.getProduct();

  constructor(private currentProductService: CurrentProductService) { }

  ngOnInit(): void {
  } 

}

Um nun auf die Attribute der Produkte zuzugreifen und diese anzeigen zu lassen, müssen Sie in das File custom-product-intro.component.htmlwechseln. Dort erstellen Sie zunächst einen ng-container, da es sich bei der Produkt-Variable um ein Observable handelt und “entpackt” werden muss. Anschliessend können Sie auf die gesamten Attribute, die innerhalb des Product-Models festgelegt sind, zugreifen. In diesem Beispiel wird zuerst der Name und dann der Preis ausgegeben.

Die nächste Besonderheit sind Komponenten, die ebenfalls über Spartacus Storefront zu Verfügung gestellt werden. Auch für diese Komponenten und ihre Module gibt es eine Dokumentation. Innerhalb dieses Beispiels wird eine Bewertungs-Komponente mittels Sternen verwendet.

1
2
3
4
5
6
7
8
9
<ng-container *ngIf="product$ | async as product">
    <h1>{{ product?.name }} </h1>
    <h3>{{ product?.price?.formattedValue }}</h3>
    
    <cx-star-rating
        [rating]="product?.averageRating"
        [disabled]="true"
    ></cx-star-rating>
</ng-container>

Damit Sie diese Spartacus Komponente auch angezeigt werden kann, müssen Sie das Modul auch innerhalb von custom-pdp.module.ts noch importieren.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
...
import { StarRatingModule } from '@spartacus/storefront';


@NgModule({
  declarations: [CustomProductIntroComponent],
  imports: [
    ...
    StarRatingModule
  ]
})
export class CustomPdpModule { }

Durch diese Änderungen haben Sie nun folgenden Ansicht auf ihrer Produktdetailseite:

PWA

Wie Sie vorhin gesehen haben, war die vierte Option des ng add @spartacus/schematics Befehls --pwa. Dadurch wurden die Einstellungen für eine Progressive Web App bereits hinzugefügt. Um diese Funktion nun auch wirklich zu verwenden, müssen Sie noch folgenden Befehl ausführen.

1
yarn build:ssr

Dieser Befehl führt wiederum zwei weitere Befehle automatisch aus:

1
ng build --prod && ng run mystore:server:production

Der erste Teil davon generiert alle notwendigen Dateien und registriert ihren Service Worker um Ihre App als PWA laufen zu lassen. Der zweite Teil führt ein automatisch erstelltes Script aus.

Wenn bei Ihnen dieser Befehl erfolgreich durchgelaufen ist, können Sie nun den Server starten:

1
yarn serve:ssr

Hierdurch können Sie nun Ihre Webseite wieder öffnen. Dieses Mal jedoch über: http://localhost:4000/

Da es sich nun um eine PWA handelt, können Sie auch innerhalb der Entwickler-Tools in dem Tab “Application” den dazu gehörigen Service Worker sehen.

Ein weiterer Vorteil ist die Installationsmöglichkeit als App.

Anschliessend lässt sich der Online Shop als App öffnen. Dies sieht dann folgendermassen aus:

Nun haben Sie erfolgreich das SAP-Backend mit einer Angular Applikation mit dem Storefront Spartacus verbunden und eine eigene Komponente erstellt. Ebenfalls können Sie den Online-Shop als Progressive-Web-App, kurz PWA, nutzen. Wenn Sie noch mehr über die Vorteile von PWAs wissen möchten, dann können Sie nächste Woche bei uns in den Blog schauen um mehr darüber lesen zu können.

Ricky Elfner

Ricky Elfner – Denker, Überlebenskünstler, Gadget-Sammler. Dabei ist er immer auf der Suche nach neuen Innovationen, sowie Tech News, um immer über aktuelle Themen schreiben zu können.