Skip to content

Commit

Permalink
SITES-7941: add a decoupled frontend project (#1002)
Browse files Browse the repository at this point in the history
* feat: add decoupled spa
* fix: add manifest and favicon for decoupled fe
* feat: adapt to file names of react-scripts 5
* fix: theme package name
* fix: remove resource resolver factory config for SPA
* fix: redirect to home page for SPA projects
* fix: add html page items always to xfpages
* docs: add some introduction for decoupled frontend, link to aem-react-spa
  • Loading branch information
buuhuu authored Nov 21, 2022
1 parent f5b19b7 commit 70ab0e8
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 23 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ Maven template that creates a minimal, best-practices-based Adobe Experience Man
* **Responsive Layout:** On templates or individual pages, [define how the elements reflow](https://docs.adobe.com/content/help/en/experience-manager-65/authoring/siteandpage/responsive-layout.html) for the defined breakpoints.
* **Header and Footer:** Assemble and localize them without code, using the [localization features of the components](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/get-started/localization.html).
* **Style System:** Avoid building custom components by allowing authors to [apply different styles](https://docs.adobe.com/content/help/en/experience-manager-learn/getting-started-wknd-tutorial-develop/style-system.html) to them.
* **Front-End Build:** Front-end devs can [mock AEM pages](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/developing/archetype/uifrontend.html#webpack-dev-server) and [build client libraries](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/developing/archetype/uifrontend.html) with Webpack, TypeScript, and SASS.
* **Front-End Build:** Front-end devs can [mock AEM pages](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/developing/archetype/uifrontend.html#webpack-dev-server) and [build client libraries](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/developing/archetype/uifrontend.html) with Webpack, TypeScript, and SASS.
* **Decoupled Front-End:** When chosing the frontend module to be decoupled, the project is preconfigured to use the [AEMaaCS Frontend Pipeline](https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/sites/administering/site-creation/enable-front-end-pipeline.html). See [the AEM React SPA](https://github.com/adobe/aem-react-spa) template for more details how to get started with a decoupled frontend module using React.
* **WebApp-Ready:** For sites using [React](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/developing/archetype/uifrontend-react.html) or [Angular](https://docs.adobe.com/content/help/en/experience-manager-core-components/using/developing/archetype/uifrontend-angular.html), use the [SPA SDK](https://docs.adobe.com/content/help/en/experience-manager-64/developing/headless/spas/spa-architecture.html) to retain [in-context authoring of the app](https://docs.adobe.com/content/help/en/experience-manager-learn/sites/spa-editor/spa-editor-framework-feature-video-use.html).
* **Commerce Enabled:** For projects that want to use Commerce Integration Framework ([CIF](https://github.com/adobe/aem-core-cif-components)) to integrate with commerce solutions like Magento.
* **Forms Enabled:** For projects that want to use ([Forms](https://github.com/adobe/aem-core-forms-components)).
Expand Down Expand Up @@ -76,7 +77,7 @@ Name | Default | Description
`aemVersion` | `cloud` | Target AEM version (can be `cloud` for [AEM as a Cloud Service](https://docs.adobe.com/content/help/en/experience-manager-cloud-service/landing/home.html); or `6.5.5` for [Adobe Managed Services](https://github.com/adobe/aem-project-archetype/tree/master/src/main/archetype/dispatcher.ams) or on-premise).
`sdkVersion` | `latest` | When `aemVersion=cloud` an [SDK](https://docs.adobe.com/content/help/en/experience-manager-cloud-service/implementing/developing/aem-as-a-cloud-service-sdk.html) version can be specified (e.g. `2020.02.2265.20200217T222518Z-200130`).
`includeDispatcherConfig` | `y` | Includes a dispatcher configuration either for cloud or for AMS/on-premise, depending of the value of `aemVersion` (can be `y` or `n`).
`frontendModule` | `general` | Includes a Webpack frontend build module that generates the client libraries (can be `general` or `none` for regular sites; can be `angular` or `react` for a Single Page App that implements the [SPA Editor](https://docs.adobe.com/content/help/en/experience-manager-65/developing/headless/spas/spa-overview.html)).
`frontendModule` | `general` | Includes a Webpack frontend build module that generates the client libraries (can be `general` or `none` for regular sites; can be `angular`, `react` or `decoupled` for a Single Page App that implements the [SPA Editor](https://docs.adobe.com/content/help/en/experience-manager-65/developing/headless/spas/spa-overview.html). In the later case the project will be preconfigured to use the [AEM as a Cloud Service Frontend Pipeline](https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/sites/administering/site-creation/enable-front-end-pipeline.html)).
`language` | `en` | Language code (ISO 639-1) to create the content structure from (e.g. `en`, `deu`).
`country` | `us` | Country code (ISO 3166-1) to create the content structure from (e.g. `US`).
`singleCountry` | `y` | Includes a language-master content structure (can be `y`, or `n`).
Expand Down
6 changes: 3 additions & 3 deletions src/main/archetype/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#set( $symbol_escape = '\' )
#set( $startbrace = "{" )
#set( $endbrace = "}" )
#set( $isSpaProject = $frontendModule == "angular" || $frontendModule == "react" )
#set( $isSpaProject = $frontendModule == "angular" || $frontendModule == "react" || $frontendModule == "decoupled" )
#set( $includeClassifierOnUberJar = $aemVersion.matches("6\.5\.[0-5]") )

<modelVersion>4.0.0</modelVersion>
Expand All @@ -38,7 +38,7 @@
<modules>
<module>all</module>
<module>core</module>
#if ( $frontendModule != "none" )
#if ( $frontendModule != "none" && $frontendModule != "decoupled" )
<module>ui.frontend</module>
#end
#if ( $includeFormsheadless == "y" )
Expand Down Expand Up @@ -89,7 +89,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
#if ( $isSpaProject )
<spa.project.core.version>1.3.12</spa.project.core.version>
<spa.project.core.version>1.3.16</spa.project.core.version>
#end
#if ( $frontendModule == "angular" )
<!--
Expand Down
2 changes: 1 addition & 1 deletion src/main/archetype/ui.apps/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Require-Capability: osgi.extender;filter:="(&(osgi.extender=sling.scripting)(ver
<version>${project.version}</version>
</dependency>

#if ( $frontendModule != "none" )
#if ( $frontendModule != "none" && $frontendModule != "decoupled" )
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${rootArtifactId}.ui.frontend</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
SPA-specific meta tags
*/-->
<meta name="theme-color" content="#000000" />
#if ( $frontendModule != "decoupled" )
<link rel="icon" href="/etc.clientlibs/${appId}/clientlibs/clientlib-${frontendModule}/resources/favicon.ico" />
<link rel="apple-touch-icon" href="/etc.clientlibs/${appId}/clientlibs/clientlib-${frontendModule}/resources/logo192.png" />
<link rel="manifest" href="/etc.clientlibs/${appId}/clientlibs/clientlib-${frontendModule}/resources/manifest.json" />

#end
<!-- AEM page model -->
<meta
property="cq:pagemodel_root_url"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,10 @@

#end


<sly data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page"
data-sly-list="${symbol_dollar}{page.htmlPageItems}">
<script data-sly-test="${symbol_dollar}{item.location.name == 'footer'}"
data-sly-element="${symbol_dollar}{item.element.name @ context='unsafe'}"
data-sly-attribute="${symbol_dollar}{item.attributes}"></script>
</sly>

Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,16 @@

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html"/>

#if ( $frontentModule != "decoupled" )
<sly data-sly-call="${symbol_dollar}{clientlib.all @ categories=['coralui3']}"/>
<sly data-sly-call="${symbol_dollar}{clientlib.css @ categories=['${appId}.base']}"/>
#end

<sly data-sly-list="${page.htmlPageItems}">
<script data-sly-test="${symbol_dollar}{item.location.name == 'header'}"
data-sly-element="${symbol_dollar}{item.element.name @ context='unsafe'}"
data-sly-attribute="${symbol_dollar}{item.attributes}"></script>
</sly>

#else

Expand All @@ -45,4 +53,12 @@
<!--/* Include Context Hub */-->
<sly data-sly-resource="${'contexthub' @ resourceType='granite/contexthub/components/contexthub'}"/>

#end
<sly data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page"
data-sly-list="${page.htmlPageItems}">
<script data-sly-test="${symbol_dollar}{item.location.name == 'header'}"
data-sly-element="${symbol_dollar}{item.element.name @ context='unsafe'}"
data-sly-attribute="${symbol_dollar}{item.attributes}"></script>
</sly>

#end

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?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" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured">
<com.adobe.cq.wcm.core.components.internal.DataLayerConfig
jcr:primaryType="nt:unstructured"
Expand All @@ -13,4 +13,106 @@
jcr:primaryType="nt:unstructured"
clientId="28b07c6be4d544f188dc2f36e33b196b"
reportSuiteId=""/>
#if ( $frontendModule == 'decoupled')
<com.adobe.aem.wcm.site.manager.config.SiteConfig
jcr:primaryType="nt:unstructured"
siteTemplatePath="/libs/wcm/core/site-templates/aem-site-template-stub-2.0.0"
themePackageName="${appId}"/>
<com.adobe.cq.wcm.core.components.config.HtmlPageItemsConfig
jcr:primaryType="cq:Page">
<jcr:content
jcr:primaryType="cq:PageContent"
prefixPath="http://localhost:3000">
<items jcr:primaryType="nt:unstructured">
<css
jcr:primaryType="nt:unstructured"
element="link"
location="header">
<attributes jcr:primaryType="nt:unstructured">
<as
jcr:primaryType="nt:unstructured"
name="as"
value="style"/>
<href
jcr:primaryType="nt:unstructured"
name="href"
value="/static/css/main.css"/>
<rel
jcr:primaryType="nt:unstructured"
name="rel"
value="preload stylesheet"/>
<type
jcr:primaryType="nt:unstructured"
name="type"
value="text/css"/>
</attributes>
</css>
<main
jcr:primaryType="nt:unstructured"
element="script"
location="header">
<attributes jcr:primaryType="nt:unstructured">
<src
jcr:primaryType="nt:unstructured"
name="src"
value="/static/js/main.js"/>
<defer
jcr:primaryType="nt:unstructured"
name="defer"
value="true"/>
<type
jcr:primaryType="nt:unstructured"
name="type"
value="text/javascript"/>
</attributes>
</main>
<favicon
jcr:primaryType="nt:unstructured"
element="link"
location="header">
<attributes jcr:primaryType="nt:unstructured">
<href
jcr:primaryType="nt:unstructured"
name="href"
value="/favicon.ico"/>
<rel
jcr:primaryType="nt:unstructured"
name="rel"
value="icon"/>
</attributes>
</favicon>
<appleTouchIcon
jcr:primaryType="nt:unstructured"
element="link"
location="header">
<attributes jcr:primaryType="nt:unstructured">
<href
jcr:primaryType="nt:unstructured"
name="href"
value="/logo192.png"/>
<rel
jcr:primaryType="nt:unstructured"
name="rel"
value="apple-touch-icon"/>
</attributes>
</appleTouchIcon>
<manifest
jcr:primaryType="nt:unstructured"
element="link"
location="header">
<attributes jcr:primaryType="nt:unstructured">
<href
jcr:primaryType="nt:unstructured"
name="href"
value="/manifest.json"/>
<rel
jcr:primaryType="nt:unstructured"
name="rel"
value="manifest"/>
</attributes>
</manifest>
</items>
</jcr:content>
</com.adobe.cq.wcm.core.components.config.HtmlPageItemsConfig>
#end
</jcr:root>
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,10 @@
<policy_spa
jcr:primaryType="nt:unstructured"
jcr:title="${appTitle} SPA Page Policy"
sling:resourceType="wcm/core/components/policy/policy"
clientlibs="[${appId}.${frontendModule}]">
#if ( $frontendModule != "decoupled" )
clientlibs="[${appId}.${frontendModule}]"
#end
sling:resourceType="wcm/core/components/policy/policy">
<jcr:content jcr:primaryType="nt:unstructured"/>
</policy_spa>
#end
Expand All @@ -435,7 +437,9 @@
jcr:primaryType="nt:unstructured"
jcr:title="${appTitle} App Policy"
sling:resourceType="wcm/core/components/policy/policy"
#if ( $frontendModule != "decoupled" )
clientlibs="[${appId}.${frontendModule}]"
#end
isRoot="{Boolean}true"
structureDepth="3"
/>
Expand Down Expand Up @@ -611,7 +615,7 @@
jcr:primaryType="nt:unstructured"
jcr:title="SPA Content"
sling:resourceType="wcm/core/components/policy/policy"
components="[/libs/wcm/foundation/components/responsivegrid,/apps/${appId}/components/text]">
components="[group:${appTitle} - Content]">
<jcr:content jcr:primaryType="nt:unstructured"/>
</spa-default>
#if ( ($includeForms == "y" or $includeFormsenrollment == "y" or $includeFormscommunications == "y") and $aemVersion == "cloud")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
<jcr:content
cq:allowedTemplates="[/conf/${appId}/settings/wcm/templates/(?!xf-).*]"
cq:conf="/conf/${appId}"
cq:redirectTarget="/content/${appId}/${country}/${language}"
#if ( $isSpaProject )
cq:redirectTarget="/content/${appId}/${country}/${language}/home"
cq:template="/conf/${appId}/settings/wcm/templates/spa-app-template"
#else
cq:redirectTarget="/content/${appId}/${country}/${language}"
cq:template="/conf/${appId}/settings/wcm/templates/page-content"
#end
jcr:primaryType="cq:PageContent"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?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:lastModified="{Date}2018-10-04T09:50:29.650+02:00"
cq:lastModifiedBy="admin"
cq:template="/conf/${appId}/settings/wcm/templates/spa-page-template"
jcr:primaryType="cq:PageContent"
jcr:title="${appTitle} Home Page"
sling:resourceType="${appId}/components/page">
<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="${appId}/components/text"
text="&lt;p>Hello World!&lt;/p>"
textIsRich="true">
<cq:responsive jcr:primaryType="nt:unstructured"/>
</text>
</responsivegrid>
</root>
</jcr:content>
</jcr:root>
Loading

0 comments on commit 70ab0e8

Please sign in to comment.