AEMでSPAを使用する前に — React

単一ページアプリケーション(SPA)により、Web サイトのユーザーに魅力的なエクスペリエンスを提供することができます。開発者は SPA フレームワークを使用してサイトを構築したいと考え、作成者はそうして構築されたサイトのコンテンツを AEM 内でシームレスに編集したいと考えています。

SPA オーサリング機能には、AEM 内で SPA をサポートするための包括的なソリューションが用意されています。この記事では、React フレームワーク上のシンプルな SPA アプリケーションを紹介し、その設定方法を説明するほか、独自の SPA の運用をすぐに開始する方法についても説明します。

メモ

この記事は React フレームワークに基づいています。対応する Angular フレームワークのドキュメントについては、「Angular を使用した AEM での SPA の概要」を参照してください。

メモ

SPAフレームワークベースのクライアント側レンダリング(ReactやAngularなど)を必要とするプロジェクトには、SPA Editorが推奨されるソリューションです。

概要

この記事では、シンプルな SPA の基本的な機能と、SPA を運用するための最低条件の概要を説明します。

AEM での SPA の動作について詳しくは、次のドキュメントを参照してください。

メモ

SPA 内のコンテンツを作成するには、コンテンツを AEM に格納し、コンテンツモデルによって公開する必要があります。

AEM 以外で開発された SPA については、コンテンツモデルのコントラクトに準拠していない場合、オーサリングをおこなうことはできません。

このドキュメントでは、React フレームワークを使用して作成されたシンプルな SPA の構造を順を追って解説し、その仕組みを理解した上で独自の SPA に適用する方法を説明します。

依存関係、設定、ビルド

サンプルの SPA では、必要な React の依存関係以外に、追加のライブラリも利用して SPA の作成を効率化できます。

依存関係

package.json ファイルは、SPA パッケージ全体の要件を定義します。SPA の動作に対する AEM の最小依存関係を以下に示します。

  "dependencies": {
    "@adobe/aem-react-editable-components": "~1.0.4",
    "@adobe/aem-spa-component-mapping": "~1.0.5",
    "@adobe/aem-spa-page-model-manager": "~1.0.3"
  }

このサンプルは React フレームワークに基づいているので、package.json ファイルには必須となる React 固有の依存関係が 2 つあります。

react
 react-dom

クライアントライブラリの作成をビルドプロセスの一部として自動化するために、aem-clientlib-generator が活用されています。

"aem-clientlib-generator": "^1.4.1",

詳しくは、GitHub のこちらのページを参照してください。

注意

必要なaem-clientlib-generatorの最小バージョンは1.4.1です。

aem-clientlib-generator は、clientlib.config.js ファイルで次のように設定されています。

module.exports = {
    // default working directory (can be changed per 'cwd' in every asset option)
    context: __dirname,

    // path to the clientlib root folder (output)
    clientLibRoot: "./../content/jcr_root/apps/my-react-app/clientlibs",

    libs: {
        name: "my-react-app",
        allowProxy: true,
        categories: ["my-react-app"],
        embed: ["my-react-app.responsivegrid"],
        jsProcessor: ["min:gcc"],
        serializationFormat: "xml",
        assets: {
            js: [
                "dist/**/*.js"
            ],
            css: [
                "dist/**/*.css"
            ]
        }
    }
};

ビルド

アプリの実際のビルドでは、クライアントライブラリの自動作成用の aem-clientlib-generator 以外に、トランスパイル用に Webpack も利用します。そのため、build コマンドは以下のようになります。

"build": "webpack && clientlib --verbose"

ビルドが完了したら、パッケージを AEM インスタンスにアップロードできます。

AEM プロジェクトアーキタイプ

AEM プロジェクトでは、 AEM プロジェクトアーキタイプを活用します。このアーキタイプは、React または Angular を使用する SPA プロジェクトをサポートし、SPA SDK を活用します。

アプリケーション構造

以前に説明したように依存関係を追加してアプリをビルドすると、AEM インスタンスにアップロードできる SPA パッケージが作成されます。

このドキュメントの次の節では、AEM での SPA 自体の構造と、アプリケーションの動作にかかわる重要なファイルのほか、それらのファイルがどのように連携するのかについて説明します。

シンプルな画像コンポーネントを例として使用していますが、このアプリケーションのコンポーネントはすべて同じ概念に基づいています。

index.js

SPA のエントリポイントはもちろん index.js ファイルです。このファイルの内容を以下に示しますが、重要な部分のみに焦点を当てるために簡略化しています。

import ReactDOM from 'react-dom';
import App from './App';
import { ModelManager, Constants } from "@adobe/aem-spa-page-model-manager";

...

ModelManager.initialize().then((pageModel) => {
ReactDOM.render(
    <App cqChildren={pageModel[Constants.CHILDREN_PROP]} cqItems={pageModel[Constants.ITEMS_PROP]} cqItemsOrder={pageModel[Constants.ITEMS_ORDER_PROP]} cqPath={ModelManager.rootPath} locationPathname={ window.location.pathname }/>
, document.getElementById('page'));

});

index.js の主要機能は、ReactDOM.render 関数を活用して、DOM 内でアプリケーションをインジェクトする場所を決めることです。

これはこの関数の標準的な使用方法です。このアプリ例に独自の使用方法ではありません。

静的インスタンス化

コンポーネントテンプレート(JSX など)を使用して静的にコンポーネントをインスタンス化する場合は、モデルからコンポーネントのプロパティに値を渡す必要があります。

App.js

アプリをレンダリングすることで、index.jsApp.js を呼び出します。このファイルの内容を以下に示していますが、重要な部分のみに焦点を当てるために簡略化されています。

import {Page, withModel } from '@adobe/aem-react-editable-components';

...

class App extends Page {
...
}

export default withModel(App);

App.js の主な役目は、アプリを構成するルートコンポーネントをラップすることです。アプリのエントリポイントはページです。

Page.js

ページをレンダリングすると、App.js は以下の Page.js(簡易表示)を呼び出します。

import {Page, MapTo, withComponentMappingContext } from "@adobe/aem-react-editable-components";

...

class AppPage extends Page {
...
}

MapTo('my-react-app/components/structure/page')(withComponentMappingContext(AppPage));

この例の AppPage クラスでは、インナーコンテンツメソッドを含む Page を拡張して使用します。

Page は、ページモデルの JSON 表現を取り込み、コンテンツを処理してページの各要素をラップ/デコレートします。Page のその他の詳細については、SPA ブループリントのドキュメントを参照してください。

Image.js

ページがレンダリングされると、以下の Image.js などのコンポーネントがレンダリング可能になります。

import React, {Component} from 'react';
import {MapTo} from '@adobe/aem-react-editable-components';

require('./Image.css');

const ImageEditConfig = {

    emptyLabel: 'Image',

    isEmpty: function() {
        return !this.props || !this.props.src || this.props.src.trim().length < 1;
    }
};

class Image extends Component {

    render() {
        return (<img src={this.props.src}>);
    }
}

MapTo('my-react-app/components/content/image')(Image, ImageEditConfig);

AEM の SPA の中核概念は、SPA コンポーネントを AEM コンポーネントにマッピングし、コンテンツが変更されたときにコンポーネントも更新する(またはその逆も含む)というものです。この通信モデルの概要については、SPA エディターの概要のドキュメントを参照してください。

MapTo('my-react-app/components/content/image')(Image, ImageEditConfig);

MapTo メソッドは、SPA コンポーネントを AEM コンポーネントにマッピングします。単一の文字列または文字列の配列の使用に対応しています。

ImageEditConfig は、エディターがプレースホルダーを生成するために必要なメタデータを提供することで、コンポーネントのオーサリング機能の有効化に関与する設定オブジェクトです。

コンテンツがない場合は、空のコンテンツを表すラベルがプレースホルダーとして提供されます。

動的に渡されるプロパティ

モデルからのデータは、コンポーネントのプロパティとして動的に渡されます。

編集可能コンテンツの書き出し

コンポーネントをエクスポートして編集可能な状態を維持することができます。

import React, { Component } from 'react';
import { MapTo } from '@adobe/aem-react-editable-components';

...

const EditConfig = {...}

class PageClass extends Component {...};

...

export default MapTo('my-react-app/react/components/structure/page')(PageClass, EditConfig);

MapTo 関数は、指定された Component を、オーサリング可能にするクラス名と属性で拡張した構成結果の PageClass を返します。このコンポーネントは後でエクスポートし、アプリケーションのマークアップでインスタンス化できます。

MapTo または withModel 関数を使用してエクスポートされた Page コンポーネントは、ModelProvider コンポーネントによってラップされます。このコンポーネントは、標準コンポーネントに、ページモデルの最新バージョンに対するアクセス権またはそのページモデル内の詳細な位置を提供します。

詳しくは、SPA ブループリントのドキュメントを参照してください。

メモ

デフォルトでは、withModel 関数を使用するとコンポーネントのモデル全体を受け取ります。

SPA コンポーネント間での情報の共有

単一ページのアプリケーション内のコンポーネントが情報を共有することは定期的に必要です。これをおこなう推奨方法にはいくつかあり、以下に簡単なものから順に示します。

  • オプション 1: React Context などを使用して、ロジックを一元化し、必要なコンポーネントにブロードキャストします。
  • オプション 2: Redux などのステートライブラリを使用して、コンポーネントの状態を共有します。
  • オプション 3:​コンテナコンポーネントをカスタマイズおよび拡張することで、オブジェクト階層を活用します。

次の手順

独自のSPAを作成する手順を説明したガイドについては、『AEM SPA Editor - WKNDイベントの使い始めに — チュートリアル](https://helpx.adobe.com/jp/experience-manager/kt/sites/using/getting-started-spa-wknd-tutorial-develop.html)』を参照してください。[

AEM向けSPAを開発するための組織編成の詳細については、「 AEM用SPAの開発」を参照してください。

動的モデルとコンポーネントのマッピングおよびAEMのSPA内での動作について詳しくは、「SPA](/docs/experience-manager-65/sites-developing/spa-dynamic-model-to-component-mapping.html?lang=ja)の動的モデルとコンポーネントのマッピング」を参照してください。[

ReactやAngular以外のフレームワーク用にSPAをAEMに実装する場合、またはAEM用のSPA SDKの仕組みを簡単に詳しく調べたい場合は、SPA Blueprintの記事を参照してください。

このページ

Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free