整合SPA integrate-spa
瞭解如何將在Angular中撰寫的單頁應用程式(SPA)原始程式碼與Adobe Experience Manager (AEM)專案整合。 瞭解如何使用現代前端工具(如Webpack開發伺服器),以針對AEM JSON模型API快速開發SPA。
目標
- 瞭解SPA專案如何與AEM和使用者端程式庫整合。
- 瞭解如何使用本機開發伺服器來進行專屬的前端開發。
- 探索使用 proxy 和靜態 Mock 檔案來針對AEM JSON模型API開發
您將建置的內容
本章會將簡單的Header元件新增至SPA。 在建立此靜態Header元件的過程中,使用了數種AEM SPA開發方法。
已延伸SPA以新增靜態Header元件
先決條件
檢閱設定本機開發環境所需的工具和指示。
取得程式碼
-
透過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 -
使用Maven將程式碼庫部署到本機AEM執行個體:
code language-shell $ mvn clean install -PautoInstallSinglePackage如果使用AEM 6.x,請新增
classic設定檔:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/integrate-spa-solution在本機取出程式碼。
整合方法 integration-approach
已建立兩個模組作為AEM專案的一部分: ui.apps和ui.frontend。
ui.frontend模組是包含所有SPA原始碼的webpack專案。 大部分的SPA開發和測試都在webpack專案中完成。 觸發生產組建時,會使用webpack建置及編譯SPA。 編譯的成品(CSS和JavaScript)會複製到ui.apps模組,然後部署至AEM執行階段。
SPA整合的高階描述。
有關前端組建的其他資訊可在此處找到。
檢查SPA整合 inspect-spa-integration
接下來,請檢查ui.frontend模組以瞭解由AEM專案原型自動產生的SPA。
-
在您選擇的IDE中,開啟WKND SPA的AEM專案。 此教學課程將使用Visual Studio Code IDE。
-
展開並檢查
ui.frontend資料夾。 開啟檔案ui.frontend/package.json -
在
dependencies下,您應該會看到數個與@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",ui.frontend模組是使用包含路由的Angular CLI工具產生的Angular應用程式。 -
同時有三個前置詞為
@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",上述模組構成AEM SPA Editor JS SDK,並提供可將SPA元件對應至AEM元件的功能。
-
在
package.json檔案中定義了多個scripts: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" }這些指令碼是以一般Angular CLI命令為基礎,但已稍作修改,以便與較大的AEM專案搭配使用。
start— 使用本機Web伺服器在本機執行Angular App。 它已更新,以代理本機AEM執行個體的內容。build— 編譯Angular應用程式以進行生產分送。 加入&& clientlib負責在建置期間將編譯的SPA作為使用者端程式庫複製到ui.apps模組中。 npm模組aem-clientlib-generator已用來協助處理這個問題。有關可用指令碼的更多詳細資料,請參閱這裡。
-
檢查檔案
ui.frontend/clientlib.config.js。 aem-clientlib-generator使用此設定檔來決定如何產生使用者端程式庫。 -
檢查檔案
ui.frontend/pom.xml。 此檔案會將ui.frontend資料夾轉換為Maven模組。pom.xml檔案已更新,以便在Maven組建期間使用frontend-maven-plugin至 test 和 build SPA。 -
在
ui.frontend/src/app/app.component.ts檢查檔案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是SPA的進入點。ModelManager由AEM SPA Editor JS SDK提供。 它負責呼叫pageModel(JSON內容)並將其插入應用程式。
新增標頭元件 header-component
接下來,將新元件新增至SPA,並將變更部署至本機AEM執行個體,以檢視整合。
-
開啟新的終端機視窗並瀏覽至
ui.frontend資料夾:code language-shell $ cd aem-guides-wknd-spa/ui.frontend -
全域安裝Angular CLI這是用來產生Angular元件,以及透過 ng 命令建置及提供Angular應用程式。
code language-shell $ npm install -g @angular/clinote caution CAUTION 此專案使用的**@angular/cli**版本是 9.1.7。 建議讓Angular CLI版本維持同步。 -
從
ui.frontend資料夾內執行Angular CLIng generate component命令,以建立新的Header元件。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)這將會在
ui.frontend/src/app/components/header為新的Angular Header元件建立骨架。 -
在您選擇的IDE中開啟
aem-guides-wknd-spa專案。 導覽至ui.frontend/src/app/components/header檔案夾。IDE中的
-
開啟檔案
header.component.html並將內容取代為下列內容:code language-html <!--/* header.component.html */--> <header className="header"> <div className="header-container"> <h1>WKND</h1> </div> </header>請注意,這會顯示靜態內容,因此此Angular元件不需要對預設產生的
header.component.ts進行任何調整。 -
在
ui.frontend/src/app/app.component.html開啟檔案 app.component.html。 新增app-header:code language-html <app-header></app-header> <router-outlet></router-outlet>這會在所有頁面內容上方包含
header元件。 -
開啟新的終端機,並導覽至
ui.frontend資料夾並執行npm 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. -
導覽至
ui.apps資料夾。 在ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-angular下方,您應該會看到已從ui.frontend/build資料夾複製編譯的SPA檔案。
-
返回終端機並導覽至
ui.apps資料夾。 執行下列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] ------------------------------------------------------------------------這會將
ui.apps封裝部署至AEM的本機執行個體。 -
開啟瀏覽器索引標籤並導覽至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。 您現在應該會看到
Header元件的內容顯示在SPA中。
從專案的根目錄(即mvn clean install -PautoInstallSinglePackage)觸發Maven組建時,會自動執行步驟 7至9。 您現在應該瞭解SPA與AEM使用者端程式庫之間整合的基本概念。 請注意,您仍然可以在AEM中編輯與新增Text元件,但Header元件不可編輯。
Webpack Dev Server - JSON API的Proxy proxy-json
如先前練習所示,執行組建並將使用者端程式庫同步至AEM的本機執行個體需要幾分鐘的時間。 這對於最終測試來說是可接受的,但對於大多數SPA開發而言並不理想。
可以使用webpack開發伺服器來快速開發SPA。 SPA由AEM產生的JSON模型驅動。 在本練習中,來自AEM執行個體的JSON內容 已代理 至由Angular專案設定的開發伺服器。
-
返回IDE並在
ui.frontend/proxy.conf.json開啟檔案 proxy.conf.json。code language-json [ { "context": [ "/content/**/*.(jpg|jpeg|png|model.json)", "/etc.clientlibs/**/*" ], "target": "http://localhost:4502", "auth": "admin:admin", "logLevel": "debug" } ]Angular應用程式提供簡單的機制來代理API要求。
context中指定的模式是透過本機AEM快速入門localhost:4502進行代理處理。 -
在
ui.frontend/src/index.html開啟檔案 index.html。 這是開發伺服器使用的根HTML檔案。請注意,
base href="/"有一個專案。 基底標籤對於應用程式解析相對URL而言至關重要。code language-html <base href="/"> -
開啟終端機視窗並導覽至
ui.frontend資料夾。 執行命令npm 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 -
開啟新的瀏覽器索引標籤(如果尚未開啟),並導覽至http://localhost:4200/content/wknd-spa-angular/us/en/home.html。
您應該會看到與AEM相同的內容,但未啟用任何撰寫功能。
-
返回IDE並在
ui.frontend/src/assets建立名為img的新資料夾。 -
下載下列WKND標誌並新增至
img資料夾:
-
在
ui.frontend/src/app/components/header/header.component.html開啟 header.component.html 並包含標誌: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>將變更儲存至 header.component.html。
-
返回瀏覽器。 您應該會立即看到應用程式的變更反映出來。
您可以繼續在 AEM 中進行內容更新,並看到這些更新反映在 webpack開發伺服器 中,因為我們正在代理內容。 請注意,內容變更只會顯示在 webpack開發伺服器 中。
-
停止終端機中具有
ctrl+c的本機Web伺服器。
Webpack Dev Server - Mock JSON API mock-json
快速開發的另一種方法是使用靜態JSON檔案充當JSON模型。 透過「嘲弄」 JSON,我們移除對本機AEM執行個體的相依性。 它也能讓前端開發人員更新JSON模型,以測試功能並推動JSON API的變更,之後再由後端開發人員實作。
模擬JSON的初始設定 需要本機AEM執行個體。
-
在瀏覽器中導覽至http://localhost:4502/content/wknd-spa-angular/us/en.model.json。
這是AEM匯出的驅動應用程式JSON。 複製JSON輸出。
-
返回IDE導覽至
ui.frontend/src並新增名為 mocks 和 json 的新資料夾,以符合下列資料夾結構:code language-plain |-- ui.frontend |-- src |-- mocks |-- json -
在
ui.frontend/public/mocks/json下建立名為 en.model.json 的新檔案。 從這裡貼上 步驟1 的JSON輸出。
-
在
ui.frontend下方建立新檔案 proxy.mock.conf.json。 將下列專案填入檔案中:code language-json [ { "context": [ "/content/**/*.model.json" ], "pathRewrite": { "^/content/wknd-spa-angular/us" : "/mocks/json"} , "target": "http://localhost:4200", "logLevel": "debug" } ]此Proxy設定會重寫以
/content/wknd-spa-angular/us開頭並為/mocks/json的請求,並提供對應的靜態JSON檔案,例如:code language-plain /content/wknd-spa-angular/us/en.model.json -> /mocks/json/en.model.json -
開啟檔案 angular.json。 新增具有已更新 資產 陣列的新 dev 設定,以參考已建立的 mocks 資料夾。
code language-json "dev": { "assets": [ "src/mocks", "src/assets", "src/favicon.ico", "src/logo192.png", "src/logo512.png", "src/manifest.json" ] },
建立專用的 dev 設定可確保 mocks 資料夾僅在開發期間使用,而且絕對不會部署至生產組建中的AEM。
-
在 angular.json 檔案中,接著更新 browserTarget 設定以使用新的 dev 設定:
code language-diff ... "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { + "browserTarget": "angular-app:build:dev" - "browserTarget": "angular-app:build" }, ...
-
開啟檔案
ui.frontend/package.json並新增新的 start:mock 命令以參照 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" }新增指令可讓您在Proxy設定之間輕鬆切換。
-
如果目前正在執行,請停止 webpack開發伺服器。 使用 start:mock 指令碼啟動 webpack dev server:
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.json導覽至http://localhost:4200/content/wknd-spa-angular/us/en/home.html,您應該會看到相同的SPA,但現在正在從 模型 JSON檔案提取內容。
-
對先前建立的 en.model.json 檔案進行小幅變更。 更新後的內容應立即反映在 webpack開發伺服器 中。
能夠操控JSON模型並檢視對即時SPA的影響有助於開發人員瞭解JSON模型API。 此外,前端和後端開發均可並行進行。
使用Sass新增樣式
接著,將一些更新的樣式新增至專案。 此專案將針對變數等幾項有用的功能新增Sass支援。
-
開啟終端機視窗並停止 webpack開發伺服器 (如果啟動)。 從
ui.frontend資料夾內輸入以下命令,以更新Angular應用程式以處理 .scss 檔案。code language-shell $ cd ui.frontend $ ng config schematics.@schematics/angular:component.styleext scss這會在檔案底部以新專案更新
angular.json檔案:code language-json "schematics": { "@schematics/angular:component": { "styleext": "scss" } } -
安裝
normalize-scss以跨瀏覽器標準化樣式:code language-shell $ npm install normalize-scss --save -
返回IDE,並在
ui.frontend/src下方建立名為styles的新資料夾。 -
在
ui.frontend/src/styles下建立名為_variables.scss的新檔案,並填入下列變數: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; -
將位於
ui.frontend/src/styles.css的檔案 styles.css 的副檔名重新命名為 styles.scss。 以下列專案取代內容: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; } -
更新 angular.json,並使用 styles.scss 重新命名 style.css 的所有參考。 應該有3個參考。
code language-diff "styles": [ - "src/styles.css" + "src/styles.scss" ],
更新標題樣式
接著,使用Sass將一些品牌特定樣式新增至 Header 元件。
-
啟動 webpack dev server 以即時檢視樣式更新:
code language-shell $ npm run start:mock -
在
ui.frontend/src/app/components/header底下,將 header.component.css 重新命名為 header.component.scss。 將下列專案填入檔案中: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; } -
更新 header.component.ts 以參照 header.component.scss:
code language-diff ... @Component({ selector: 'app-header', templateUrl: './header.component.html', - styleUrls: ['./header.component.css'] + styleUrls: ['./header.component.scss'] }) ... -
返回瀏覽器與 webpack開發伺服器:
您現在應該會看到更新的樣式已新增至 Header 元件。
將SPA更新部署至AEM
對 標頭 所做的變更目前只能透過 webpack開發伺服器 顯示。 將更新的SPA部署至AEM以檢視變更。
-
停止 webpack開發伺服器。
-
導覽至專案
/aem-guides-wknd-spa的根目錄,並使用Maven將專案部署至AEM:code language-shell $ cd .. $ mvn clean install -PautoInstallSinglePackage -
導覽至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。 您應該會看到已套用標誌和樣式的更新 Header:
現在,更新的SPA已匯入AEM,製作作業可以繼續進行。
恭喜! congratulations
恭喜,您已更新SPA並探索與AEM整合! 您現在知道使用 webpack開發伺服器 針對AEM JSON模型API開發SPA的兩種不同方法。
您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/integrate-spa-solution在本機取出程式碼。
後續步驟 next-steps
將SPA元件對應至AEM元件 — 瞭解如何使用AEM SPA Editor JS SDK將Angular元件對應至Adobe Experience Manager (AEM)元件。 元件對應可讓作者在AEM SPA Editor中對SPA元件進行動態更新,類似於傳統的AEM編寫。