Integrate a SPA integrate-spa
- Editor universale per la modifica visiva di contenuti headless.
- Editor frammenti di contenuto per la modifica di contenuti headless basata su modulo.
Scopri come il codice sorgente di un’applicazione a pagina singola scritto in Angular può essere integrato con un progetto Adobe Experience Manager (AEM). Learn to use modern front-end tools, like a webpack dev server, to rapidly develop the SPA against the AEM JSON model API.
Obiettivo
- Understand how the SPA project is integrated with AEM with client-side libraries.
- Learn how to use a local development server for dedicated front-end development.
- Explore the use of a proxy and static mock file for developing against the AEM JSON model API
Cosa verrà creato
This chapter will add a simple Header component to the SPA. In the process of building out this static Header component several approaches to AEM SPA development are used.
The SPA is extended to add a static Header component
Prerequisiti
Rivedi gli strumenti e le istruzioni necessari per configurare un ambiente di sviluppo locale.
Ottieni il codice
-
Scarica il punto di partenza per questa esercitazione tramite Git:
code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-spa.git $ cd aem-guides-wknd-spa $ git checkout Angular/integrate-spa-start -
Implementa la base di codice in un’istanza AEM locale utilizzando Maven:
code language-shell $ mvn clean install -PautoInstallSinglePackageSe utilizzi AEM 6.x, aggiungi il profilo
classic:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
You can always view the finished code on GitHub or check the code out locally by switching to the branch Angular/integrate-spa-solution.
Integration approach integration-approach
Two modules were created as part of the AEM project: ui.apps and ui.frontend.
The ui.frontend module is a webpack project that contains all of the SPA source code. A majority of the SPA development and testing is done in the webpack project. When a production build is triggered, the SPA is built and compiled using webpack. The compiled artifacts (CSS and Javascript) are copied into the ui.apps module which is then deployed to the AEM runtime.
A high-level depiction of the SPA integration.
Additional information about the Front-end build can be found here.
Inspect the SPA integration inspect-spa-integration
Esaminare quindi il modulo ui.frontend per comprendere l'applicazione a pagina singola generata automaticamente dall'archetipo progetto AEM.
-
Nell’IDE che preferisci, apri il progetto AEM per l’applicazione a pagina singola WKND. Questa esercitazione utilizzerà l'IDE codice di Visual Studio.
-
Espandere ed esaminare la cartella
ui.frontend. Apri il file inui.frontend/package.json -
Sotto
dependenciesdovresti vedere diversi relativi a@angular:code language-json "@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",Il modulo
ui.frontendè un'applicazione Angular generata utilizzando lo strumento Angular CLI che include il routing. -
Ci sono anche tre dipendenze con prefisso
@adobe:code language-json "@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",I moduli di cui sopra costituiscono AEM SPA Editor JS SDK e forniscono la funzionalità che consente di mappare i componenti SPA ai componenti AEM.
-
Nel file
package.jsonsono definiti diversiscripts:code language-json "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" }Questi script si basano su comandi CLI di Angular comuni, ma sono stati leggermente modificati per funzionare con il progetto AEM più grande.
start- esegue l'app Angular localmente utilizzando un server Web locale. È stato aggiornato per fungere da proxy del contenuto dell’istanza AEM locale.build- compila l'app Angular per la distribuzione di produzione. L'aggiunta di&& clientlibè responsabile della copia dell'applicazione a pagina singola compilata nel moduloui.appscome libreria lato client durante una compilazione. Per facilitare questa operazione, viene utilizzato il modulo npm aem-clientlib-generator.Ulteriori dettagli sugli script disponibili sono disponibili qui.
-
Esamina il file
ui.frontend/clientlib.config.js. Questo file di configurazione viene utilizzato da aem-clientlib-generator per determinare come generare la libreria client. -
Esamina il file
ui.frontend/pom.xml. Questo file trasforma la cartellaui.frontendin un modulo Maven. Il filepom.xmlè stato aggiornato per utilizzare frontend-maven-plugin per test e build l'applicazione a pagina singola durante una compilazione Maven. -
Esaminare il file
app.component.tsinui.frontend/src/app/app.component.ts:code language-js 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è il punto di ingresso dell'applicazione a pagina singola.ModelManagerè fornito da AEM SPA Editor JS SDK. È responsabile della chiamata e dell'inserimento dipageModel(contenuto JSON) nell'applicazione.
Aggiungere un componente Intestazione header-component
Quindi, aggiungi un nuovo componente all’applicazione a pagina singola e implementa le modifiche in un’istanza AEM locale per visualizzare l’integrazione.
-
Aprire una nuova finestra del terminale e passare alla cartella
ui.frontend:code language-shell $ cd aem-guides-wknd-spa/ui.frontend -
Installa Angular CLI a livello globale Utilizzato per generare componenti Angular e per generare e gestire l'applicazione Angular tramite il comando ng.
code language-shell $ npm install -g @angular/clinote caution CAUTION La versione di @angular/cli utilizzata dal progetto è 9.1.7. Si consiglia di mantenere sincronizzate le versioni di Angular CLI. -
Creare un nuovo componente
Headereseguendo il comando Angular CLIng generate componentdalla cartellaui.frontend.code language-shell $ 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)Verrà creata un'ossatura per il nuovo componente Angular Header in
ui.frontend/src/app/components/header. -
Aprire il progetto
aem-guides-wknd-spanell'IDE desiderato. Passare alla cartellaui.frontend/src/app/components/header.
-
Aprire il file
header.component.htmle sostituire il contenuto con quanto segue:code language-html <!--/* header.component.html */--> <header className="header"> <div className="header-container"> <h1>WKND</h1> </div> </header>In questo modo viene visualizzato il contenuto statico, pertanto questo componente Angular non richiede alcuna modifica al valore predefinito generato
header.component.ts. -
Apri il file app.component.html in
ui.frontend/src/app/app.component.html. Aggiungiapp-header:code language-html <app-header></app-header> <router-outlet></router-outlet>Questo includerà il componente
headerprima di tutto il contenuto della pagina. -
Aprire un nuovo terminale, passare alla cartella
ui.frontended eseguire il comandonpm run build:code language-shell $ cd ui.frontend $ npm run build Linting "angular-app"... All files pass linting. Generating ES5 bundles for differential loading... ES5 bundle generation complete. -
Passare alla cartella
ui.apps. Sottoui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-angulardovresti vedere che i file SPA compilati sono stati copiati dalla cartellaui.frontend/build.
-
Tornare al terminale e spostarsi nella cartella
ui.apps. Esegui il seguente comando Maven:code language-shell $ 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] ------------------------------------------------------------------------Il pacchetto
ui.appsverrà distribuito a un'istanza in esecuzione locale di AEM. -
Apri una scheda del browser e passa a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html. Il contenuto del componente
Headerdovrebbe essere visualizzato nell'applicazione a pagina singola.
I passaggi 7-9 vengono eseguiti automaticamente quando si attiva una build Maven dalla radice del progetto (ovvero mvn clean install -PautoInstallSinglePackage). Ora dovresti comprendere le nozioni di base sull’integrazione tra le librerie lato client di applicazioni a pagina singola e AEM. È comunque possibile modificare e aggiungere Text componenti in AEM, tuttavia il componente Header non è modificabile.
Server di sviluppo Webpack: proxy dell’API JSON proxy-json
Come mostrato negli esercizi precedenti, l’esecuzione di una build e la sincronizzazione della libreria client con un’istanza locale di AEM richiedono alcuni minuti. Questo è accettabile per il test finale, ma non è ideale per la maggior parte dello sviluppo di applicazioni a pagina singola.
È possibile utilizzare un server di sviluppo webpack per sviluppare rapidamente l'applicazione a pagina singola. L’applicazione a pagina singola è guidata da un modello JSON generato da AEM. In questo esercizio il contenuto JSON di un'istanza in esecuzione di AEM è inviato tramite proxy al server di sviluppo configurato dal progetto Angular.
-
Torna all'IDE e apri il file proxy.conf.json in
ui.frontend/proxy.conf.json.code language-json [ { "context": [ "/content/**/*.(jpg|jpeg|png|model.json)", "/etc.clientlibs/**/*" ], "target": "http://localhost:4502", "auth": "admin:admin", "logLevel": "debug" } ]L'app Angular fornisce un semplice meccanismo per inoltrare le richieste API. I pattern specificati in
contextsono inviati tramite proxy tramitelocalhost:4502, l'avvio rapido locale di AEM. -
Apri il file index.html in
ui.frontend/src/index.html. Si tratta del file HTML radice utilizzato dal server di sviluppo.Si noti che è presente una voce per
base href="/". Il tag di base è fondamentale per la risoluzione degli URL relativi da parte dell'app.code language-html <base href="/"> -
Aprire una finestra del terminale e passare alla cartella
ui.frontend. Eseguire il comandonpm start:code language-shell $ 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 -
Apri una nuova scheda del browser (se non è già aperta) e passa a http://localhost:4200/content/wknd-spa-angular/us/en/home.html.
Dovresti visualizzare gli stessi contenuti di AEM, ma senza alcuna funzionalità di authoring abilitata.
-
Tornare all'IDE e creare una nuova cartella denominata
imginui.frontend/src/assets. -
Scaricare e aggiungere il logo WKND seguente alla cartella
img:
-
Apri header.component.html in
ui.frontend/src/app/components/header/header.component.htmle includi il logo:code language-html <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>Save the changes to header.component.html.
-
Return to the browser. You should immediately see the changes to the app reflected.
You can continue to make content updates in AEM and see them reflected in webpack dev server, since we are proxying the content. Note that the content changes are only visible in the webpack dev server.
-
Stop the local web server with
ctrl+cin the terminal.
Webpack Dev Server - Mock JSON API mock-json
Another approach to rapid development is to use a static JSON file to act as the JSON model. By "mocking" the JSON, we remove the dependency on a local AEM instance. It also allows a front-end developer to update the JSON model in order to test functionality and drive changes to the JSON API that would then be later implemented by a back-end developer.
The initial set up of the mock JSON does require a local AEM instance.
-
In the browser navigate to http://localhost:4502/content/wknd-spa-angular/us/en.model.json.
This is the JSON exported by AEM that is driving the application. Copy the JSON output.
-
Return to the IDE navigate to
ui.frontend/srcand add new folders named mocks and json to match the following folder structure:code language-plain |-- ui.frontend |-- src |-- mocks |-- json -
Create a new file named en.model.json beneath
ui.frontend/public/mocks/json. Paste the JSON output from Step 1 here.
-
Create a new file proxy.mock.conf.json beneath
ui.frontend. Populate the file with the following:code language-json [ { "context": [ "/content/**/*.model.json" ], "pathRewrite": { "^/content/wknd-spa-angular/us" : "/mocks/json"} , "target": "http://localhost:4200", "logLevel": "debug" } ]This proxy configuration will rewrite requests that start with
/content/wknd-spa-angular/uswith/mocks/jsonand serve the corresponding static JSON file, for example:code language-plain /content/wknd-spa-angular/us/en.model.json -> /mocks/json/en.model.json -
Open the file angular.json. Add a new dev configuration with an updated assets array to reference the mocks folder created.
code language-json "dev": { "assets": [ "src/mocks", "src/assets", "src/favicon.ico", "src/logo192.png", "src/logo512.png", "src/manifest.json" ] },
La creazione di una configurazione dev dedicata garantisce che la cartella mocks venga utilizzata solo durante lo sviluppo e non venga mai distribuita ad AEM in una build di produzione.
-
Nel file angular.json, aggiorna la configurazione browserTarget per utilizzare la nuova configurazione dev:
code language-diff ... "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { + "browserTarget": "angular-app:build:dev" - "browserTarget": "angular-app:build" }, ...
-
Apri il file
ui.frontend/package.jsone aggiungi un nuovo comando start:mock per fare riferimento al file proxy.mock.conf.json.code language-diff "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" }L’aggiunta di un nuovo comando consente di passare facilmente da una configurazione proxy all’altra.
-
Se è in esecuzione, arrestare il server di sviluppo webpack. Avvia il server di sviluppo webpack utilizzando lo script start:mock:
code language-shell $ 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.jsonPassa a http://localhost:4200/content/wknd-spa-angular/us/en/home.html per visualizzare la stessa applicazione a pagina singola, ma il contenuto viene ora estratto dal file JSON finto.
-
Apporta una piccola modifica al file en.model.json creato in precedenza. Il contenuto aggiornato deve essere immediatamente riflesso nel server di sviluppo Webpack.
La possibilità di manipolare il modello JSON e vedere gli effetti su un’applicazione a pagina singola live può aiutare uno sviluppatore a comprendere l’API del modello JSON. Consente inoltre lo sviluppo sia front-end che back-end in parallelo.
Aggiungi stili con Sass
Successivamente, al progetto viene aggiunto uno stile aggiornato. Questo progetto aggiungerà il supporto di Sass per alcune funzionalità utili come le variabili.
-
Aprire una finestra del terminale e arrestare il server di sviluppo webpack, se avviato. Dall'interno della cartella
ui.frontendimmettere il comando seguente per aggiornare l'app Angular per elaborare .scss file.code language-shell $ cd ui.frontend $ ng config schematics.@schematics/angular:component.styleext scssIl file
angular.jsonverrà aggiornato con una nuova voce nella parte inferiore del file:code language-json "schematics": { "@schematics/angular:component": { "styleext": "scss" } } -
Installa
normalize-scssper normalizzare gli stili nei vari browser:code language-shell $ npm install normalize-scss --save -
Tornare all'IDE e sotto
ui.frontend/srccreare una nuova cartella denominatastyles. -
Creare un nuovo file sotto
ui.frontend/src/stylesdenominato_variables.scsse popolarlo con le seguenti variabili:code language-scss //_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; -
Rinomina l'estensione del file styles.css in
ui.frontend/src/styles.cssin styles.scss. Sostituire il contenuto con quanto segue:code language-scss /* 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; } -
Aggiorna angular.json e rinomina tutti i riferimenti a style.css con styles.scss. Dovrebbero essere presenti 3 riferimenti.
code language-diff "styles": [ - "src/styles.css" + "src/styles.scss" ],
Aggiorna stili intestazione
Aggiungi quindi alcuni stili specifici del brand al componente Intestazione utilizzando Sass.
-
Avvia il server di sviluppo webpack per visualizzare gli stili aggiornati in tempo reale:
code language-shell $ npm run start:mock -
In
ui.frontend/src/app/components/headerrinominare header.component.css in header.component.scss. Compila il file con quanto segue:code language-scss @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; } -
Aggiorna header.component.ts per fare riferimento a header.component.scss:
code language-diff ... @Component({ selector: 'app-header', templateUrl: './header.component.html', - styleUrls: ['./header.component.css'] + styleUrls: ['./header.component.scss'] }) ... -
Torna al browser e al server di sviluppo webpack:
Gli stili aggiornati dovrebbero essere aggiunti al componente Intestazione.
Distribuire aggiornamenti SPA in AEM
Le modifiche apportate all'Intestazione sono attualmente visibili solo tramite il server di sviluppo Webpack. Distribuisci l’applicazione a pagina singola aggiornata in AEM per visualizzare le modifiche.
-
Arresta il server di sviluppo webpack.
-
Passare alla directory principale del progetto
/aem-guides-wknd-spae distribuire il progetto in AEM utilizzando Maven:code language-shell $ cd .. $ mvn clean install -PautoInstallSinglePackage -
Passa a http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html. Dovresti visualizzare l'Intestazione aggiornata con logo e stili applicati:
Ora che l’applicazione a pagina singola aggiornata è in AEM, l’authoring può continuare.
Congratulazioni. congratulations
Congratulazioni, hai aggiornato l’applicazione a pagina singola ed esplorato l’integrazione con AEM. Ora conosci due diversi approcci per lo sviluppo dell'applicazione a pagina singola rispetto all'API del modello JSON di AEM utilizzando un server di sviluppo webpack.
Puoi sempre visualizzare il codice finito su GitHub o estrarre il codice localmente passando al ramo Angular/integrate-spa-solution.
Passaggi successivi next-steps
Mappatura dei componenti SPA sui componenti AEM - Scopri come mappare i componenti Angular sui componenti Adobe Experience Manager (AEM) con AEM SPA Editor JS SDK. La mappatura dei componenti consente agli autori di apportare aggiornamenti dinamici ai componenti delle applicazioni a pagina singola nell’editor delle applicazioni a pagina singola di AEM, in modo simile all’authoring tradizionale AEM.