Document Tree
Document Properties
Kbid
30851D
Last Modified
16-Aug-2024
Added to KB
18-Apr-2023
Public Access
Everyone
Status
Online
Doc Type
Concepts
Product
Intershop Progressive Web App
Concept - Intershop Progressive Web App - Configuration

In a complex application like the Intershop Progressive Web App, there are multiple ways and kinds of configuration.
The complexity increases if you consider that the communication with Intershop Commerce Management has to be coordinated as well.
In addition, the PWA, when run with Angular Universal, consists of a server-side and a client-side application.

Ways of Configuring Angular Applications

Warning

If available, always prefer configuration via system environment variables and running the PWA with Universal Rendering.

Angular CLI Environments

The standard way of configuring an Angular Application is managing multiple environment files that are part of the project's source tree, usually located in src/environments. To choose one configuration, you have to supply the parameter when building the Angular Application.
See Guide - Building and Running Server-Side Rendering and Configuring Application Environments for further information.

Do not access properties supplied with environment files directly in artifacts.
Instead, you need to provide them via InjectionTokens to be used in components, pipes, or services.
Standard InjectionTokens are defined in injection-keys.ts.
Use this file to create new keys for the standard PWA; project customizations should create their own file next to it.

First, extend the environment.model to support your new property.
Then define an InjectionToken that can be used to access a certain property later on:

export const PROPERTY = createEnvironmentInjectionToken('property');

The new token is automatically initialized with the default value from the Angular CLI environment files.
To override it in tests, you can provide it in the TestBed configuration.

To inject the property with dependency injection, use the helper InjectSingle to properly inherit type information:

import { Inject } from '@angular/core'

import { PROPERTY } from 'ish-core/configurations/injection-keys'
import { InjectSingle } from 'ish-core/utils/injection';

...

constructor(@Inject(PROPERTY) private property: InjectSingle<typeof PROPERTY>)

As can be seen here, only build-time and deploy-time configuration parameters can be supplied this way.

Node.js Environment Variables

When running the application in Angular Universal mode within a Node.js environment, we can additionally access the process environment variables via process.env.
This method provides a way to configure the application at deploy time, e.g., when using Docker images.
Configuration can then be consumed and passed to the client side via state transfer using Angular's TransferState.

To introduce a new TransferState key, add it to the state-keys.ts.

export const NEW_KEY = makeStateKey<string>('newKey');

The actual transfer is handled by the app.server.module.ts where the mapping of the environment variable is done.

Accessing the transferred state in a service or a component is done as follows:

import { NEW_KEY } from 'ish-core/configurations/state-keys';

newKey string;

constructor(private transferState: TransferState) {}

if (!SSR) {
  this.newKey = this.transferState.get<string>(NEW_KEY, 'default value');
}

NgRx Configuration State

The previous ways were mainly handling deployment- or build-time-related means to configure an Angular application.
All further configuration that has some kind of runtime flexibility, especially configuration that is retrieved via REST calls from the ICM, has to be handled in the NgRx store and to be used throughout the application with selectors.
Effects and actions should be used to manipulate those settings.

URL Parameters

A configuration effect (NgRx) for listening to route parameters when initially visiting the page has been composed.
This provides the most flexible way of configuring the application at runtime.

Different Levels of Configuration Settings

Build Settings

One example for a build time configuration is the property serviceWorker, which is managed in the angular.json configurations and used to activate the service worker.

In general, properties available at build time can only be supplied by Angular CLI environments (see above).

Deployment Settings

Deployment settings do not influence the build process and, therefore, can be set in more flexible manners.
The main criteria of this category is the fact that deployment settings do not change during runtime.
The most common way of supplying them can be implemented by using Angular CLI environment files and InjectionTokens for distribution throughout the application's code.

An example for this kind of settings are breakpoint settings for the different device classes of the application touch points.

Deployment settings can also be set by using TransferState to use environment variables of the deployment for the configuration of the application.

Runtime Settings

The most flexible kind of settings, which can also change when the application runs, are runtime settings.
Angular CLI environment files cannot provide a way to handle those.
Only the NgRx store can do that.
Thus, only NgRx means should be used to supply them.
Nevertheless, default values can be provided by environment files and can later be overridden by system environment variables.

Everything managed in the NgRx state is accumulated on the server side and sent to the client side with the initial HTML response.

To access these properties, we provide the StatePropertiesService, which takes care of retrieving the configuration either from the configuration state, an environment variable or the environment.ts (in that order).

Configurations REST Resource

ICM provides a Configurations REST resource - /configurations - that is supposed to provide all relevant runtime configurations that can be defined in the ICM back office and are required to configure a REST client as well.
This includes service configurations, locales, basket preferences, etc.

The ICM configurations information can be accessed through the getServerConfigParameter selector.

ICM Endpoint Configuration

Setting the Base URL

At first, the PWA has to be connected with the corresponding ICM.
This can be done by modifying environment files or by setting the environment variable ICM_BASE_URL for the process running the Node.js server.
The latter is the preferred way.
See also Guide - Building and Running Server-Side Rendering.

Independent of where and how you deploy the Angular Universal application, be it in a Docker container or plain, running on Azure, with or without service orchestrator, setting the base URL provides the most flexible way of configuring the PWA.
Refer to the documentation for mechanisms of your environment on how to set and pass environment variables.

Settings for Channels and Applications

Use the properties icmChannel and icmApplication in the Angular CLI environment or the environment variables ICM_CHANNEL and ICM_APPLICATION to statically direct one deployment to a specific REST endpoint of the ICM.

Feature Toggles

To activate additional functionality, we use the concept of feature toggles throughout the application.
For instance, there is no general distinction between B2B and B2C applications.
Each setup can define specific features at any time.
Of course, the ICM server must supply appropriate REST resources to leverage functionality.

Available Feature Toggles

Feature Toggle Description of Enabled Feature
compare Product compare feature (additional configuration via dataRetention configuration options)
contactUs Allow the user to contact the website provider via a contact web form
extraConfiguration Fetch extra configuration information from Configuration CMS component for configurable themes etc.
productNotifications Product notifications feature for price and in stock notifications
rating Display product ratings
recently Display recently viewed products (additional configuration via dataRetention configuration options)
saveLanguageSelection Save the user's language selection and restore it after PWA load
storeLocator Display physical stores and their addresses
B2B Features
businessCustomerRegistration Create business customers on registration
costCenters Cost center feature
orderTemplates Order template feature
punchout Punchout feature
quickorder Quick order page and direct add to cart input
quoting Quoting feature
B2C Features
guestCheckout Allow unregistered guest checkout
wishlists Wishlist product list feature
Third-party Integrations
maps Google Maps integration for locating stores (used with the storeLocator feature, additional configuration via gmaKey)
sentry Sentry error tracking and monitoring (additional configuration via sentryDSN)
tacton Tacton product configuration integration (additional configuration via tacton and dataRetention configuration options)
tracking Google Tag Manager tracking (additional configuration via gtmToken)
ICM compatibility
legacyEncoding Use URL resource encoding for ICM 7.10 and ICM 11

Configuring Features

The configuration of features can be done statically by the Angular CLI environment property features (string array) or the environment parameter FEATURES (comma-separated string list).
To configure it dynamically, use the PWA URL parameter features (comma-separated string list) during URL rewriting in the reverse proxy (see Concept - Multi-Site Handling).

Programmatically Switching Features

Various means to activate and deactivate functionality based on feature toggles are supplied.

Guard

Add the Guard as canActivate to the routing definition.
Additionally, you have to supply a data field called feature, containing a string that determines for which feature the route should be active.
If the feature is deactivated, the user is sent to the error page on accessing.

const routes: Routes = [
  {
    path: 'quote',
    loadChildren: ...,
    canActivate: [featureToggleGuard],
    data: { feature: 'quoting' },
  },
...

Directive

<ish-product-add-to-compare *ishFeature="'compare'"> ...</ish-product-add-to-compare>

Pipe

<ish-product-add-to-compare *ngIf="'compare' | ishFeature"> ...</ish-product-add-to-compare>

Service

@Injectable({ providedIn: 'root' })
export class SomeService {
  constructor(private featureToggleService: FeatureToggleService) {}
...
    if (this.featureToggleService.enabled('quoting')) {
...
}

Unit Testing with Feature Toggles

With Version 0.21 we introduced FeatureToggleModule.forTesting which provides a shallow implementation for testing with feature toggles not depending on the state management.
Use it in the imports of the TestBed declaration of the unit test.
Switching features in tests can be triggered by calling FeatureToggleModule.switchTestingFeatures with a new set of activated feature toggles.

Setting Default Locale

You can set the default locale statically by modifying the order of the provided locales in the Angular CLI environment files.
The first locale is always chosen as the default one.
To set the default locale dynamically, use the URL parameter lang when rewriting the URL in the reverse proxy (see Concept - Multi-Site Handling).

Extend Locales

To add other languages except English, German, or French:

  1. Add the locale to the ICM channel configuration.

  2. Create a new json mapping file with all translations, e.g., src/assets/i18n/nl_NL.json.

  1. (optional) Add the new language switch translation keys to other locales:
    example de_DE.json:

      "locale.nl_NL.long": "Niederländisch",
      "locale.nl_NL.short": "nl",
    
  2. (optional) Add the locale-specific currency filter to the environments under src/environments, e.g.,

     localeCurrencyOverride: {
       ...
       nl_NL: 'EUR',
     },
  3. Import the Angular locale data in the InternationalizationModule:

    import localeNl from '@angular/common/locales/nl';
  4. Register the locale using registerLocaleData in the constructor:

    registerLocaleData(localeNl);
  5. Add new json mapping file import to LOCAL_TRANSLATIONS injection token in the InternationalizationModule provider:

     providers: [
       {
         provide: LOCAL_TRANSLATIONS,
         useValue: {
           useFactory: (lang: string) => {
             switch (lang) {
               // other added json-mapping-file imports with translations
               ...
               case: nl_NL {
                 return import('../../assets/i18n/nl_NL.json');
               }
             }
           },
         },
       }
    ]
Disclaimer
The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.
The Intershop Knowledge Portal uses only technically necessary cookies. We do not track visitors or have visitors tracked by 3rd parties. Please find further information on privacy in the Intershop Privacy Policy and Legal Notice.
Home
Knowledge Base
Product Releases
Log on to continue
This Knowledge Base document is reserved for registered customers.
Log on with your Intershop Entra ID to continue.
Write an email to supportadmin@intershop.de if you experience login issues,
or if you want to register as customer.