Managing AEM hosts
Deploying an AEM Headless application requires attention to how AEM URLs are constructed to ensure the correct AEM host/domain is used. The primary URL/request types to be aware of are:
- HTTP requests to AEM GraphQL APIs
- Image URLs to image assets referenced in Content Fragments, and delivered by AEM
Typically, an AEM Headless app interacts with a single AEM service for both GraphQL API and image requests. The AEM service changes based on the AEM Headless app deployment:
To handle deployment type permutations, each app deployment is built using a configuration specifying the AEM service to connect to. The configured AEM service鈥檚 host/domain is then used to construct the AEM GraphQL API URLs and Image URLs. To determine the correct approach for managing build dependent configurations, reference the AEM Headless app鈥檚 framework (for example, React, iOS, Android鈩, and so on) documentation, as the approach varies by framework.
The following are examples of possible approaches for constructing URLs for AEM GraphQL API and image requests, for several popular headless frameworks and platforms.
AEM GraphQL API requests
The HTTP GET requests from the headless app to AEM鈥檚 GraphQL APIs must be configured to interact with the correct AEM service, as described in the table above.
When using AEM Headless SDKs (available for browser-based JavaScript, server-based JavaScript, and Java鈩), an AEM host can initialize the AEM Headless client object with the AEM Service to connect with.
When developing a custom AEM Headless client, ensure the AEM service鈥檚 host is parameterize-able based on build parameters.
Examples
The following are examples of how AEM GraphQL API requests can have the AEM host value made configurable for various headless app frameworks.
This example, loosely based on the AEM Headless React app, illustrates how AEM GraphQL API requests can be configured to connect to different AEM Services based on environment variables.
React apps should use the AEM Headless Client for JavaScript to interact with AEM鈥檚 GraphQL APIs. The AEM Headless client, provided by the AEM Headless Client for JavaScript, must be initialized with the AEM Service host it connects to.
React environment file
React uses , or .env files, stored in the root of the project to define build-specific values. For example, the .env.development file contains values used for during development, while .env.production contains values used for production builds.
.env.development
| code language-none |
|---|
|
.env files for other uses by postfixing .env and a semantic descriptor, such as .env.stage or .env.production. Different .env files can be used when running or building the React app, by setting the REACT_APP_ENV before executing an npm command.
For example, a React app鈥檚 package.json may contain the following scripts config:
package.json
| code language-none |
|---|
|
AEM headless client
The AEM Headless Client for JavaScript contains an AEM Headless client that makes HTTP requests to AEM鈥檚 GraphQL APIs. The AEM Headless client must be initialized with the AEM host it interacts with, using the value from the active .env file.
src/api/headlessClient.js
| code language-none |
|---|
|
React useEffect(鈥) hook
Custom React useEffect hooks call the AEM Headless client, initialized with the AEM host, on behalf of the React component rendering the view.
src/api/persistedQueries.js
| code language-javascript |
|---|
|
React component
The custom useEffect hook, useAdventureByPath is imported, and used to get the data using the AEM Headless client and ultimately render the content to the end user.
- 鈥荣谤肠/肠辞尘辫辞苍别苍迟蝉/础诲惫别苍迟耻谤别顿别迟补颈濒.箩蝉鈥
| code language-javascript |
|---|
|
This example, based on the example AEM Headless iOS鈩 app, illustrates how AEM GraphQL API requests can be configured to connect to different AEM hosts based on .
iOS鈩 apps require a custom AEM Headless client to interact with AEM鈥檚 GraphQL APIs. The AEM Headless client must be written such that the AEM service host is configurable.
Build configuration
The XCode configuration file contains the default configuration details.
Config.xcconfig
| code language-swift |
|---|
|
Initialize the custom AEM headless client
The uses a custom AEM headless client initialized with the config values for AEM_SCHEME and AEM_HOST.
| code language-swift |
|---|
|
The custom AEM headless client (api/Aem.swift) contains a method makeRequest(..) that prefixes AEM GraphQL APIs requests with the configured AEM scheme and host.
api/Aem.swift
| code language-swift |
|---|
|
to connect to different AEM services. The build-specific values for the AEM_SCHEME and AEM_HOST are used based on the selected build in XCode, resulting in the custom AEM Headless client to connect with the correct AEM service.
This example, based on the , illustrates how AEM GraphQL API requests can be configured to connect to different AEM Services based on build-specific (or flavors) configuration variables.
Android鈩 apps (when written in Java鈩) should use the to interact with AEM鈥檚 GraphQL APIs. The AEM Headless client, provided by the AEM Headless Client for Java鈩, must be initialized with the AEM Service host it connects to.
Build configuration file
Android鈩 apps define 鈥減roductFlavors鈥 that are used to build artifacts for different uses.
This example shows how two Android鈩 product flavors can be defined, providing different AEM service hosts (AEM_HOST) values for development (dev) and production (prod) uses.
In the app鈥檚 build.gradle file, a new flavorDimension named env is created.
In the env dimension, two productFlavors are defined: dev and prod. Each productFlavor uses buildConfigField to set build-specific variables defining the AEM service to connect to.
app/build.gradle
| code language-gradle |
|---|
|
Android鈩 loader
Initialize the AEMHeadlessClient builder, provided by the AEM Headless Client for Java鈩 with the AEM_HOST value from the buildConfigField field.
app/src/main/java/com/adobe/wknd/androidapp/loader/AdventuresLoader.java
| code language-java |
|---|
|
When building the Android鈩 app for different uses, specify the env flavor, and the corresponding AEM host value is used.
AEM image URLs
The image requests from the headless app to AEM must be configured to interact with the correct AEM service, as described in the above table.
51黑料不打烊 recommends using optimized images made available through the _dynamicUrl field in AEM鈥檚 GraphQL APIs. The _dynamicUrl field returns an host-less URL that can be prefixed with the AEM service host used to query AEM GraphQL APIs. For the _dynamicUrl field in the GraphQL response looks like:
{
...
"_dynamicUrl": "/adobe/dynamicmedia/deliver/dm-aid--dd42d814-88ec-4c4d-b5ef-e3dc4bc0cb42/example.jpg?preferwebp=true",
...
}
Examples
The following are examples of how image URLs can prefix the AEM host value made configurable for various headless app frameworks. The examples assume the use of GraphQL queries that return image references using the _dynamicUrl field.
For example:
GraphQL persisted query
This GraphQL query returns an image reference鈥檚 _dynamicUrl. As seen in the GraphQL response which excludes a host.
query ($path: String!) {
adventureByPath(_path: $path, _assetTransform: { format: JPG, preferWebp: true }) {
item {
title,
primaryImage {
... on ImageRef {
_dynamicUrl
}
}
}
}
}
GraphQL response
This GraphQL response returns the image reference鈥檚 _dynamicUrl which excludes a host.
{
"data": {
"adventureByPath": {
"item": {
"adventurePrimaryImage": {
"_dynamicUrl": "/adobe/dynamicmedia/deliver/dm-aid--de43411-88ec-4c4d-b5ef-e3dc4bc0cb42/adobestock-175749320.jpg?preferwebp=true",
}
}
}
}
}
This example, based on the example AEM Headless React app, illustrates how image URLs can be configured to connect to the correct AEM Services based on environment variables.
This example shows how prefix the image reference _dynamicUrl field, with a configurable REACT_APP_AEM_HOST React environment variable.
React environment file
React uses , or .env files, stored in the root of the project to define build-specific values. For example, the .env.development file contains values used for during development, while .env.production contains values used for production builds.
.env.development
| code language-none |
|---|
|
.env files for other uses by postfixing .env and a semantic descriptor, such as .env.stage or .env.production. Different .env file can be used when running or building the React app, by setting the REACT_APP_ENV before executing an npm command.
For example, a React app鈥檚 package.json may contain the following scripts config:
package.json
| code language-none |
|---|
|
React component
The React component imports the REACT_APP_AEM_HOST environment variable, and prefixes the image _dynamicUrl value, to provide a fully resolvable image URL.
This same REACT_APP_AEM_HOST environment variable is used to initialize the AEM Headless client used by useAdventureByPath(..) custom useEffect hook used to fetch the GraphQL data from AEM. Using the same variable to construct the GraphQL API request as the image URL, ensure that the React app interacts with the same AEM service for both use cases.
- 鈥荣谤肠/肠辞尘辫辞苍别苍迟蝉/础诲惫别苍迟耻谤别顿别迟补颈濒.箩蝉鈥
| code language-javascript |
|---|
|
This example, based on the example AEM Headless iOS鈩 app, illustrates how AEM image URLs can be configured to connect to different AEM hosts based on .
Build configuration
The XCode configuration file contains the default configuration details.
Config.xcconfig
| code language-swift |
|---|
|
Image URL generator
In Aem.swift, the custom AEM headless client implementation, a custom function imageUrl(..) takes the image path as provided in the _dynamicUrl field in the GraphQL response, and prepends it with AEM鈥檚 host. This function is then invoked in the iOS views whenever an image is rendered.
WKNDAdventures/AEM/Aem.swift
| code language-swift |
|---|
|
iOS view
The iOS view and prefixes the image _dynamicUrl value, to provide a fully resolvable image URL.
WKNDAdventures/Views/AdventureListItemView.swift
| code language-swift |
|---|
|
to connect to different AEM services. The build-specific values for the AEM_SCHEME and AEM_HOST are used based on the selected build in XCode, resulting in the custom AEM Headless client to interact with the correct AEM service.
This example, based on the , illustrates how AEM image URLs can be configured to connect to different AEM Services based on build-specific (or flavors) configuration variables.
Build configuration file
Android鈩 apps define 鈥減roductFlavors鈥 which are used to build artifacts for different uses.
This example shows how two Android鈩 product flavors can be defined, providing different AEM service hosts (AEM_HOST) values for development (dev) and production (prod) uses.
In the app鈥檚 build.gradle file, a new flavorDimension named env is created.
In the env dimension, two productFlavors are defined: dev and prod. Each productFlavor uses buildConfigField to set build-specific variables defining the AEM service to connect to.
app/build.gradle
| code language-gradle |
|---|
|
Loading the AEM image
The Android鈩 uses an ImageGetter to fetch and locally cache image data from AEM. In prepareDrawableFor(..) the AEM service host, defined in the active build config, is used to prefix the image path creating a resolvable URL to AEM.
app/src/main/java/com/adobe/wknd/androidapp/loader/RemoteImagesCache.java
| code language-java |
|---|
|
Android鈩 view
The Android鈩 view gets the image data by way of the RemoteImagesCache using the _dynamicUrl value from the GraphQL response.
app/src/main/java/com/adobe/wknd/androidapp/AdventureDetailFragment.java
| code language-java |
|---|
|
When building the Android鈩 app for different uses, specify the env flavor, and the corresponding AEM host value is used.