Configure AEM for SPA Editor
While the SPA codebase is managed outside of AEM, an AEM project is required to setup supporting configuration and content requirements. This chapter walks through the creation of an AEM project that contains necessary configurations:
- AEM WCM Core Components proxies
- AEM Remote SPA Page proxy
- AEM Remote SPA Page Templates
- Baseline Remote SPA AEM pages
- Subproject to define SPA to AEM URL mappings
- OSGi configuration folders
Download the base project from GitHub
Download the aem-guides-wknd-graphql
project from Github.com. This will contain some baseline files used in this project.
$ mkdir -p ~/Code
$ git clone https://github.com/adobe/aem-guides-wknd-graphql.git
$ cd remote-spa-tutorial
Create an AEM project
Create an AEM project in which configurations and baseline content are managed. This project will be generated within the cloned aem-guides-wknd-graphql
project’s remote-spa-tutorial
folder.
Always use the latest version of the AEM Archetype.
$ cd ~/Code/aem-guides-wknd-graphql/remote-spa-tutorial
$ mvn -B archetype:generate \
-D archetypeGroupId=com.adobe.aem \
-D archetypeArtifactId=aem-project-archetype \
-D archetypeVersion=39 \
-D aemVersion=cloud \
-D appTitle="WKND App" \
-D appId="wknd-app" \
-D groupId="com.adobe.aem.guides.wkndapp" \
-D frontendModule="react"
$ mv ~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/wknd-app ~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/com.adobe.aem.guides.wknd-app
The last command simply renames the AEM project folder so it is clear it’s the AEM project, and not to be confused with Remote SPA_
While frontendModule="react"
is specified, the ui.frontend
project is not used for the Remote SPA use case. The SPA is developed and managed externally to AEM and only uses AEM as a content API. The frontendModule="react"
flag is required for the project include the spa-project
AEM Java™ dependencies and set up the Remote SPA Page Templates.
The AEM Project Archetype generates the following elements that used to configure AEM for integration with the SPA.
- AEM WCM Core Components proxies at
ui.apps/src/.../apps/wknd-app/components
- AEM SPA Remote Page proxy at
ui.apps/src/.../apps/wknd-app/components/remotepage
- AEM Page Templates at
ui.content/src/.../conf/wknd-app/settings/wcm/templates
- Subproject to define content mappings at
ui.content/src/...
- Baseline Remote SPA AEM pages at
ui.content/src/.../content/wknd-app
- OSGi configuration folders at
ui.config/src/.../apps/wknd-app/osgiconfig
With the base AEM project is generated, a few adjustments ensure SPA Editor compatibility with Remote SPAs.
Remove ui.frontend project
Since the SPA is a Remote SPA, assume it’s developed and managed outside of the AEM project. To avoid conflicts, remove the ui.frontend
project from deploying. If the ui.frontend
project is not removed, two SPAs, the default SPA provided in the ui.frontend
project and the Remote SPA, is loaded at the same time in the AEM SPA Editor.
-
Open the AEM project (
~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/com.adobe.aem.guides.wknd-app
) in your IDE -
Open the root
pom.xml
-
Comment the
<module>ui.frontend</module
out from the<modules>
listcode language-none <modules> <module>all</module> <module>core</module> <!-- <module>ui.frontend</module> --> <module>ui.apps</module> <module>ui.apps.structure</module> <module>ui.config</module> <module>ui.content</module> <module>it.tests</module> <module>dispatcher</module> <module>ui.tests</module> <module>analyse</module> </modules>
The
pom.xml
file should look like: -
Open the
ui.apps/pom.xml
-
Comment out the
<dependency>
on<artifactId>wknd-app.ui.frontend</artifactId>
code language-none <dependencies> <!-- Remote SPA project will provide all frontend resources <dependency> <groupId>com.adobe.aem.guides.wkndapp</groupId> <artifactId>wknd-app.ui.frontend</artifactId> <version>${project.version}</version> <type>zip</type> </dependency> --> </dependencies>
The
ui.apps/pom.xml
file should look like:
If the AEM project was built before these changes, manually delete the ui.frontend
generated Client Library from the ui.apps
project at ui.apps/src/main/content/jcr_root/apps/wknd-app/clientlibs/clientlib-react
.
AEM content mapping
For AEM to load the Remote SPA in the SPA Editor, mappings between the SPA’s routes and the AEM Pages used to open and author content must be established.
The importance of this configuration is explored later.
The mapping can be done with Sling Mapping defined in /etc/map
.
-
In the IDE, open the
ui.content
subproject -
Navigate to
src/main/content/jcr_root
-
Create a folder
etc
-
In
etc
, create a foldermap
-
In
map
, create a folderhttp
-
In
http
, create a file.content.xml
with the contents:code language-none <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="sling:Mapping"> <localhost_any/> </jcr:root>
-
In
http
, create a folderlocalhost_any
-
In
localhost_any
, create a file.content.xml
with the contents:code language-none <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="sling:Mapping" sling:match="localhost\\.\\d+"> <wknd-app-routes-adventure/> </jcr:root>
-
In
localhost_any
, create a folderwknd-app-routes-adventure
-
In
wknd-app-routes-adventure
, create a file.content.xml
with the contents:code language-none <?xml version="1.0" encoding="UTF-8"?> <!-- The 'wknd-app-routes-adventure' mapping, maps requests to the SPA's adventure route to it's corresponding page in AEM at /content/wknd-app/us/en/home/adventure/xxx. Note the adventure AEM pages are created directly in AEM. --> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="sling:Mapping" sling:match="adventure:.*/([^/]+)/?$" sling:internalRedirect="/content/wknd-app/us/en/home/adventure/$1"/>
-
Add the mapping nodes to
ui.content/src/main/content/META-INF/vault/filter.xml
to they included in the AEM package.code language-none <?xml version="1.0" encoding="UTF-8"?> <workspaceFilter version="1.0"> <filter root="/conf/wknd-app" mode="merge"/> <filter root="/content/wknd-app" mode="merge"/> <filter root="/content/dam/wknd-app/asset.jpg" mode="merge"/> <filter root="/content/experience-fragments/wknd-app" mode="merge"/> <!-- Add the Sling Mapping rules for the WKND App --> <filter root="/etc/map" mode="merge"/> </workspaceFilter>
The folder structure and .context.xml
files should look like:
The filter.xml
file should look like:
Now, when the AEM project is deployed, these configurations are automatically included.
The Sling Mapping effects AEM running on http
and localhost
, so only support local development. When deploying to AEM as a Cloud Service, similar Sling Mappings must be added that target https
and the appropriate AEM as a Cloud Service domain/s. For more information, see the Sling Mapping documentation.
Cross-Origin Resource Sharing security policies
Next, configure AEM to protect the content so only this SPA can access the AEM content. Configure Cross-Origin Resource Sharing in AEM.
-
In your IDE, open the
ui.config
Maven subproject -
Navigate
src/main/content/jcr_root/apps/wknd-app/osgiconfig/config
-
Create a file named
com.adobe.granite.cors.impl.CORSPolicyImpl~wknd-app_remote-spa.cfg.json
-
Add the following to the file:
code language-none { "supportscredentials":true, "exposedheaders":[ "" ], "supportedmethods":[ "GET", "HEAD", "POST", "OPTIONS" ], "alloworigin":[ "https://external-hosted-app", "localhost:3000" ], "maxage:Integer":1800, "alloworiginregexp":[ ".*" ], "allowedpaths":[ ".*" ], "supportedheaders":[ "Origin", "Accept", "X-Requested-With", "Content-Type", "Access-Control-Request-Method", "Access-Control-Request-Headers", "authorization" ] }
The com.adobe.granite.cors.impl.CORSPolicyImpl~wknd-app_remote-spa.cfg.json
file should look like:
The key configuration elements are:
-
alloworigin
specifies which hosts are allowed to retrieve content from AEM.localhost:3000
is added to support the SPA running locallyhttps://external-hosted-app
acts as a placeholder to be replaced with the domain that Remote SPA is hosted on.
-
allowedpaths
specify which paths in AEM are covered by this CORS configuration. The default allows access to all content in AEM, however this can be scoped to only the specific paths the SPA can access, for example:/content/wknd-app
.
Set AEM Page as Remote SPA Page Template
The AEM Project Archetype generates a project primed for AEM’s integration with a Remote SPA, but requires a small, but important adjustment to auto-generated AEM page structure. The auto-generated AEM page must have its type changed to Remote SPA page, rather than a SPA page.
-
In your IDE, open the
ui.content
subproject -
Open to
src/main/content/jcr_root/content/wknd-app/us/en/home/.content.xml
-
Update this
.content.xml
file with:code language-none <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="cq:Page"> <jcr:content cq:template="/conf/wknd-app/settings/wcm/templates/spa-remote-page" jcr:primaryType="cq:PageContent" jcr:title="WKND App Home Page" sling:resourceType="wknd-app/components/remotepage"> <root jcr:primaryType="nt:unstructured" sling:resourceType="wcm/foundation/components/responsivegrid"> <responsivegrid jcr:primaryType="nt:unstructured" sling:resourceType="wcm/foundation/components/responsivegrid"> <text jcr:primaryType="nt:unstructured" sling:resourceType="wknd-app/components/text" text="<p>Hello World!</p>" textIsRich="true"> <cq:responsive jcr:primaryType="nt:unstructured"/> </text> </responsivegrid> </root> </jcr:content> </jcr:root>
The key changes are updates to the jcr:content
node’s:
cq:template
to/conf/wknd-app/settings/wcm/templates/spa-remote-page
sling:resourceType
towknd-app/components/remotepage
The src/main/content/jcr_root/content/wknd-app/us/en/home/.content.xml
file should look like:
These changes allow this page, which acts are the SPA’s root in AEM, to load the Remote SPA in SPA Editor.
ui.content
project is set to merge nodes, rather than update.This page could also be removed and re-created as a Remote SPA Page in AEM itself, however since this page is auto-created in the ui.content
project it is best to update it in the code base.
Deploy the AEM Project to AEM SDK
-
Ensure that AEM Author service is running on port 4502
-
From the command line, navigate to the root of the AEM Maven project
-
Use Maven to deploy the project to your local AEM SDK Author service
code language-none $ mvn clean install -PautoInstallSinglePackage
Configure the root AEM page
With the AEM Project deployed, there is one last step to prepare SPA Editor to load our Remote SPA. In AEM, mark the AEM page that corresponds to the SPA’s root,/content/wknd-app/us/en/home
, generated by the AEM Project Archetype.
-
Log in to AEM Author
-
Navigate to Sites > WKND App > us > en
-
Select the WKND App Home Page, and tap Properties
-
Navigate to the SPA tab
-
Fill out the Remote SPA Configuration
- SPA Host URL:
http://localhost:3000
- The URL to the root of the Remote SPA
- SPA Host URL:
-
Tap Save & Close
Remember that we changed this page’s type to that of a Remote SPA Page, which is what allows us to see the SPA tab in its Page Properties.
This configuration only must be set on the AEM page that corresponds to the root of the SPA. All AEM pages beneath this page inherit the value.
Congratulations
You’ve now prepared AEM’s configurations and deployed them to your local AEM author! You now know how to:
- Remove the AEM Project Archetype-generated SPA, by commenting out the dependencies in
ui.frontend
- Add Sling Mappings to AEM that map the SPA routes to resources in AEM
- Set up AEM’s Cross-Origin Resource Sharing security policies that allow the Remote SPA to consume content from AEM
- Deploy the AEM project to your local AEM SDK Author service
- Mark an AEM Page as the Remote SPA’s root using the SPA Host URL page property
Next Steps
With AEM configured, we can focus on bootstrapping the Remote SPA with support for editable areas using AEM SPA Editor!