Integración de una SPA
Creado para:
- Principiante
- Desarrollador
Comprenda cómo el código fuente de una aplicación de una sola página (SPA) escrita en Angular se puede integrar en un proyecto de Adobe Experience Manager (AEM). Aprenda a utilizar herramientas front-end modernas, como un servidor de desarrollo de Webpack, para desarrollar rápidamente la SPA con la API del modelo JSON de AEM.
Objetivo
- Comprenda cómo el proyecto de SPA está integrado con AEM con bibliotecas del lado del cliente.
- Aprenda a utilizar un servidor de desarrollo local para el desarrollo front-end dedicado.
- Explore el uso de un proxy y un archivo simulador estático para desarrollar con la API del modelo JSON de AEM
Qué va a generar
Este capítulo agregará un componente Header
simple a la SPA. En el proceso de crear este componente Header
estático se utilizan varios enfoques para el desarrollo de la SPA de AEM.
El SPA se ha ampliado para agregar un componente Header
estático
Requisitos previos
Revise las herramientas y las instrucciones necesarias para configurar un entorno de desarrollo local.
Obtener el código
-
Descargue el punto de partida para este tutorial mediante Git:
$ git clone git@github.com:adobe/aem-guides-wknd-spa.git $ cd aem-guides-wknd-spa $ git checkout Angular/integrate-spa-start
-
Implemente el código base en una instancia local de AEM mediante Maven:
$ mvn clean install -PautoInstallSinglePackage
Si usa AEM 6.x, agregue el perfil
classic
:$ mvn clean install -PautoInstallSinglePackage -Pclassic
Siempre puede ver el código terminado en GitHub o desprotegerlo localmente cambiando a la rama Angular/integrate-spa-solution
.
Enfoque de integración
Se crearon dos módulos como parte del proyecto AEM: ui.apps
y ui.frontend
.
El módulo ui.frontend
es un proyecto webpack que contiene todo el código fuente de la SPA. La mayoría del desarrollo y las pruebas de SPA se realizan en el proyecto de Webpack. Cuando se activa una compilación de producción, la SPA se crea y compila mediante Webpack. Los artefactos compilados (CSS y Javascript) se copian en el módulo ui.apps
, que luego se implementa en el tiempo de ejecución de AEM.
Representación de alto nivel de la integración de SPA.
Encontrará información adicional sobre la versión del front-end aquí.
Inspeccione la integración de SPA
A continuación, inspeccione el módulo ui.frontend
para comprender la SPA que ha generado automáticamente el arquetipo del proyecto AEM.
-
En el IDE de su elección, abra el proyecto de AEM para la SPA de WKND. Este tutorial usará el IDE de código de Visual Studio.
-
Expanda e inspeccione la carpeta
ui.frontend
. Abrir el archivoui.frontend/package.json
-
En
dependencies
debería ver varios elementos relacionados con@angular
:"@angular/animations": "~9.1.11", "@angular/common": "~9.1.11", "@angular/compiler": "~9.1.11", "@angular/core": "~9.1.11", "@angular/forms": "~9.1.10", "@angular/platform-browser": "~9.1.10", "@angular/platform-browser-dynamic": "~9.1.10", "@angular/router": "~9.1.10",
El módulo
ui.frontend
es una aplicación Angular generada mediante la herramienta Angular CLI que incluye enrutamiento. -
También hay tres dependencias con el prefijo
@adobe
:"@adobe/cq-angular-editable-components": "^2.0.2", "@adobe/cq-spa-component-mapping": "^1.0.3", "@adobe/cq-spa-page-model-manager": "^1.1.3",
Los módulos anteriores conforman AEM SPA Editor JS SDK y proporcionan la funcionalidad para que sea posible asignar componentes SPA a componentes AEM.
-
En el archivo
package.json
se han definido variosscripts
:"scripts": { "start": "ng serve --open --proxy-config ./proxy.conf.json", "build": "ng lint && ng build && clientlib", "build:production": "ng lint && ng build --prod && clientlib", "test": "ng test", "sync": "aemsync -d -w ../ui.apps/src/main/content" }
Estos scripts se basan en comandos CLI de Angular comunes, pero se han modificado ligeramente para que funcionen con el proyecto AEM más grande.
start
: ejecuta la aplicación de Angular localmente mediante un servidor web local. Se ha actualizado para representar el contenido de la instancia local de AEM.build
: compila la aplicación de Angular para la distribución de producción. La adición de&& clientlib
es responsable de copiar el SPA compilado en el móduloui.apps
como una biblioteca del lado del cliente durante una compilación. El módulo npm aem-clientlib-generator se usa para facilitar esto.Encontrará más detalles sobre los scripts disponibles aquí.
-
Inspeccione el archivo
ui.frontend/clientlib.config.js
. aem-clientlib-generator utiliza este archivo de configuración para determinar cómo generar la biblioteca de cliente. -
Inspeccione el archivo
ui.frontend/pom.xml
. Este archivo transforma la carpetaui.frontend
en un módulo Maven. El archivopom.xml
se ha actualizado para usar frontend-maven-plugin para probar y compilar el SPA durante una compilación de Maven. -
Inspeccione el archivo
app.component.ts
enui.frontend/src/app/app.component.ts
:import { Constants } from '@adobe/cq-angular-editable-components'; import { ModelManager } from '@adobe/cq-spa-page-model-manager'; import { Component } from '@angular/core'; @Component({ selector: '#spa-root', // tslint:disable-line styleUrls: ['./app.component.css'], templateUrl: './app.component.html' }) export class AppComponent { ... constructor() { ModelManager.initialize().then(this.updateData); } private updateData = pageModel => { this.path = pageModel[Constants.PATH_PROP]; this.items = pageModel[Constants.ITEMS_PROP]; this.itemsOrder = pageModel[Constants.ITEMS_ORDER_PROP]; } }
app.component.js
es el punto de entrada de la SPA.ModelManager
lo proporciona AEM SPA Editor JS SDK. Es responsable de llamar apageModel
(el contenido JSON) y de inyectarlo en la aplicación.
Añadir un componente de encabezado
A continuación, añada un nuevo componente a la SPA e implemente los cambios en una instancia local de AEM para ver la integración.
-
Abra una nueva ventana de terminal y vaya a la carpeta
ui.frontend
:$ cd aem-guides-wknd-spa/ui.frontend
-
Instale Angular CLI globalmente. Se usa para generar componentes de Angular, así como para generar y ofrecer la aplicación de Angular mediante el comando ng.
$ npm install -g @angular/cli
CAUTION
La versión de @angular/cli que usa este proyecto es 9.1.7. Se recomienda mantener las versiones de CLI de Angular sincronizadas. -
Cree un nuevo componente
Header
ejecutando el comandong generate component
de Angular CLI desde la carpetaui.frontend
.$ ng generate component components/header CREATE src/app/components/header/header.component.css (0 bytes) CREATE src/app/components/header/header.component.html (21 bytes) CREATE src/app/components/header/header.component.spec.ts (628 bytes) CREATE src/app/components/header/header.component.ts (269 bytes) UPDATE src/app/app.module.ts (1809 bytes)
Se creará un esqueleto para el nuevo componente Encabezado de Angular en
ui.frontend/src/app/components/header
. -
Abra el proyecto
aem-guides-wknd-spa
en el IDE que desee. Navegue hasta la carpetaui.frontend/src/app/components/header
. -
Abra el archivo
header.component.html
y reemplace el contenido por lo siguiente:<!--/* header.component.html */--> <header className="header"> <div className="header-container"> <h1>WKND</h1> </div> </header>
Tenga en cuenta que muestra contenido estático, por lo que este componente de Angular no requiere ningún ajuste en el
header.component.ts
generado de forma predeterminada. -
Abra el archivo app.component.html en
ui.frontend/src/app/app.component.html
. Agregarapp-header
:<app-header></app-header> <router-outlet></router-outlet>
Esto incluirá el componente
header
sobre todo el contenido de la página. -
Abra un nuevo terminal, vaya a la carpeta
ui.frontend
y ejecute el comandonpm run build
:$ cd ui.frontend $ npm run build Linting "angular-app"... All files pass linting. Generating ES5 bundles for differential loading... ES5 bundle generation complete.
-
Navegue hasta la carpeta
ui.apps
. Debajo deui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-angular
debería ver que los archivos SPA compilados se han copiado de la carpetaui.frontend/build
. -
Vuelva al terminal y navegue hasta la carpeta
ui.apps
. Ejecute el siguiente comando Maven:$ cd ../ui.apps $ mvn clean install -PautoInstallPackage ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 9.629 s [INFO] Finished at: 2020-05-04T17:48:07-07:00 [INFO] ------------------------------------------------------------------------
Esto implementará el paquete
ui.apps
en una instancia local de AEM en ejecución. -
Abra una ficha del explorador y vaya a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html. Ahora debería ver el contenido del componente
Header
en la SPA.
Los pasos 7-9 se ejecutan automáticamente al activar una compilación de Maven desde la raíz del proyecto (por ejemplo, mvn clean install -PautoInstallSinglePackage
). Ahora debe comprender los conceptos básicos de la integración entre la SPA y las bibliotecas del lado del cliente de AEM. Observe que todavía puede editar y agregar Text
componentes en AEM, pero el componente Header
no se puede editar.
Servidor de desarrollo de Webpack: proxy de la API de JSON
Como se ha visto en los ejercicios anteriores, realizar una compilación y sincronizar la biblioteca de cliente con una instancia local de AEM lleva unos minutos. Esto es aceptable para las pruebas finales, pero no es ideal para la mayoría del desarrollo de la SPA.
Se puede usar un servidor de desarrollo de Webpack para desarrollar rápidamente el SPA. La SPA está impulsada por un modelo JSON generado por AEM. En este ejercicio, el contenido JSON de una instancia en ejecución de AEM se procesa como proxy en el servidor de desarrollo configurado por el proyecto de Angular.
-
Vuelva al IDE y abra el archivo proxy.conf.json en
ui.frontend/proxy.conf.json
.[ { "context": [ "/content/**/*.(jpg|jpeg|png|model.json)", "/etc.clientlibs/**/*" ], "target": "http://localhost:4502", "auth": "admin:admin", "logLevel": "debug" } ]
La aplicación de Angular proporciona un mecanismo fácil para las solicitudes de API de proxy. Los patrones especificados en
context
se procesarán como proxy a través delocalhost:4502
, el inicio rápido local de AEM. -
Abra el archivo index.html en
ui.frontend/src/index.html
. Este es el archivo raíz de HTML que utiliza el servidor de desarrollo.Observe que hay una entrada para
base href="/"
. La etiqueta base es crítica para que la aplicación resuelva direcciones URL relativas.<base href="/">
-
Abra una ventana de terminal y vaya a la carpeta
ui.frontend
. Ejecute el comandonpm start
:$ cd ui.frontend $ npm start > wknd-spa-angular@0.1.0 start /Users/dgordon/Documents/code/aem-guides-wknd-spa/ui.frontend > ng serve --open --proxy-config ./proxy.conf.json 10% building 3/3 modules 0 active[HPM] Proxy created: [ '/content/**/*.(jpg|jpeg|png|model.json)', '/etc.clientlibs/**/*' ] -> http://localhost:4502 [HPM] Subscribed to http-proxy events: [ 'error', 'close' ] ℹ 「wds」: Project is running at http://localhost:4200/webpack-dev-server/ ℹ 「wds」: webpack output is served from / ℹ 「wds」: 404s will fallback to //index.html
-
Abra una nueva ficha de explorador (si no está abierta) y vaya a http://localhost:4200/content/wknd-spa-angular/us/en/home.html.
Debería ver el mismo contenido que en AEM, pero sin ninguna de las funcionalidades de creación habilitadas.
-
Vuelva al IDE y cree una nueva carpeta denominada
img
enui.frontend/src/assets
. -
Descargue y agregue el siguiente logotipo WKND a la carpeta
img
: -
Abra header.component.html en
ui.frontend/src/app/components/header/header.component.html
e incluya el logotipo:<header class="header"> <div class="header-container"> <div class="logo"> <img class="logo-img" src="assets/img/wknd-logo-dk.png" alt="WKND SPA" /> </div> </div> </header>
Guarde los cambios en header.component.html.
-
Vuelva al explorador. Debería ver reflejados inmediatamente los cambios en la aplicación.
Puede seguir haciendo actualizaciones de contenido en AEM y verlas reflejadas en el servidor de desarrollo de Webpack, ya que el contenido se transfiere por proxy. Tenga en cuenta que los cambios de contenido solo son visibles en el servidor de desarrollo de Webpack.
-
Detenga el servidor web local con
ctrl+c
en el terminal.
Servidor de desarrollo de Webpack: simulación de API de JSON
Otro enfoque para el desarrollo rápido es utilizar un archivo JSON estático para actuar como modelo JSON. Al "burlarse" del JSON, eliminamos la dependencia de una instancia local de AEM. También permite a un desarrollador front-end actualizar el modelo JSON para probar la funcionalidad y dirigir cambios en la API JSON que luego implementaría un desarrollador back-end.
La configuración inicial del JSON ficticio requiere una instancia de AEM local.
-
En el explorador, vaya a http://localhost:4502/content/wknd-spa-angular/us/en.model.json.
Este es el JSON exportado por AEM que administra la aplicación. Copie la salida JSON.
-
Vuelva al IDE y vaya a
ui.frontend/src
y agregue las nuevas carpetas denominadas mocks y json para que coincidan con la siguiente estructura de carpetas:|-- ui.frontend |-- src |-- mocks |-- json
-
Cree un nuevo archivo llamado en.model.json debajo de
ui.frontend/public/mocks/json
. Pegue aquí la salida JSON del Paso 1. -
Cree un nuevo archivo proxy.mock.conf.json debajo de
ui.frontend
. Rellene el archivo con lo siguiente:[ { "context": [ "/content/**/*.model.json" ], "pathRewrite": { "^/content/wknd-spa-angular/us" : "/mocks/json"} , "target": "http://localhost:4200", "logLevel": "debug" } ]
Esta configuración proxy reescribirá las solicitudes que comiencen por
/content/wknd-spa-angular/us
con/mocks/json
y sirvan al archivo JSON estático correspondiente, por ejemplo:/content/wknd-spa-angular/us/en.model.json -> /mocks/json/en.model.json
-
Abra el archivo angular.json. Agregue una nueva configuración de dev con una matriz de assets actualizada para hacer referencia a la carpeta mocks creada.
"dev": { "assets": [ "src/mocks", "src/assets", "src/favicon.ico", "src/logo192.png", "src/logo512.png", "src/manifest.json" ] },
Crear una configuración dev dedicada garantiza que la carpeta mocks solo se use durante el desarrollo y nunca se implemente en AEM en una compilación de producción.
-
En el archivo angular.json, actualice la configuración de browserTarget para usar la nueva configuración de dev:
... "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { + "browserTarget": "angular-app:build:dev" - "browserTarget": "angular-app:build" }, ...
-
Abra el archivo
ui.frontend/package.json
y agregue un nuevo comando start:mock para hacer referencia al archivo proxy.mock.conf.json."scripts": { "start": "ng serve --open --proxy-config ./proxy.conf.json", + "start:mock": "ng serve --open --proxy-config ./proxy.mock.conf.json", "build": "ng lint && ng build && clientlib", "build:production": "ng lint && ng build --prod && clientlib", "test": "ng test", "sync": "aemsync -d -w ../ui.apps/src/main/content" }
Añadir un nuevo comando facilita el cambio entre las configuraciones de proxy.
-
Si se está ejecutando, detenga el servidor de desarrollo de Webpack. Inicie el servidor de desarrollo webpack con el script start:mock:
$ npm run start:mock > wknd-spa-angular@0.1.0 start:mock /Users/dgordon/Documents/code/aem-guides-wknd-spa/ui.frontend > ng serve --open --proxy-config ./proxy.mock.conf.json
Vaya a http://localhost:4200/content/wknd-spa-angular/us/en/home.html y debería ver el mismo SPA, pero el contenido se está extrayendo del archivo JSON mock.
-
Realice un pequeño cambio en el archivo en.model.json creado anteriormente. El contenido actualizado debe reflejarse inmediatamente en el servidor de desarrollo de Webpack.
Poder manipular el modelo JSON y ver los efectos en un SPA activo puede ayudar a un desarrollador a comprender la API del modelo JSON. También permite que el desarrollo del front-end y del back-end se produzca en paralelo.
Agregar estilos con Sass
A continuación, se añaden al proyecto algunos estilos actualizados. Este proyecto agregará compatibilidad con Sass para algunas características útiles como las variables.
-
Abra una ventana de terminal y detenga webpack dev server si se inició. Desde la carpeta
ui.frontend
, escriba el siguiente comando para actualizar la aplicación de Angular y procesar los archivos .scss.$ cd ui.frontend $ ng config schematics.@schematics/angular:component.styleext scss
Esto actualizará el archivo
angular.json
con una nueva entrada en la parte inferior del archivo:"schematics": { "@schematics/angular:component": { "styleext": "scss" } }
-
Instale
normalize-scss
para normalizar los estilos en todos los exploradores:$ npm install normalize-scss --save
-
Vuelva al IDE y, debajo de
ui.frontend/src
, cree una nueva carpeta denominadastyles
. -
Cree un nuevo archivo debajo de
ui.frontend/src/styles
con el nombre_variables.scss
y rellénelo con las siguientes variables://_variables.scss //== Colors // //## Gray and brand colors for use across theme. $black: #202020; $gray: #696969; $gray-light: #EBEBEB; $gray-lighter: #F7F7F7; $white: #FFFFFF; $yellow: #FFEA00; $blue: #0045FF; //== Typography // //## Font, line-height, and color for body text, headings, and more. $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif; $font-family-serif: Georgia, "Times New Roman", Times, serif; $font-family-base: $font-family-sans-serif; $font-size-base: 18px; $line-height-base: 1.5; $line-height-computed: floor(($font-size-base * $line-height-base)); // Functional Colors $brand-primary: $yellow; $body-bg: $white; $text-color: $black; $text-color-inverse: $gray-light; $link-color: $blue; //Layout $max-width: 1024px; $header-height: 75px; // Spacing $gutter-padding: 12px;
-
Cambie el nombre de la extensión del archivo styles.css en
ui.frontend/src/styles.css
a styles.scss. Reemplace el contenido por lo siguiente:/* styles.scss * / /* Normalize */ @import '~normalize-scss/sass/normalize'; @import './styles/variables'; body { background-color: $body-bg; font-family: $font-family-base; margin: 0; padding: 0; font-size: $font-size-base; text-align: left; color: $text-color; line-height: $line-height-base; } body.page { max-width: $max-width; margin: 0 auto; padding: $gutter-padding; padding-top: $header-height; }
-
Actualice angular.json y cambie el nombre de todas las referencias a style.css con styles.scss. Debe haber 3 referencias.
"styles": [ - "src/styles.css" + "src/styles.scss" ],
Actualizar estilos de encabezado
A continuación, agregue algunos estilos específicos de marca al componente Header mediante Sass.
-
Inicie webpack dev server para ver cómo se actualizan los estilos en tiempo real:
$ npm run start:mock
-
En
ui.frontend/src/app/components/header
, cambie el nombre de header.component.css a header.component.scss. Rellene el archivo con lo siguiente:@import "~src/styles/variables"; .header { width: 100%; position: fixed; top: 0; left:0; z-index: 99; background-color: $brand-primary; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.24); } .header-container { display: flex; max-width: $max-width; margin: 0 auto; padding-left: $gutter-padding; padding-right: $gutter-padding; } .logo { z-index: 100; display: flex; padding-top: $gutter-padding; padding-bottom: $gutter-padding; } .logo-img { width: 100px; }
-
Actualizar header.component.ts para hacer referencia a header.component.scss:
... @Component({ selector: 'app-header', templateUrl: './header.component.html', - styleUrls: ['./header.component.css'] + styleUrls: ['./header.component.scss'] }) ...
-
Vuelva al explorador y al servidor de desarrollo de Webpack:
Ahora debería ver los estilos actualizados agregados al componente Header.
Implementación de actualizaciones de SPA en AEM
Actualmente, los cambios realizados en Header solo son visibles a través del servidor de desarrollo de Webpack. Implemente el SPA actualizado en AEM para ver los cambios.
-
Detenga el servidor de desarrollo de Webpack.
-
Vaya a la raíz del proyecto
/aem-guides-wknd-spa
e implemente el proyecto en AEM mediante Maven:$ cd .. $ mvn clean install -PautoInstallSinglePackage
-
Vaya a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html. Debería ver el encabezado actualizado con el logotipo y los estilos aplicados:
Ahora que el SPA actualizado está en AEM, la creación puede continuar.
Enhorabuena.
¡Felicidades, ha actualizado el SPA y ha explorado la integración con AEM! Ahora conoce dos enfoques diferentes para desarrollar la SPA con la API del modelo JSON de AEM mediante un servidor de desarrollo de Webpack.
Siempre puede ver el código terminado en GitHub o desprotegerlo localmente cambiando a la rama Angular/integrate-spa-solution
.
Siguientes pasos
Asignar componentes de SPA a componentes de AEM: aprenda a asignar componentes de Angular a componentes de Adobe Experience Manager (AEM) con AEM SPA Editor JS SDK. La asignación de componentes permite a los autores realizar actualizaciones dinámicas de los componentes de la SPA en el Editor de SPA de AEM, de forma similar a la creación tradicional de AEM.