Comprender cómo se puede integrar el código fuente de una aplicación de una sola página (SPA) escrita en Angular con 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 el SPA con la API del modelo JSON de AEM.
Este capítulo agregará una Header
al SPA. En el proceso de creación de esta estática Header
componente se utilizan varios enfoques para AEM el desarrollo de SPA.
El SPA se amplía para agregar un Header
componente
Revise las herramientas e instrucciones necesarias para configurar un entorno de desarrollo local.
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 de AEM local mediante Maven:
$ mvn clean install -PautoInstallSinglePackage
Si usa AEM 6.x añada la variable classic
perfil:
$ mvn clean install -PautoInstallSinglePackage -Pclassic
Siempre puede ver el código terminado en GitHub o desproteja el código localmente cambiando a la rama Angular/integrate-spa-solution
.
Se crearon dos módulos como parte del proyecto AEM: ui.apps
y ui.frontend
.
La variable ui.frontend
es un webpack proyecto que contiene todo el código fuente de SPA. La mayoría de las pruebas y el desarrollo de SPA se realizan en el proyecto de webpack. Cuando se activa una compilación de producción, la SPA se crea y se compila mediante un webpack. Los artefactos compilados (CSS y Javascript) se copian en la variable ui.apps
que luego se implementa en el tiempo de ejecución de AEM.
Descripción general de la integración de SPA.
La información adicional sobre la compilación del front-end puede ser se encuentra aquí.
A continuación, revise la ui.frontend
para comprender el SPA que el AEM tipo de archivo del proyecto.
En el IDE de su elección, abra el proyecto AEM para el SPA WKND. Este tutorial utilizará la variable Código IDE de Visual Studio.
Expanda e inspeccione la variable ui.frontend
carpeta. Abra el archivo ui.frontend/package.json
En el dependencies
debería ver varias relacionadas 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",
La variable ui.frontend
es un aplicación de angular generado mediante el uso de la variable Herramienta CLI de angular que incluye el 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 forman el AEM SDK de JS Editor SPA y proporcionar la funcionalidad para que sea posible asignar SPA componentes a AEM componentes.
En el package.json
file several scripts
están definidas:
"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"
}
Estas secuencias de comandos se basan en Comandos CLI de angular pero se han modificado ligeramente para trabajar con el proyecto de 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 de AEM local.
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 ui.apps
como biblioteca del lado del cliente durante una compilación. El módulo npm aem-clientlib-generator se utiliza para facilitar este proceso.
Se pueden encontrar más detalles sobre los scripts disponibles here.
Inspect el archivo ui.frontend/clientlib.config.js
. Este archivo de configuración lo utiliza aem-clientlib-generator para determinar cómo generar la biblioteca de cliente.
Inspect el archivo ui.frontend/pom.xml
. Este archivo transforma el ui.frontend
carpeta en un Módulo Maven. La variable pom.xml
se ha actualizado para usar la variable frontend-maven-plugin a prueba y versión el SPA durante una compilación de Maven.
Inspect el archivo app.component.ts
at ui.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 del SPA. ModelManager
es proporcionado por AEM SPA Editor JS SDK. Es responsable de llamar e inyectar el pageModel
(el contenido JSON) en la aplicación.
A continuación, agregue un componente nuevo a la SPA e implemente los cambios en una instancia de AEM local para ver la integración.
Abra una nueva ventana de terminal y vaya a la ui.frontend
carpeta:
$ cd aem-guides-wknd-spa/ui.frontend
Instalar CLI de angular globalmente Se utiliza para generar componentes de Angular, así como para crear y servir la aplicación de Angular a través de la variable ng comando.
$ npm install -g @angular/cli
La versión de @angular/cli utilizado por este proyecto es 9.1.7. Se recomienda mantener las versiones de CLI de Angular sincronizadas.
Cree una nueva Header
al ejecutar la CLI de Angular ng generate component
desde el ui.frontend
carpeta.
$ 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)
Esto creará un esqueleto para el nuevo componente Encabezado de Angular en ui.frontend/src/app/components/header
.
Abra el aem-guides-wknd-spa
en el IDE que elija. Vaya a la ui.frontend/src/app/components/header
carpeta.
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 esto muestra contenido estático, por lo que este componente de Angular no requiere ningún ajuste en la generación predeterminada header.component.ts
.
Abra el archivo . app.component.html at ui.frontend/src/app/app.component.html
. Agregue la variable app-header
:
<app-header></app-header>
<router-outlet></router-outlet>
Esto incluirá la variable header
sobre todo el contenido de la página.
Abra un terminal nuevo y vaya a la ui.frontend
y ejecute el npm run build
comando:
$ cd ui.frontend
$ npm run build
Linting "angular-app"...
All files pass linting.
Generating ES5 bundles for differential loading...
ES5 bundle generation complete.
Vaya a la ui.apps
carpeta. Bajo ui.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 variableui.frontend/build
carpeta.
Vuelva al terminal y navegue hasta el ui.apps
carpeta. 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á la variable ui.apps
a una instancia local en ejecución de AEM.
Abra una pestaña 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 Header
componente que se muestra en el SPA.
Pasos 7-9 se ejecutan automáticamente al activar una compilación de Maven desde la raíz del proyecto (p. ej. mvn clean install -PautoInstallSinglePackage
). Ahora debe comprender los conceptos básicos de la integración entre las bibliotecas de SPA y AEM del lado del cliente. Observe que aún puede editar y agregar Text
componentes en AEM, sin embargo, la variable Header
no es editable.
Como se ha visto en ejercicios anteriores, realizar una compilación y sincronizar la biblioteca del cliente con una instancia local de AEM tarda unos minutos. Esto es aceptable para las pruebas finales, pero no es ideal para la mayoría del desarrollo de SPA.
A servidor de desarrollo de webpack puede utilizarse para desarrollar rápidamente el SPA. El SPA está impulsado por un modelo JSON generado por AEM. En este ejercicio, el contenido JSON de una instancia de AEM en ejecución es proxy en el servidor de desarrollo configurado por el proyecto de angular.
Vuelva al IDE y abra el archivo proxy.conf.json at ui.frontend/proxy.conf.json
.
[
{
"context": [
"/content/**/*.(jpg|jpeg|png|model.json)",
"/etc.clientlibs/**/*"
],
"target": "http://localhost:4502",
"auth": "admin:admin",
"logLevel": "debug"
}
]
La variable aplicación de angular proporciona un mecanismo fácil para las solicitudes de API proxy. Los patrones especificados en context
se procesan mediante proxy localhost:4502
, el inicio rápido AEM local.
Abra el archivo . index.html at ui.frontend/src/index.html
. Este es el archivo HTML raíz que utiliza el servidor de desarrollo.
Tenga en cuenta que hay una entrada para base href="/"
. La variable etiqueta base es fundamental para que la aplicación resuelva las direcciones URL relativas.
<base href="/">
Abra una ventana de terminal y vaya a la ui.frontend
carpeta. Ejecutar el comando npm 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 pestaña del explorador (si aún 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 capacidades de creación habilitadas.
Vuelva al IDE y cree una nueva carpeta denominada img
at ui.frontend/src/assets
.
Descargue y añada el siguiente logotipo WKND al img
carpeta:
Apertura header.component.html at 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 inmediatamente los cambios realizados en la aplicación.
Puede seguir actualizando el contenido en AEM y veas reflejadas en servidor de desarrollo de webpack, ya que estamos proxizando el contenido. Tenga en cuenta que los cambios de contenido solo son visibles en la variable servidor de desarrollo de webpack.
Detenga el servidor web local con ctrl+c
en el terminal.
Otro enfoque para el desarrollo rápido es utilizar un archivo JSON estático para actuar como el modelo JSON. Al "burlarse" del JSON, eliminamos la dependencia de una instancia de AEM local. También permite a un desarrollador front-end actualizar el modelo JSON para probar la funcionalidad y dirigir los cambios a la API JSON que luego sería implementada por un desarrollador back-end.
La configuración inicial del JSON de prueba hace requerir una instancia de AEM local.
En el navegador, 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 para navegar ui.frontend/src
y añada nuevas carpetas denominadas mocks y json para que coincida con la siguiente estructura de carpetas:
|-- ui.frontend
|-- src
|-- mocks
|-- json
Cree un nuevo archivo con el nombre en.model.json below ui.frontend/public/mocks/json
. Pegar la salida JSON desde Paso 1 aquí.
Crear un nuevo archivo proxy.mock.conf.json below 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 de proxy reescribirá las solicitudes que comiencen por /content/wknd-spa-angular/us
con /mocks/json
y sirven el 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. Agregar una nueva dev configuración con una activos para hacer referencia a la matriz mocks carpeta creada.
"dev": {
"assets": [
"src/mocks",
"src/assets",
"src/favicon.ico",
"src/logo192.png",
"src/logo512.png",
"src/manifest.json"
]
},
Creación de una dev garantiza que la variable mocks solo se utiliza durante el desarrollo y nunca se implementa para AEM en una compilación de producción.
En el angular.json , actualice el browserTarget para usar la nueva dev configuración:
...
"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 start:mock para hacer referencia a la variable proxy.mock.conf.json archivo.
"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 la alternancia entre las configuraciones de proxy.
Si se está ejecutando, detenga la variable servidor de desarrollo de webpack. Inicie el servidor de desarrollo de webpack usando la variable start:mock script:
$ 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 ahora se está extrayendo del mock Archivo JSON.
Realice un pequeño cambio en la variable en.model.json archivo creado anteriormente. El contenido actualizado debe reflejarse inmediatamente en la variable 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 el desarrollo del front-end y del back-end en paralelo.
A continuación, se añaden al proyecto algunos estilos actualizados. Este proyecto agregará Sass compatibilidad con algunas funciones útiles como las variables.
Abra una ventana de terminal y detenga el servidor de desarrollo de webpack si se ha iniciado. Desde dentro de la variable ui.frontend
carpeta introduzca el siguiente comando para actualizar la aplicación de Angular que desea procesar .scs archivos.
$ cd ui.frontend
$ ng config schematics.@schematics/angular:component.styleext scss
Esto actualizará la variable angular.json
con una nueva entrada en la parte inferior del archivo:
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
}
Instalar normalize-scss
para normalizar los estilos en los navegadores:
$ npm install normalize-scss --save
Vuelva al IDE y debajo de ui.frontend/src
crear una nueva carpeta con el nombre styles
.
Cree un nuevo archivo debajo de ui.frontend/src/styles
named _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 estilos.css at ui.frontend/src/styles.css
a estilos.scss. Sustituya el contenido por el 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;
}
Actualizar angular.json y cambie el nombre de todas las referencias a style.css con estilos.scss. Debería haber 3 referencias.
"styles": [
- "src/styles.css"
+ "src/styles.scss"
],
A continuación, agregue algunos estilos específicos de la marca al Encabezado utilizando Sass.
Inicie el servidor de desarrollo de webpack para ver cómo se actualizan los estilos en tiempo real:
$ npm run start:mock
En ui.frontend/src/app/components/header
volver a nombrar 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 referencia header.component.scss:
...
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
- styleUrls: ['./header.component.css']
+ styleUrls: ['./header.component.scss']
})
...
Vuelva al explorador y a la servidor de desarrollo de webpack:
Ahora debería ver los estilos actualizados añadidos al Encabezado componente.
Los cambios realizados en la variable Encabezado actualmente solo son visibles a través de la variable 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 para AEM con Maven:
$ cd ..
$ mvn clean install -PautoInstallSinglePackage
Vaya a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html. Debería ver la Encabezado con logotipo y estilos aplicados:
Ahora que la SPA actualizada está en AEM, la creación puede continuar.
Felicidades, ha actualizado la SPA y 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 desproteja el código localmente cambiando a la rama Angular/integrate-spa-solution
.
Asignación de componentes de SPA a componentes de AEM : Aprenda a asignar componentes de Angular a componentes de Adobe Experience Manager (AEM) con el SDK de JS de AEM Editor SPA. La asignación de componentes permite a los autores realizar actualizaciones dinámicas de los componentes de SPA dentro del AEM SPA Editor, de forma similar a la creación de AEM tradicional.