Skip to content

Commit

Permalink
docs: deployment and PWA building blocks documentation (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
MKless authored and shauke committed Oct 20, 2020
1 parent 9640bfb commit 807fafb
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 69 deletions.
4 changes: 2 additions & 2 deletions docs/concepts/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ See also [Guide - Building and Running Server-Side Rendering](../guides/ssr-star
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.

### Setting for Channels and Applications
### 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.

Expand Down Expand Up @@ -193,7 +193,7 @@ export class ConfigurationModule {

> ### Configuration REST Resource
>
> We are currently planning to implement a Configuration REST resource in the ICM so that all necessary runtime configuration can be defined in the ICM Back Office and consumed by each PWA deployment.
> We are currently planning to implement a Configuration REST resource in ICM so that all necessary runtime configuration can be defined in the ICM back office and consumed by each PWA deployment.

# Further References

Expand Down
10 changes: 5 additions & 5 deletions docs/concepts/deployment-angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ kb_sync_latest_only

## Simple Browser-Side Rendering

Angular Applications are by default built for a [static deployment][angular-deployment].
Angular applications are built for a [static deployment][angular-deployment] by default.
When running `ng build` in any shape or form, the build output is aggregated in the `dist` folder and the resulting files can be statically served using any HTTP server that is capable of doing that (only a [fallback](https://angular.io/guide/deployment#routed-apps-must-fallback-to-indexhtml) for `index.html` has to be configured).

When the application is served this way, the initial page response for the browser is minimal (`index.html` with scripts inserted) and the application gets composed and rendered on the client side.

![Angular-BrowserSideApp-Sequence](deployment-angular-browsersideapp-sequence.jpg 'Angular-BrowserSideApp-Sequence')

Of course, this can have a significant impact on the client side if no efficient rendering power is available.
Search engine crawlers might also not be able to execute JavaScript and therefor might only see the initial minimal response.
Search engine crawlers might also not be able to execute JavaScript and therefore might only see the initial minimal response.

This method of deployment is suitable for demo servers supplying a fast build chain.
However, we do not recommend this setup for production use.
Expand All @@ -29,7 +29,7 @@ However, we do not recommend this setup for production use.
To tackle sophisticated SEO requirements, the [Angular Universal][angular-universal] package was introduced.
In a second step in the build process, a server-side application can be built by the Angular CLI after building the client-side application.
The resulting distribution has to be executed in a node environment.
The _server.js_ executable handles client requests on the server and pre-renders the content of the page, basically executing everything in a Node.js environment.
The _server.js_ executable handles client requests on the server and pre-renders the content of the page, basically executing everything in a _Node.js_ environment.
The resulting initial page response to the browser is mainly prepared and can be displayed quickly on the client side while the client-side application is booting up.

![Angular-ServerSideRendering-Sequence](deployment-angular-serversiderendering-sequence.jpg 'Angular-ServerSideRendering-Sequence')
Expand All @@ -40,9 +40,9 @@ We provide a `Dockerfile` for building the [SSR Image][concept-building-blocks].
## Impact of Service Workers

If the Intershop PWA is run with an enabled [Service Worker][concept-progressive-web-app], the SSR process is only triggered for the first visit to the web page.
After that, the Service Worker makes the Application behave like a simple browser-side application, where certain additional caching can lead to an improved client experience.
After that, the service worker lets the application behave like a simple browser-side application, where certain additional caching can lead to an improved client experience.

Browsers and Crawlers that don't support JavaScript execution will however continue to get fully pre-rendered page responses from the SSR process.
However, browsers and crawlers that do not support JavaScript execution will still receive fully pre-rendered page responses from the SSR process.

# Further References

Expand Down
3 changes: 2 additions & 1 deletion docs/concepts/hybrid-approach.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ The server-side rendering process must be started with `SSR_HYBRID=1`.
In addition, the PWA must be run with secure URLs as well.
This can be achieved with `SSL=1`.

**Only for development environments**: It might be necessary to set `TRUST_ICM=1` if the used development ICM is deployed with an insecure certificate.
> :warning: **Only for development environments**: It might be necessary to set `TRUST_ICM=1` if the used development ICM is deployed with an insecure certificate.
Also, the **Service Worker must be disabled** for the PWA, as it installs itself into the browser of the client device and takes over the routing process, making it impossible to break out of the PWA and delegate to the ICM.

Expand Down Expand Up @@ -106,3 +106,4 @@ For this reason, the PWA must be adapted to work with the Responsive Starter Sto

- [Guide - Building and Running Server-Side Rendering](../guides/ssr-startup.md)
- [Guide - Handle rewritten ICM URLs in Hybrid Mode](../guides/hybrid-approach-icm-url-rewriting.md)
- [Concept - Multi-site handling](multi-site-handling.md)
14 changes: 7 additions & 7 deletions docs/concepts/multi-site-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This would be set up by having 16 channels with one headless application each on
In a setup before the PWA 0.9 release this would have lead to a deployment with 16 PWA instances combined with one nginx for caching each.
Of course, a fail-over setup would increase the number of required deployment containers even more.

That is why, since version 0.9 of the PWA there are means to dynamically configure ICM channel and application to determine the correct REST endpoint for each incoming top level request.
Therefore, starting from version 0.9, the PWA features means to dynamically configure ICM channel and application to determine the correct REST endpoint for each incoming top level request.

The aforementioned scenario can now be run with just one PWA instance and a reverse proxy running in front, implementing this dynamic configuration.

Expand All @@ -35,24 +35,24 @@ It shows both the PWA parameters `channel`, `application` and their fixed exampl
The parameters of each incoming request are then read by the PWA upon initialization and used for the composition of the initial HTML response on the server side.
Afterwards they are propagated to the client side and re-used for subsequent REST requests.

In the source code of the project we provide an [extended nginx](./pwa-building-blocks.md#pwa---nginx) docker image for easy configuration of multiple channels via sub-domains.
In the source code of the project we provide an [extended nginx](./pwa-building-blocks.md#pwa---nginx) Docker image for easy configuration of multiple channels via sub-domains.

## Multi-Site Production Deployment

These steps should give an overview of the internal workings:

![Current Deployment](pwa-building-blocks-production-deployment.svg)

1. The Browser requests the page by URL from the reverse proxy. Nginx appends URL parameters to the incoming request URL for channel, application, ... depending on the incoming domain.
1. The browser requests the page by URL from the reverse proxy. Nginx appends URL parameters to the incoming request URL for channel, application, etc depending on the incoming domain.

2. The node express.js server runs Angular Universal pre-rendering for the requested URL. Angular Universal dynamically configures itself with the incoming parameters.
2. The node _express.js_ server runs Angular Universal pre-rendering for the requested URL. Angular Universal dynamically configures itself with the incoming parameters.

3. The requested page is filled with content retrieved via ICM REST API for this dynamically configured channel.

4. The configuration parameters are persisted for the client application via state transfer. Afterwards, the response is delivered to nginx.
4. The configuration parameters are persisted for the client application via state transfer. Afterwards, the response is delivered to Nginx.

5. The response is delivered to the browser.

6. The initial page response is displayed to the user and the Angular Client Application is booting up in the browser, configuring itself with the transferred parameters for channel, application, ...
6. The initial page response is displayed to the user and the Angular Client application is booting up in the browser, configuring itself with the transferred parameters for channel, application, etc.

7. Once booted up, additional REST Calls are directed to the matching ICM endpoint for the configured channel.
7. Once booted up, additional REST calls are directed to the matching ICM endpoint for the configured channel.
2 changes: 1 addition & 1 deletion docs/concepts/progressive-web-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The manifest in the PWA is theme specific and can be customized in the file `src

## Service Worker

[Service Workers](https://angular.io/guide/service-worker-intro) are automatically installed into client device browsers after the first visit to the shop and take over the all handling of the application on the client side.
[Service Workers](https://angular.io/guide/service-worker-intro) are automatically installed into client device browsers after the first visit to the shop and take over all the handling of the application on the client side.
Possible advanced features supplied are offline-capabilities and push notifications.
After installation, the service worker effectively disables server-side rendering for clients and invokes all rendering on the client himself.

Expand Down
98 changes: 63 additions & 35 deletions docs/concepts/pwa-building-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,100 @@ kb_sync_latest_only

# Building Blocks of the Intershop PWA Public Deployment

## ICM
## Intershop Commerce Management (ICM)

- provides data via REST API
- new headless application type since 0.23 (LINK to migration document)
- every other application also possible, if REST API is provided
The Intershop Commerce Management (ICM) provides the necessary data for running the [default Intershop PWA deployment](https://intershoppwa.azurewebsites.net/home) via a REST API.
Since release [0.23](https://github.com/intershop/intershop-pwa/releases/tag/0.23.0), it uses the new headless application type (see [Migrations - 0.22 to 0.23](../guides/migrations.md#022-to-023)).

## PWA - SSR
Using another backend is also possible as long as it provides a [compatible REST API](cms-integration.md#integration-with-an-external-cms).

- combines express.js server and server-side Angular Universal application (LINK to deployment-angular)
- does not hold internal state, for ease of scalability
## PWA - Server-Side Rendering (SSR)

Features:
In order to facilitate server-side rendering (SSR), the default deployment uses a dockerized [_express.js_](https://expressjs.com/) server running [Angular Universal](https://angular.io/guide/universal).
On a new request, Angular Universal pre-renders the page and instantly provides the browser with meaningful content.
For an architectural overview of how SSR functions in the Intershop PWA, see [Deployment Scenarios](deployment-angular.md).
Pre-rendering pages enables a number of features:

- SEO features (LINK)
- Dynamic configuration via URL parameters (LINK to configuration), used for multi-site (LINK) and multi-theme (LINK).
- hybrid approach (LINK)
- growing list of thirdparty integrations (LINK see overview)
- **SEO compatibility**: Many web crawlers have no or only a limited capability to interpret JavaScript code. To make single-page applications like the Intershop PWA accessible to search engines, SSR is necessary. Pre-rendered pages can easily be crawled and indexed. For more information, see [Search Engine Optimization](search-engine-optimization.md).
- **Dynamic configurations**: Using SSR allows for safe, dynamic configuration of the Intershop PWA through various URL parameters (see [Configuration](configuration.md)). For example, server-side parameter configuration enables [multi-site](multi-site-handling.md) and [multi-theme](../guides/multiple-themes.md) handling.
- **Hybrid approach**: Via the _express.js_ server, URLs can be remapped to allow dynamic integration of specific _Responsive Starter Store_ pages. See [Hybrid Approach](hybrid-approach.md) for more information.

## PWA - nginx
For an overview of the ever-growing list of third party integrations relating to SSR and deployment in general, see [Third-party Integrations](../README.md#third-party-integrations).

- modified/tuned nginx
## PWA - Nginx

Features:
As a first point of contact for any browser requests directed at a default deployment, the custom [_nginx_](https://www.nginx.com/) reverse proxy webserver serves a number of functions.
Each of these is seperately configurable (see [Building and Running nginx Docker Image](../guides/nginx-startup.md)).
Nginx enables the following features to be used in an Intershop PWA deployment:

- [PageSpeed Module](https://www.modpagespeed.com/) for browser optimization
- Enabled compression for downstream services
- Caching of PWA SSR responses
- Multi Channel handling via domains with environment variables (LINK to multi-site)
- Device type detection for pre-rendering the page fitting to the incoming user agent.
- growing list of thirdparty integrations (LINK see overview)
- Uncomplicated caching of PWA server-side rendering responses provided by the upstream Angular Universal server.
- Integration of the [PageSpeed Module](https://www.modpagespeed.com/) for access to different browser optimizations.
- Handling of multiple channels via URL parameters in conjunction with SSR (see [Multi-Site Handling](multi-site-handling.md)).
- Customizable compression for downstream services
- Device type detection to ensure a correct pre-render, adapted to the incoming user agent.

For an overview of the ever-growing list of third party integrations relating to nginx and deployment in general, see [Third-party Integrations](../README.md#third-party-integrations).

## Browser

- runs the bootstrapped Angular Client Application (LINK to deployment-angular)
The browser runs the bootstrapped/pre-rendered Angular application.
After initially communicating with the _nginx_ webserver, later REST requests are directed to the configured ICM endpoint or custom backend.
For more information on the browser's role in rendering the Intershop PWA, see [Deployment Scenarios for Angular Applications](deployment-angular.md).

# Default Production Deployment

- all building blocks chained together
Chaining the building blocks together results in the depicted system.
Read on for a step-by-step walkthrough of the initial connection request.

![Current Deployment](pwa-building-blocks-production-deployment.svg)

1. The Browser requests the page by URL from the nginx.
1. The browser requests the page by URL from the nginx.

1. If the cache is enabled and a cached response is found, the response is returned immediately, go to 6
1. If the cache is enabled and a cached response is found, the response is returned immediately, go to 6.
2. If no cached response is available, the SSR process is triggered.

2. The node express.js server runs Angular Universal pre-rendering for the requested URL.
2. The node _express.js_ server runs Angular Universal pre-rendering for the requested URL.

3. Angular Universal fills the requested page with content retrieved via ICM REST API.
3. Angular Universal fills the requested page with content retrieved via the ICM REST API.

4. The response is delivered to nginx, where it is also cached if caching is enabled.

5. The response is delivered to the browser.

6. The initial page response is displayed to the user and the Angular Client Application is booting up in the browser.
6. The initial page response is displayed to the user and the Angular Client application boots up in the browser.

7. Once booted up, additional REST Calls are directed straight to the ICM and the PWA acts as a single-page application. No further HTML pages are requested.

## Deploy without nginx
## Deployment Without Nginx

Deployment without using nginx is theoretically possible, even though many useful features of an nginx deployment are obviously not available.

> :warning: Enabling [service workers](progressive-web-app.md#service-worker) is not possible without using nginx. The Intershop PWA will not function as intended if you do.
## Hiding the ICM Backend

For security reasons, it may be desirable to hide the backend adress and prevent direct access to it.
The Intershop PWA supports this functionality and the [default deployment](https://intershoppwa.azurewebsites.net/home) uses this feature.
To enable it, set the `PROXY_ICM` environment variable on the [SSR container](../guides/ssr-startup.md) to a new URL.
Instead of directing REST calls straight to the ICM (see step seven in the [Default Production Deployment](#default-production-deployment)), traffic is routed through the SSR container.
The _express.js_ server is set up to proxy requests.
Upon completing the Angular Universal pre-rendering, all URLs referring explicitly to the used ICM (links, images, configuration) are replaced with URLs to the proxy.

## Stateless vs. Stateful Building Blocks

- theoretically possible
- no features provided by nginx: caching, device detection, ...
- problems with service workers (experimental, LINK to progressive-web-app)
For scalability and parallelization reasons, considering whether each building block is stateful or stateless is important.
The **ICM** deals with large databases, caches write and read requests and therefore manages a high amount of internal states.
Substituting ICM instances at runtime and managing fail-over capacities is not trivial.
The **SSR container** acts like a pure function.
Making the same request is always going to return the same result.
This way, setting up multiple instances, rebooting containers at runtime or even setting up serverless deployments are all possible.
It is important to keep the stateless nature of the Intershop PWA in mind when writing new code and expanding its functionalities.
The **nginx container** is not technically stateless, since it handles caching of SSR responses.
However, nginx is not functionally dependent on its internal state like the ICM is.
If an nginx container were to lose its internal state, all cached responses would instead be passed on to the _express.js_ server and be answered at the cost of a delay.

# Further References

- ssr-startup
- nginx-startup
- ...
- [Guide - Building and Running Server-Side Rendering](../guides/ssr-startup.md)
- [Guide - Building and Running nginx Docker Image](../guides/nginx-startup.md)
- [Concept - Deployment Scenarios for Angular Applications](deployment-angular.md)
Loading

0 comments on commit 807fafb

Please sign in to comment.