Wednesday, November 10, 2021

Single Page Application(SPA) Design Patterns with AEM(Adobe Experience Manager)

A single-page application is a web application or website that interacts with the user by dynamically rewriting the current web page with new data from the webserver, instead of the default method of a web browser loading entire new pages.

SPA application will provide some of the benefits like

  • Front end developer has full control over the app
  • Seamless UI experience
  • Ease in building more interactive applications
  • Better performance

But need to watch out on some the areas like

  • SEO optimization — MPA(Multi-Page Application) application may give better SEO considering multiple pages in the website for the search engines to crawl
  • Security issues — SPA applications are more prone to XSS attacks
  • No WYSIWYG editor for content authoring.
  • More dependency on Developments teams for site launches/site changes
  • Lack of analytic insights — Considering Single page, may not be able to get details Analytics like MPA

The Single Page Applications (SPA) may not be appropriate for all the use cases, should be selected carefully based on your need and use cases.

Considering the importance of SPA, now the focus is more on SPA with CMS — Consume the content from CMS systems to enable the SPA experience to end-users.

In this post let us discuss, How AEM works with SPA frameworks to enable a seamless experience for the end-users, and explore the different design patterns for SPA with AEM.

Headless SPA:

In this design pattern, the SPA application is completely separated from AEM, and content from AEM is consumed through headless GraphQL APIs as needed. The content in AEM is managed through Content Framnents and exposed through GraphQL API as a JSON.

In this pattern, the front-end developer has full control over the app but Content authors cannot leverage AEM’s content authoring experience.

High-level steps to enable this pattern-

  • Create Content Fragment Models in AEM to structure the Content
  • Author Content Fragments through Content Fragment Model
  • Enable QraphQL API’s
  • Enable CORS
  • Consume AEM’s GraphQL APIs from the SPA application

Refer to https://medium.com/tech-learnings/how-to-deliver-headless-content-through-graphql-api-and-content-fragments-da2b2d22df06 for more details on enabling Content Fragments and consuming the data through GraphQL API.

The persistent GraphQL queries can be used to improve the data fetching performance from the SPA application.

Any GraphQL libraries e.g Apollo GraphQL client can be used to fetch the data from AEM, Adobe already enabled some of the wrapper client libraries to fetch the data.

JS — https://github.com/adobe/aem-headless-client-js

Java — https://github.com/adobe/aem-headless-client-java

Node JS — https://github.com/adobe/aem-headless-client-nodejs

Refer to https://github.com/techforum-repo/youttubedata/tree/master/AEM-SPA for a quick simple demo(Refer to https://github.com/adobe/aem-guides-wknd-graphql for WKND demo)

Refer to https://experienceleague.adobe.com/docs/experience-manager-learn/getting-started-with-aem-headless/graphql/multi-step/overview.html?lang=en for more details on this design pattern.

Integrated SPA:

In this design, the SPA is integrated into AEM, the project fully leverages the SPA Editor SDK and the frontend components are developed as a library and the content structure of the app is delegated to AEM

The benefits of this design are, the content author can edit the app using AEM’s content authoring experience. The SPA is compatible with the template editor.

The developer is not in control of the structure of the app, the developer can still reserve areas of the app for content that is not meant to be authored using AEM.

The SPA is responsible for the routing and AEM listens to it and fetches the component data based on it.

SPA Editor — AEM’s SPA Editor provides support for in-context editing of a Single Page Application or SPA. Combine AEM’s rich content editing with all the benefits of SPAs

AEM’s SPA Editor JS SDK — In short, the SPA Editor JS SDK is a collection of open-source JavaScript libraries that provide a framework to enable the editable content for SPA pages through AEM SPA Editor.

@adobe/aem-spa-component-mapping
@adobe/aem-spa-page-model-manager
@adobe/aem-react-editable-components
@adobe/aem-core-components-react-base”
@adobe/aem-core-components-react-spa
@adobe/aem-angular-editable-components
@adobe/aem-core-components-angular-base
@adobe/aem-core-components-angular-spa

The basic concept is to map a SPA Component to an AEM Component. AEM components, running server-side, export content in the form of JSON. The JSON content is consumed by the SPA, running client-side in the browser. A 1:1 mapping between SPA components and an AEM component is created.

Supported Frameworks — React JS and Angular are supported out of the box.

The aem-project-archetype can be used to create AEM SPA projects

mvn -B archetype:generate \
-D archetypeGroupId=com.adobe.aem \
-D archetypeArtifactId=aem-project-archetype \
-D archetypeVersion=30 \
-D appTitle=”My Site” \
-D appId=”mysite” \
-D groupId=”com.mysite”
-D frontendModule=general

The value for the frontendModule parameter can be angular or react for a Single Page App

If required update the default values in .env/.env.development files under ui.frontend project

The aem-clientlib-generator module enabled as part of the ui.frontend project generates the AEM ClientLibraries for the SPA scripts.

The SPA components internally use the AEM Content Service API to fetch the required authored content — the JSON data exposed through JSON exporter.

If the existing SPA follows the AEM SPA development guidelines, then the SPA can be migrated to AEM and edited through the SPA editor

Refer to the below links for more details

migrating-existing-spas-to-aem

integrate-spa

Some of the limitations with the current version of SPA Editor — the below features are not currently supported by the SPA editor

  • Target mode
  • ContextHub
  • Inline image editing
  • Edit configs (eg. listeners)
  • Style System
  • Undo / Redo
  • Page diff and Time Warp
  • Features performing HTML rewriting server-side such as Link Checker, CDN rewriter service, URL shortening, etc.
  • Developer mode
  • AEM Launches

The SPA Editor(Integrated SPA) is the recommended solution for projects that use a SPA framework (React or Angular) with AEM.

External SPA with Editable Areas:

In this design, the SPA is hosted outside of AEM, the developer keeps control over the app by only enabling authoring in restricted areas of the app. The content for the editable areas is enabled by AEM content authors.

The Developer will keep full control of the SPA application but the Content authors are restricted to a limited set of AEM’s content authoring experience.

With the SPA Editor 2.0, it’s possible to enable the in-content editing to specific areas or snippets in the app.

High-level steps to enable this pattern —

  • Create SPA project with latest Maven Arch type — remove the ui.frontend module as the SPA is externaly hosted.

mvn -B archetype:generate \
-D archetypeGroupId=com.adobe.aem \
-D archetypeArtifactId=aem-project-archetype \
-D archetypeVersion=30 \
-D appTitle=”My Site” \
-D appId=”mysite” \
-D groupId=”com.mysite”\
-D frontendModule=react\

  • Deploy the AEM project
  • Create a Page using the “Remote SPA Page” template and enable the SPA URL to the page properties
  • Enable CORS policy in AEM to allow SPA application to fetch AEM content — the default configuration to support the localhost SPA is already enabled under ui.config/src/main/content\jcr_root/apps/spaeditableareas/osgiconfig/config.author/com.adobe.granite.cors.impl.CORSPolicyImpl~spaeditableareas.cfg.json(http://localhost:3000), modify based on your SPA URL
  • Enable CORS policy in SPA application to allow AEM to access the asset-manifest.json e.g http://localhost:3000/asset-manifest.json
  • Enable AEM Editor SDK’s to the SPA application
  • Instantiate/Initialization of the Model Manager — Proxy is enabled for local Development(fetch the model through the proxy), Model Manager with Model Client(AEM Publish Server URL) can be used to fetch the model from remote AEM publish servers
  • Enable Editable areas — Container(Page)/Fixed Components, the required components should be enabled in Template policy for the Layout container.
  • Edit content in AEM

Refer to https://experienceleague.adobe.com/docs/experience-manager-cloud-service/implementing/developing/hybrid/editing-external-spa.html?lang=en for more details.

Refer to https://github.com/techforum-repo/youttubedata/tree/master/AEM-SPA/externalspawitheditableareas for the sample project

Server-Side Rendering(SSR):

Server-side rendering (SSR) is rendering client-side SPAs on the server and then sending a fully rendered page to the client. This allows for dynamic components to be served as static HTML markup.

SSR is not required for all projects, select if SSR is going to provide more SEO and performance benefits, the SSR design will introduce additional complexity, effort, and cost.

Refer to the following URL https://experienceleague.adobe.com/docs/experience-manager-64/developing/headless/spas/spa-ssr.html?lang=en to understand more on SSR in AEM.

The SSR rendering can be enabled through Node JS/Express or Adobe Runtime I/O, Adobe recommends Adobe I/O runtime for enabling Server Side Rendering. There are two communication flows

  • AEM Driven — AEM performs the bootstrapping and serving of content
  • Adobe I/O driven — Adobe I/O Runtime is responsible for the bootstrapping.

Let us review AEM Driven communication flow — I am using Node JS/Express to enable SSR in my local system(Adobe recommends Adobe Runtime I/O to enable SSR)

High-level steps to enable this pattern —

  • Create SPA project with latest Maven Arch type

mvn -B archetype:generate \
-D archetypeGroupId=com.adobe.aem \
-D archetypeArtifactId=aem-project-archetype \
-D archetypeVersion=30 \
-D appTitle=”My Site” \
-D appId=”mysite” \
-D groupId=”com.mysite”\
-D frontendModule=react\
-D enableSSR=y

The parameter”enableSSR” enables SSR support for the front-end project.

  • If required update the default values in .env/.env.development files under ui.frontend project
  • Build/Strat and Deploy SSR — Various npm scripts are enabled in ui.frontend project (build-with-ssr, build-with-express, start-ssr-ioruntime, start-ssr-express, and deploy-ssr-ioruntime) — I am using build-with-express and start-ssr-express for my local testing. The SSR server will be running in default 3233 port while executing “build-with-express” and “start-ssr-express”
  • Deploy the complete project to AEM
  • Remote Content Renderer — ensure the Remote content renderer is enabled with correct “Content path pattern” and “Remote endpoint URL”, the default configuration is enabled while creating the new project — http://localhost:4502/system/console/configMgr/com.adobe.cq.remote.content.renderer.impl.factory.ConfigurationFactoryImpl~spassr (spassr is my project name)
  • Edit the required content in AEM

Now the content is Server Side rendered — http://localhost:4502/content/spassr/us/en/home.html?wcmmode=disabled, the content will be Client-Side Rendered if the SSR service is not available.

Refer to https://github.com/techforum-repo/youttubedata/tree/master/AEM-SPA/ssr/spassr for the sample project

In conclusion, the Single Page Applications (SPA) may not be appropriate for all the use cases, should be selected carefully based on your need and use cases. The integrated SPA model will be ideal for new AEM projects with SPA applications — this will give seamless authoring experience along with required control to Developers. In the case of SSR, Adobe recommends Adobe Runtime I/O for Server Side Rendering but Node JS flow is also supported.

No comments:

Post a Comment