SPA Editor SDK を使用して AEM ページにマッピングすることで、SPA の複数のビューをサポートする方法について説明します。 動的ナビゲーションは、React Router と React Core Components を使用して実装されています。
この章では、AEM の SPA にナビゲーションを追加します。 ナビゲーションメニューは AEM のページ階層によって起動され、ナビゲーションコアコンポーネントが提供する JSON モデルを活用します。
ローカル開発環境の設定に必要なツールや手順を確認します。この章は、コンポーネントのマッピングの続きとなりますが、必要な操作をすべて実行するには、SPA 対応 AEM プロジェクトをローカル AEM インスタンスにデプロイする必要があります。
ブラウザーを開き、AEM(http://localhost:4502/)にログインします。開始コードベースは、既にデプロイされている必要があります。
SPA ページテンプレート(http://localhost:4502/editor.html/conf/wknd-spa-react/settings/wcm/templates/spa-page-template/structure.html)に移動します。
一番外にある「ルートレイアウトコンテナ」を選択し、そのポリシーアイコンをクリックします。オーサリングで レイアウトコンテナのロック解除を選択しないように注意します。
SPA 構造という名前の新しいポリシーを作成します。
許可されたコンポーネント/一般でレイアウトコンテナのコンポーネントを選択します。
許可されたコンポーネント/WKND SPA REACT - 構造 でナビゲーションコンポーネントを選択します。
許可されたコンポーネント/WKND SPA REACT - コンテンツで、画像およびテキストのコンポーネントを選択します。合計 4 つのコンポーネントを選択する必要があります。
「完了」をクリックして、変更を保存します。
ページを更新し、ロック解除されたレイアウトコンテナの上にナビゲーションコンポーネントを追加します。
ナビゲーションコンポーネントを選択し、そのポリシーアイコンをクリックして、ポリシーを編集します。
SPA ナビゲーションのポリシーのタイトルを使用して新しいポリシーを作成します。
「プロパティ」で、次の手順を実行します。
/content/wknd-spa-react/us/en
に設定します。これにより、/content/wknd-spa-react/us/en
の 2 レベル下のナビゲーションが収集されます。
変更を保存すると、テンプレートの一部として入力された Navigation
が表示されます。
次に、AEM で別のビューとして機能する追加のページを作成します。 また、AEM が提供する JSON モデルの階層構造も調べます。
Sites コンソール(http://localhost:4502/sites.html/content/wknd-spa-react/us/en/home)に移動します。「WKND SPA React ホームページ」を選択し、作成/ページをクリックします。
「テンプレート」で「SPA ページ」を選択します。プロパティで、タイトルに「Page 1」、名前に「page-1」と入力します。
「作成」をクリックし、ダイアログのポップアップで「開く」をクリックして、AEM SPA エディターでページを開きます。
新規テキストコンポーネントをメインのレイアウトコンテナに追加します。コンポーネントを編集し、RTE と H2 要素を使用して「Page 1」というテキストを入力します。
画像などのコンテンツを自由に追加できます。
AEM Sites コンソールに戻り、上記の手順を繰り返して、Page 1 の兄弟として Page 2 という名前の 2 番目のページを作成します。
最後に、3 番目のページである Page 3 を、Page 2 の子として作成します。完了すると、サイト階層は次のようになります。
ナビゲーションコンポーネントを使用して、SPA の様々な領域に移動できるようになりました。
AEM エディターの外部でページを開きます。http://localhost:4502/content/wknd-spa-react/us/en/home.html。ナビゲーションコンポーネントを使用して、アプリの様々なビューに移動します。
ブラウザーのデベロッパーツールを使用して、ナビゲート中にネットワークリクエストを調べます。以下のスクリーンショットは、Google Chrome ブラウザーからキャプチャしたものです。
最初のページを読み込んだ後、後続のナビゲーションでページ全体が更新されず、以前訪問したページに戻る際にネットワークトラフィックが最小化されていることを確認します。
次に、SPA のマルチビューエクスペリエンスを推進する JSON モデルを調べます。
新規タブで、AEM が提供する JSON モデル API を開きます。http://localhost:4502/content/wknd-spa-react/us/en.model.json。ブラウザー拡張機能を使用して JSON の形式を設定すると役立つ場合があります。
この JSON コンテンツは、SPAが最初に読み込まれる際にリクエストされます。 外側の構造は次のようになります。
{
"language": "en",
"title": "en",
"templateName": "spa-app-template",
"designPath": "/libs/settings/wcm/designs/default",
"cssClassNames": "spa page basicpage",
":type": "wknd-spa-react/components/spa",
":items": {},
":itemsOrder": [],
":hierarchyType": "page",
":path": "/content/wknd-spa-react/us/en",
":children": {
"/content/wknd-spa-react/us/en/home": {},
"/content/wknd-spa-react/us/en/home/page-1": {},
"/content/wknd-spa-react/us/en/home/page-2": {},
"/content/wknd-spa-react/us/en/home/page-2/page-3": {}
}
}
:children
の下に、作成された各ページのエントリが表示されます。すべてのページのコンテンツは、この最初の JSON リクエストに含まれます。 ナビゲーションルーティングを使用すると、コンテンツが既にクライアントサイドで使用可能になっているため、SPA の後続のビューが素早く読み込まれます。
最初のページの読み込みが遅くなるため、最初の JSON リクエストで SPA のすべてのコンテンツを読み込むのは得策ではありません。次に、ページの階層の深度を収集する方法について説明します。
SPA Rootテンプレートに移動します。http://localhost:4502/editor.html/conf/wknd-spa-react/settings/wcm/templates/spa-app- template/structure.html。
ページプロパティメニュー/ページポリシーをクリックします。
SPA Root テンプレートにある「階層構造」タブでは、収集される JSON コンテンツを制御できます。構造の深度は、ルートの下の子ページを収集するサイト階層の深度を決定します。「構造パターン」フィールドを使用して、正規表現に基づいて追加のページを除外することもできます。
「構造の深度」を 2 に更新します。
「完了」をクリックして、変更をポリシーに保存します。
JSON モデルを再度開きます。 http://localhost:4502/content/wknd-spa-react/us/en.model.json
{
"language": "en",
"title": "en",
"templateName": "spa-app-template",
"designPath": "/libs/settings/wcm/designs/default",
"cssClassNames": "spa page basicpage",
":type": "wknd-spa-react/components/spa",
":items": {},
":itemsOrder": [],
":hierarchyType": "page",
":path": "/content/wknd-spa-react/us/en",
":children": {
"/content/wknd-spa-react/us/en/home": {},
"/content/wknd-spa-react/us/en/home/page-1": {},
"/content/wknd-spa-react/us/en/home/page-2": {}
}
}
Page 3 のパス(最初の JSON モデルの /content/wknd-spa-react/us/en/home/page-2/page-3
)が削除されています。これは、Page 3 が階層のレベル 3 にあり、レベル 2 の最大深度のコンテンツのみを含めるようにポリシーを更新したためです。
SPA ホームページ(http://localhost:4502/content/wknd-spa-react/us/en/home.html)を再度開き、ブラウザーのデベロッパーツールを開きます。
ページを更新すると、SPA Root である /content/wknd-spa-react/us/en.model.json
への XHR リクエストが表示されます。このチュートリアルで前述した SPA ルートテンプレートの階層の深さ設定に基づいて、3 つの子ページのみが含まれます。 これには、Page 3 は含まれません。
デベロッパーツールを開いた状態で、Navigation
コンポーネントを使用して Page 3 に直接移動します。
/content/wknd-spa-react/us/en/home/page-2/page-3.model.json
に対して新しい XHR リクエストが行われることを確認します。
AEM Model Manager では、Page 3 の JSON コンテンツは使用せず、追加の XHR リクエストを自動的にトリガーします。
http://localhost:4502/content/wknd-spa-react/us/en/home/page-2.html に直接移動して、ディープリンクを試します。また、ブラウザーの「戻る」ボタンが引き続き機能することを確認します。
ナビゲーションとルーティングは React Router で実装されています。React Router は、React アプリケーション用のナビゲーションコンポーネントのコレクションです。AEM React コアコアコンポーネントは、React Router の機能を使用して、前の手順で使用したナビゲーションコンポーネントを実装します。
次に、React Router が SPA とどのように統合されているかを調べ、React Router のリンクコンポーネントを使用して実験します。
IDE で、ui.frontend/src/index.js
にあるファイル index.js
を開きます。
/* index.js */
import { Router } from 'react-router-dom';
...
...
ModelManager.initialize().then(pageModel => {
const history = createBrowserHistory();
render(
<Router history={history}>
<App
history={history}
cqChildren={pageModel[Constants.CHILDREN_PROP]}
cqItems={pageModel[Constants.ITEMS_PROP]}
cqItemsOrder={pageModel[Constants.ITEMS_ORDER_PROP]}
cqPath={pageModel[Constants.PATH_PROP]}
locationPathname={window.location.pathname}
/>
</Router>,
document.getElementById('spa-root')
);
});
App
が React Router の Router
コンポーネントにラップされていることを確認します。ModelManager
は AEM SPA Editor JS SDK で提供され、JSON モデル API に基づいて動的ルートを AEM ページに追加します。
ui.frontend/src/components/Page/Page.js
でファイル Page.js
を開きます
class AppPage extends Page {
get containerProps() {
let attrs = super.containerProps;
attrs.className =
(attrs.className || '') + ' page ' + (this.props.cssClassNames || '');
return attrs;
}
}
export default MapTo('wknd-spa-react/components/page')(
withComponentMappingContext(withRoute(AppPage))
);
Page
SPA コンポーネントは、MapTo
関数を使用して、AEM のページを対応する SPA コンポーネントにマップします。withRoute
ユーティリティは、cqPath
プロパティに基づいて、SPA を適切な AEM 子ページに動的にルーティングするのに役立ちます。
ui.frontend/src/components/Header/Header.js
で Header.js
コンポーネントを開きます。
Header
を更新して、ホームページへのリンクで <h1>
タグをラップします。
//Header.js
import React, {Component} from 'react';
+ import {Link} from 'react-router-dom';
require('./Header.css');
export default class Header extends Component {
render() {
return (
<header className="Header">
<div className="Header-container">
+ <Link to="/content/wknd-spa-react/us/en/home.html">
<h1>WKND</h1>
+ </Link>
</div>
</header>
);
}
デフォルトの <a>
アンカータグを使用する代わりに、React Router が提供する <Link>
を使用します。to=
が有効なルートを指す場合、SPA はそのルートに切り替わり、ページ全体の更新は実行しません。ここでは、単にホームページへのリンクをハードコードして、Link
の使用法について説明します。
ui.frontend/src/App.test.js
で App.test.js
のテストを更新します。
+ import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
- ReactDOM.render(<App />, div);
+ ReactDOM.render(<Router><App /></Router>, div);
});
App.js
で参照される静的コンポーネント内で React Router の機能を使用しているため、単体テストを更新する際には考慮が必要です。
ターミナルを開き、プロジェクトのルートに移動して、Maven スキルを使用して AEM にプロジェクトをデプロイします。
$ cd aem-guides-wknd-spa.react
$ mvn clean install -PautoInstallSinglePackage
AEM で SPA のいずれかのページに移動します。http://localhost:4502/content/wknd-spa-react/us/en/home/page-1.html
Navigation
コンポーネントを使用して移動する代わりに、Header
内のリンクを使用します。
ページ全体の更新がトリガーされず、SPA ルーティングが機能していることを確認します。
必要に応じて、標準の <a>
アンカータグを使用して Header.js
ファイルで試します。
<a href="/content/wknd-spa-react/us/en/home.html">
<h1>WKND</h1>
</a>
これは、SPA ルーティングと通常の web ページリンクの違いを説明するのに役立ちます。
これで、SPA Editor SDK で AEM ページにマッピングすることで、SPA の複数のビューをサポートする方法を学びました。 React Router を使用して動的ナビゲーションが実装され、Header
コンポーネントに追加されました。