Show Menu
TOPICS×

SPA and Server-Side Rendering

AEM 6.4.5.0 or later is required to use the SPA server side rendering features as described in this document.

Overview

Single page applications (SPAs) can offer the user a rich, dynamic experiences that react and behave in familiar ways, often just like native applications. This is achieved by relying on the client to load the content up front and then do the heavy lifting of handling user interaction and thus minimizing the amount of communication needed between the client and the server, making the app more reactive.
However this can lead to longer initial load times, especially if the SPA is large and rich in its content. In order to optimize load times, some of the content can be rendered server-side. Using server side rendering (SSR) can accelerate the initial load of the page and then pass further rendering on to the client.

When to Use SSR

SSR is not required on all projects. Althgouh AEM fully supports JS SSR for SPA, Adobe does not recommend implementing it systematically for every project.
When deciding to implement SSR you must first estimate what additional complexity, effort, and cost adding SSR realistically represents for the project, including the long term maintenance. An SSR architecture should be chosen only when the added value clearly exceeds the estimated costs.
SSR usually provides some value when there is a clear "yes" to either of the following questions:
  • SEO: Is SSR still actually required for your site to be properly indexed by the search engines that bring traffic? Keep in mind that the main search engine crawlers now evaluate JS.
  • Page Speed: Does SSR provide a measurable speed improvement in real-life environments and add to the overall user experience?
Only when one at least one of these two questions are answered with a clear "yes" for your project does Adobe recommend implementing SSR. The following sections describe how to do this using Adobe I/O Runtime.

Adobe I/O Runtime

If you are confident that your project requires the implementation of SSR , Adobe's recommended solution is to use Adobe I/O Runtime.
For more information on Adobe I/O Runtime, please see
The following secitons detail how Adobe I/O Runtime can be used to implement SSR for your SPA in two different models:
Adobe recommends a separate Adobe I/O Runtime instance for every AEM environment (author, publish, stage, etc.).

Remote Content Renderer Configuration

AEM must know where the remotely-rendered content can be retrieved. Regardless of which model you choose to implement for SSR , you will need to specify to AEM how to access this remote rendering service.
This is done via the RemoteContentRenderer - Configuration Factory OSGi service. Search for the string "RemoteContentRenderer" in the Web Console Configuration console at http://<host>:<port>/system/console/configMgr .
The following fields are available for the configuration:
  • Content path pattern - Regular expression in order to match a portion of the content, if necessary
  • Remote endpoint URL - URL of the endpoint that is responsible for the generating the content
    • Use the secured HTTPS protocol if not in local network.
  • Additional request headers - Additional headers to be added to the request sent to the remote endpoint
    • Pattern: key=value
  • Request timeout - Remote host request timeout in milliseconds
Regardless of if you choose to implement the AEM-driven communication flow or the Adobe I/O Runtime-driven flow , you must define a remote content renderer configuration.
This configuration also must be defined if you choose to use a custom Node.js server .
This configuration leverages the Remote Content Renderer , which has additional extension and customization options available.

AEM-Driven Communication Flow

When using SSR, the component interaction workflow of SPAs in AEM includes a phase in which the initial content of the app is generated by Adobe I/O Runtime.
  1. The browser requests the SSR content from AEM.
  2. AEM posts the model to Adobe I/O Runtime.
  3. Adobe I/O Runtime returns the generated content
  4. AEM serves the HTML returned by Adobe I/O Runtime via the HTL template of the backend page component.

Adobe I/O Runtime-Driven Communication Flow

The section AEM-Driven Communication Flow describes the standard and recommended implementation of server side rendering with regards to SPAs in AEM, where AEM performs the bootstrapping and serving of content.
Alternatively, SSR can be implemented so that Adobe I/O Runtime is responsible for the bootstrapping, effectively reversing the communication flow.
Both models are valid and supported by AEM. However, one should consider the advantages and disadvantages of each before implementing a particular model.
Bootstrapping
Advantages
Disadvantages
via AEM
AEM manages injecting libraries where needed
Resources only need to be maintained on AEM
Possibly unfamiliar to SPA developer
via Adobe I/O Runtime
More familiar to SPA developers
Clientlib resources required by the application such as CSS and JavaScript will need to be made available by the AEM developer via the allowProxy
Resources must be synched between AEM and Adobe I/O Runtime
To enable authoring of the SPA, a proxy server for Adobe I/O Runtime may be necessary

Planning for SSR

Generally only part of an application needs to be rendered server side. The common example is the content that will be displayed above the fold on the initial load of the page needs to be rendered server side. This saves time by delivering to the client, already rendered content. As the user interacts with the SPA, the additional content is rendered by the client.
As you consider implementing server side rendering for your SPA, you need to review which parts of the app it will require SSR.

Developing an SPA using SSR

SPA components could be rendered by the client (in the browser) or server side. When rendered server side, browser properties such as window size and location are not present. Therefore SPA components should be isomorphic, making no assumption about where they will be rendered.
To leverage SSR, you will need to deploy your code in AEM as well as on Adobe I/O Runtime, which is responsible for the server side rendering. Most of the code will be the same, however server-specific tasks will differ.

SSR for SPAs in AEM

SSR for SPAs in AEM require Adobe I/O Runtime, which is called for the rendering of the app content server side. Within the HTL of the app, a resource on Adobe I/O Runtime is called to render the content.
Just as AEM supports the Angular and React SPA frameworks out-of-the box, server side rendering is also supported for Angular and React apps. See the NPM documentation for both frameworks for further details.
For a simplistic example, please refer to the We.Retail Journal app . It renders the entire application server side. Although this is not a real-world example, it does illustrate what is needed to implement SSR.
The We.Retail Journal app is for demonstration purposes only and therefore uses Node.js as a simple example instead of the recommended Adobe I/O Runtime. This example should not be used for any project work.
All SPA projects on AEM should be based on the Maven Archetype for SPA Starter Kit .

Using Node.js

Adobe I/O Runtime is the recommended solution for implementing SSR for SPAs in AEM.
For on-premesis AEM instances, it is also possible to implement SSR using a custom Node.js instance in the same way as described above. Although this is supported by Adobe, it is not recommended.
Node.js is not supported for Adobe-hosted AEM instances.
If SSR must be implemented via Node.js, Adobe recommends a separate Node.js instance for every AEM environment (author, publish, stage, etc.).

Remote Content Renderer

The Remote Content Renderer Configuration that is required to use SSR with your SPA in AEM taps into a more generalized rendering service that can be extended and customized to meet your needs.

RemoteContentRenderingService

RemoteContentRenderingService is an OSGi service to retrieve content rendered on a remote server, such as from Adobe I/O. The content sent to the remote server is based on the request parameter passed.
RemoteContentRenderingService can be injected by dependency inversion into either a custom Sling model or servlet when additional content manipulation is required.
This service is internally used by the RemoteContentRendererRequestHandlerServlet .

RemoteContentRendererRequestHandlerServlet

The RemoteContentRendererRequestHandlerServlet can be used to programmatically set the request configuration. DefaultRemoteContentRendererRequestHandlerImpl , the provided default request handler implementation, allows you to create multiple OSGi configurations in order to map a location in the content structure to a remote endpoint.
To add a custom request Handler, implement the RemoteContentRendererRequestHandler interface. Be sure to set the Constants.SERVICE_RANKING component property to an integer higher than 100, which is the ranking of the DefaultRemoteContentRendererRequestHandlerImpl .
@Component(immediate = true,
        service = RemoteContentRendererRequestHandler.class,
        property={
            Constants.SERVICE_RANKING +":Integer=1000"
        })
public class CustomRemoteContentRendererRequestHandlerImpl implements RemoteContentRendererRequestHandler {}

Configure the OSGi Configuration of the Default Handler

The configuration of the default handler must be configured as described in the section Remote Content Renderer Configuration .
### Remote Content Renderer Usage
To have a servlet fetch and return some content that can be injected into the page:
  1. Ensure your remote server is accessible.
  2. Add one of the following snippets to the HTL template of an AEM component.
  3. Optionally, create or modify the OSGi configurations.
  4. Browse the content of your site
Usually, the HTL template of a page component is the main recipient of such a feature.
<sly data-sly-resource="${resource @ resourceType='cq/remote/content/renderer/request/handler'}" />

Requirements

The servlets leverage the Sling Model Exporter to serialize the component data. By default, both the com.adobe.cq.export.json.ContainerExporter and com.adobe.cq.export.json.ComponentExporter are supported as Sling Model adapters. If necessary, you can add classes that the request should be adapted to using the RemoteContentRendererServlet and implementing the RemoteContentRendererRequestHandler#getSlingModelAdapterClasses . The additional classes must extend the ComponentExporter .