整合SPA integrate-spa

瞭解以Angular撰寫的單頁應用程式(SPA)原始碼如何與Adobe Experience Manager (AEM)專案整合。 瞭解如何使用現代前端工具(如Webpack開發伺服器),以針對SPA JSON模型API快速開發AEM。

目標

  1. 瞭解SPA專案如何與AEM和使用者端程式庫整合。
  2. 瞭解如何使用本機開發伺服器來進行專屬的前端開發。
  3. 探索使用​ proxy ​和靜態​ Mock ​檔案來針對AEM JSON模型API開發

您將建置的內容

本章會將簡單的Header元件新增至SPA。 在建置此靜態Header元件的過程中,使用了數種AEM SPA開發方法。

在AEM 中新增標題

SPA已擴充以新增靜態Header元件

先決條件

檢閱設定本機開發環境所需的工具和指示。

取得程式碼

  1. 透過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
    
  2. 使用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.appsui.frontend

ui.frontend模組是包含所有SPA原始程式碼的webpack專案。 大部分的SPA開發和測試都是在webpack專案中完成的。 觸發生產組建時,會使用webpack建置及編譯SPA。 編譯的成品(CSS和Javascript)會複製到ui.apps模組,然後部署到AEM執行階段。

ui.frontend高階架構

SPA整合的高階描述。

有關前端組建的其他資訊可在此處找到。

Inspect與SPA整合 inspect-spa-integration

接下來,檢查ui.frontend模組以瞭解AEM專案原型已自動產生的SPA。

  1. 在您選擇的IDE中,開啟WKND SPA的AEM專案。 此教學課程將使用Visual Studio Code IDE

    VSCode - AEM WKND SPA專案

  2. 展開並檢查ui.frontend資料夾。 開啟檔案ui.frontend/package.json

  3. 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模組是使用包含路由的AngularCLI工具產生的Angular應用程式

  4. 同時有三個前置詞為@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元件的功能。

  5. 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"
    }
    

    這些指令碼是以一般AngularCLI命令為基礎,但已稍作修改,以便與較大的AEM專案搭配使用。

    start — 使用本機網頁伺服器在本機執行Angular應用程式。 它已更新,以代理本機AEM執行個體的內容。

    build — 編譯Angular應用程式以進行生產分送。 加入&& clientlib負責在建置期間將編譯的SPA作為使用者端程式庫複製到ui.apps模組中。 npm模組aem-clientlib-generator已用來協助處理這個問題。

    有關可用指令碼的更多詳細資料,請參閱這裡

  6. Inspect檔案ui.frontend/clientlib.config.jsaem-clientlib-generator使用此設定檔來決定如何產生使用者端程式庫。

  7. Inspect檔案ui.frontend/pom.xml。 此檔案會將ui.frontend資料夾轉換為Maven模組pom.xml檔案已更新,以便在Maven組建期間使用frontend-maven-plugin至​ test ​和​ build SPA。

  8. ui.frontend/src/app/app.component.tsInspect檔案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編輯器JS SDK提供。 它負責呼叫pageModel (JSON內容)並將其插入應用程式。

新增標頭元件 header-component

接下來,將新元件新增至SPA,並將變更部署至本機AEM執行個體,以檢視整合。

  1. 開啟新的終端機視窗並瀏覽至ui.frontend資料夾:

    code language-shell
    $ cd aem-guides-wknd-spa/ui.frontend
    
  2. 全域安裝AngularCLI這是用來產生Angular元件,以及透過​ ng ​命令建置及提供Angular應用程式。

    code language-shell
    $ npm install -g @angular/cli
    
    note caution
    CAUTION
    此專案使用的​**@angular/cli**​版本是​ 9.1.7。 建議讓AngularCLI版本保持同步。
  3. ui.frontend資料夾內執行AngularCLI ng 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標題元件建立骨架。

  4. 在您選擇的IDE中開啟aem-guides-wknd-spa專案。 導覽至 ui.frontend/src/app/components/header 檔案夾。

    IDE中的 Header元件路徑

  5. 開啟檔案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進行任何調整。

  6. ui.frontend/src/app/app.component.html開啟檔案​ app.component.html。 新增app-header

    code language-html
    <app-header></app-header>
    <router-outlet></router-outlet>
    

    這會在所有頁面內容上方包含header元件。

  7. 開啟新的終端機,並導覽至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.
    
  8. 導覽至ui.apps資料夾。 在ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-angular下方,您應該會看到編譯的SPA檔案是從ui.frontend/build資料夾中複製的。

    在ui.apps中產生的使用者端資料庫

  9. 返回終端機並導覽至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的本機執行個體。

  10. 開啟瀏覽器索引標籤並導覽至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專案設定的開發伺服器。

  1. 返回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中指定的模式是透過localhost:4502 (本機AEM快速入門)進行代理處理。

  2. ui.frontend/src/index.html開啟檔案​ index.html。 這是開發伺服器使用的根HTML檔案。

    請注意,base href="/"有一個專案。 基底標籤對於應用程式解析相對URL而言至關重要。

    code language-html
    <base href="/">
    
  3. 開啟終端機視窗並導覽至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
    
  4. 開啟新的瀏覽器索引標籤(如果尚未開啟),並導覽至http://localhost:4200/content/wknd-spa-angular/us/en/home.html

    Webpack開發伺服器 — Proxy json

    您應該會看到與AEM相同的內容,但未啟用任何撰寫功能。

  5. 返回IDE並在ui.frontend/src/assets建立名為img的新資料夾。

  6. 下載下列WKND標誌並新增至img資料夾:

    WKND標誌

  7. 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

  8. 返回瀏覽器。 您應該會立即看到應用程式的變更反映出來。

    標誌已新增至標頭

    您可以繼續在​ AEM ​中進行內容更新,並看到這些更新反映在​ webpack開發伺服器 ​中,因為我們正在代理內容。 請注意,內容變更只會顯示在​ webpack開發伺服器 ​中。

  9. 停止終端機中具有ctrl+c的本機Web伺服器。

Webpack Dev Server - Mock JSON API mock-json

快速開發的另一種方法是使用靜態JSON檔案充當JSON模型。 透過「嘲弄」 JSON,我們移除對本機AEM例項的相依性。 它也能讓前端開發人員更新JSON模型,以測試功能並推動JSON API的變更,之後再由後端開發人員實作。

模擬JSON的初始設定​ 需要本機AEM執行個體

  1. 在瀏覽器中導覽至http://localhost:4502/content/wknd-spa-angular/us/en.model.json

    這是由AEM匯出並驅動應用程式的JSON。 複製JSON輸出。

  2. 返回IDE導覽至ui.frontend/src並新增名為​ mocks ​和​ json ​的新資料夾,以符合下列資料夾結構:

    code language-plain
    |-- ui.frontend
        |-- src
            |-- mocks
                |-- json
    
  3. ui.frontend/public/mocks/json下建立名為​ en.model.json ​的新檔案。 從這裡貼上​ 步驟1 ​的JSON輸出。

    模擬模型Json檔案

  4. 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
    
  5. 開啟檔案​ 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"
              ]
        },
    

    AngularJSON Dev Assets更新資料夾

    建立專用的​ dev ​設定可確保​ mocks ​資料夾僅用於開發期間,且絕對不會部署至生產組建中的AEM。

  6. 在​ 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"
          },
      ...
    

    AngularJSON組建開發更新

  7. 開啟檔案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設定之間輕鬆切換。

  8. 如果目前正在執行,請停止​ 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檔案提取內容。

  9. 對先前建立的​ en.model.json ​檔案進行小幅變更。 更新後的內容應立即反映在​ webpack開發伺服器 ​中。

    模型的json更新

    能夠操控JSON模型並檢視對即時SPA的影響有助於開發人員瞭解JSON模型API。 此外,前端和後端開發均可並行進行。

使用Sass新增樣式

接著,將一些更新的樣式新增至專案。 此專案將針對變數等幾項有用的功能新增Sass支援。

  1. 開啟終端機視窗並停止​ 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"
        }
    }
    
  2. 安裝normalize-scss以跨瀏覽器標準化樣式:

    code language-shell
    $ npm install normalize-scss --save
    
  3. 返回IDE,並在ui.frontend/src下方建立名為styles的新資料夾。

  4. 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;
    
  5. 將位於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;
    }
    
  6. 更新​ angular.json,並使用​ styles.scss ​重新命名​ style.css ​的所有參考。 應該有3個參考。

    code language-diff
      "styles": [
    -    "src/styles.css"
    +    "src/styles.scss"
       ],
    

更新標題樣式

接著,使用Sass將一些品牌特定樣式新增至​ Header ​元件。

  1. 啟動​ webpack dev server ​以即時檢視樣式更新:

    code language-shell
    $ npm run start:mock
    
  2. 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;
    }
    
  3. 更新​ 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']
      })
    ...
    
  4. 返回瀏覽器與​ webpack開發伺服器

    樣式標頭 — webpack dev server

    您現在應該會看到更新的樣式已新增至​ Header ​元件。

將SPA更新部署至AEM

對​ 標頭 ​所做的變更目前只能透過​ webpack開發伺服器 ​顯示。 將更新的SPA部署到AEM以檢視變更。

  1. 停止​ webpack開發伺服器

  2. 導覽至專案/aem-guides-wknd-spa的根並使用Maven將專案部署到AEM:

    code language-shell
    $ cd ..
    $ mvn clean install -PautoInstallSinglePackage
    
  3. 導覽至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。 您應該會看到已套用標誌和樣式的更新​ Header

    已在AEM中更新標題

    現在AEM已更新SPA,製作作業可以繼續進行。

恭喜! congratulations

恭喜,您已更新SPA並探索與AEM整合! 您現在知道使用​ webpack開發伺服器 ​針對AEM JSON模型API開發SPA的兩種不同方法。

您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/integrate-spa-solution在本機取出程式碼。

後續步驟 next-steps

將SPA元件對應至AEM元件 — 瞭解如何使用AEM SPA編輯器JS SDK將Angular元件對應至Adobe Experience Manager (AEM)元件。 元件對應可讓作者在SPA SPA編輯器中對AEM元件進行動態更新,類似於傳統的AEM編寫。

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4