SPA エディター用のリモート SPA のBootstrap

編集可能な領域をリモート SPA に追加する前に、AEM SPA エディター JavaScript SDK とその他のいくつかの設定でブートストラップ処理を行う必要があります。

AEM SPA エディター JS SDK npm 依存関係のインストール

まず、React プロジェクトのAEM SPA npm の依存関係を確認してインストールします。

$ cd ~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app
$ npm install @adobe/aem-spa-page-model-manager
$ npm install @adobe/aem-spa-component-mapping
$ npm install @adobe/aem-react-editable-components

SPA 環境変数の確認

AEM とのやり取りの方法を理解できるように、いくつかの環境変数をリモート SPA に公開する必要があります。

  1. IDE の ~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app でリモート SPA プロジェクトを開きます

  2. ファイル .env.development を開きます

  3. ファイルでキーに特に注意しながら、必要に応じて更新します。

    code language-none
    REACT_APP_HOST_URI=http://localhost:4502
    
    REACT_APP_USE_PROXY=true
    
    REACT_APP_AUTH_METHOD=basic
    
    REACT_APP_BASIC_AUTH_USER=admin
    REACT_APP_BASIC_AUTH_PASS=admin
    

    リモート SPA 環境変数

    React のカスタム環境変数には、「REACT_APP_」のプレフィックスが付いている必要があります。

    • REACT_APP_HOST_URI:リモート SPA が接続する AEM サービスのスキームとホスト

      • この値は、AEM環境(ローカル、開発、ステージング、実稼動)と AEM サービスのタイプ(オーサーとパブリッシュ)に応じて変わります
    • REACT_APP_USE_PROXYhttp-proxy-middleware モジュールを使用する /content, /graphql, .model.json などの AEM リクエストをプロキシするよう React 開発サーバーに指示することで、開発中の CORS の問題を回避できます

    • REACT_APP_AUTH_METHOD:AEM 経由のリクエストの認証方法。オプションは「service-token」、「dev-token」、「basic」です。認証なしのユースケースの場合は空白のままにします。

      • AEM 作成者で使用する場合は必須です
      • AEM パブリッシュでの使用で必要な場合があります(コンテンツが保護されている場合)
      • AEM SDK に対する開発では、Basic Auth を介してローカルアカウントをサポートします。これは、このチュートリアルで使用している方法です
      • AEM as a Cloud Serviceと統合する際は、アクセストークンを使用します
    • REACT_APP_BASIC_AUTH_USER:AEM コンテンツの取得時に SPA が認証する AEM ユーザー名

    • REACT_APP_BASIC_AUTH_PASS:AEM コンテンツの取得時に SPA が認証する AEM パスワード

ModelManager API の統合

アプリで利用できる AEM SPA npm の依存関係を使って、ReactDOM.render(...) が呼び出される前にプロジェクトの index.js でAEMの ModelManager を初期化します。

この ModelManager は、AEM に接続して編集可能なコンテンツを取得します。

  1. IDE でリモート SPAプロジェクトを開きます。

  2. ファイル src/index.js を開きます。

  3. ModelManager の読み込みを追加し、root.render(..) 呼び出しの前に初期化します。

    code language-javascript
    ...
    import { ModelManager } from "@adobe/aem-spa-page-model-manager";
    
    // Initialize the ModelManager before invoking root.render(..).
    ModelManager.initializeAsync();
    
    const container = document.getElementById('root');
    const root = createRoot(container);
    root.render(<App />);
    

src/index.js ファイルは次のようになります。

src/index.js

内部 SPA プロキシの設定

編集可能な SPA を作成する際は、適切なリクエストを AEM にルーティングするように設定されている SPA の内部プロキシを設定することをお勧めします。これは、ベース WKND GraphQL アプリによって既にインストールされている http-proxy-middleware npm モジュールを使用して行います。

  1. IDE でリモート SPAプロジェクトを開きます。

  2. src/proxy/setupProxy.spa-editor.auth.basic.js でファイルを開きます。

  3. ファイルを次のコードで更新します。

    code language-javascript
    const { createProxyMiddleware } = require('http-proxy-middleware');
    const {REACT_APP_HOST_URI, REACT_APP_BASIC_AUTH_USER, REACT_APP_BASIC_AUTH_PASS } = process.env;
    
    /*
        Set up a proxy with AEM for local development
        In a production environment this proxy should be set up at the webserver level or absolute URLs should be used.
    */
    module.exports = function(app) {
    
        /**
        * Filter to check if the request should be re-routed to AEM. The paths to be re-routed at:
        * - Starts with /content (AEM content)
        * - Starts with /graphql (AEM graphQL endpoint)
        * - Ends with .model.json (AEM Content Services)
        *
        * @param {*} path the path being requested of the SPA
        * @param {*} req the request object
        * @returns true if the SPA request should be re-routed to AEM
        */
        const toAEM = function(path, req) {
            return path.startsWith('/content') ||
                path.startsWith('/graphql') ||
                path.endsWith('.model.json')
        }
    
        /**
        * Re-writes URLs being proxied to AEM such that they can resolve to real AEM resources
        * - The "root" case of `/.model.json` are rewritten to the SPA's home page in AEM
        * - .model.json requests for /adventure:xxx routes are rewritten to their corresponding adventure page under /content/wknd-app/us/en/home/adventure/
        *
        * @param {*} path the path being requested of the SPA
        * @param {*} req the request object
        * @returns returns a re-written path, or nothing to use the @param path
        */
        const pathRewriteToAEM = function (path, req) {
            if (path === '/.model.json') {
                return '/content/wknd-app/us/en/home.model.json';
            } else if (path.startsWith('/adventure/') && path.endsWith('.model.json')) {
                return '/content/wknd-app/us/en/home/adventure/' + path.split('/').pop();
            }
        }
    
        /**
        * Register the proxy middleware using the toAEM filter and pathRewriteToAEM rewriter
        */
        app.use(
            createProxyMiddleware(
                toAEM, // Only route the configured requests to AEM
                {
                    target: REACT_APP_HOST_URI,
                    changeOrigin: true,
                    // Pass in credentials when developing against an Author environment
                    auth: `${REACT_APP_BASIC_AUTH_USER}:${REACT_APP_BASIC_AUTH_PASS}`,
                    pathRewrite: pathRewriteToAEM // Rewrite SPA paths being sent to AEM
                }
            )
        );
    
        /**
        * Enable CORS on requests from the SPA to AEM
        *
        * If this rule is not in place, CORS errors will occur when running the SPA on http://localhost:3000
        */
        app.use((req, res, next) => {
            res.header("Access-Control-Allow-Origin", REACT_APP_HOST_URI);
            next();
        });
    };
    

    setupProxy.spa-editor.auth.basic.js ファイルは次のようになります。

    src/proxy/setupProxy.spa-editor.auth.basic.js

    このプロキシ設定では、主に次の 2 つを行います。

    1. SPA(http://localhost:3000)から AEM http://localhost:4502 に対して行われる特定のリクエストのプロキシ

      • toAEM(path, req) に定義されているとおり、プロキシの対象となるのは、AEM が提供する必要があることを示すパターンに一致するパスを持つリクエストのみです。
      • pathRewriteToAEM(path, req) に定義されているとおり、SPA のパスを同等の AEM ページに書き換えます。
    2. res.header("Access-Control-Allow-Origin", REACT_APP_HOST_URI); で定義されているとおり、すべてのリクエストに CORS ヘッダーを追加して、AEM コンテンツへのアクセスを許可します。

      • これを追加しない場合、SPA で AEM コンテンツを読み込む際に CORS エラーが発生します。
  4. ファイル src/setupProxy.js を開きます。

  5. setupProxy.spa-editor.auth.basic プロキシ設定ファイルを指している行を確認します。

    code language-none
    ...
    case BASIC:
    // Use user/pass for local development with Local Author Env
    return require('./proxy/setupProxy.spa-editor.auth.basic');
    ...
    

なお、src/setupProxy.js またはその参照先ファイルに変更がある場合は、SPA を再起動する必要があります。

静的 SPA リソース

WKND ロゴなどの静的 SPA リソースやグラフィックの読み込みでは、src URL を更新させて、リモート SPA のホストから強制的に読み込む必要があります。SPA がオーサリング用に SPA エディターに読み込まれる際に相対指定のままにした場合、これらの URL はデフォルトで SPA ではなく AEM のホストを使用するようになります。その結果、次の画像に示すように 404 リクエストエラーが発生します。

壊れた静的リソース

この問題を解決するには、リモート SPA でホストされる静的リソースで、リモート SPA のオリジンを含んだ絶対パスを使用するようにします。

  1. IDE で SPA プロジェクトを開きます。

  2. SPA の環境変数ファイル src/.env.development を開き、SPA のパブリック URI 用の変数を追加します。

    code language-none
    ...
    # The base URI the SPA is accessed from
    REACT_APP_PUBLIC_URI=http://localhost:3000
    

    AEM as a Cloud Service にデプロイする場合は、対応する .env ファイルに同じ操作を実行する必要があります。

  3. ファイル src/App.js を開きます。

  4. SPA の環境変数から SPA のパブリック URI を読み込みます。

    code language-javascript
    const {  REACT_APP_PUBLIC_URI } = process.env;
    
    function App() { ... }
    
  5. WKND ロゴ <img src=.../> の前に REACT_APP_PUBLIC_URI を付けて、SPA に対する解決を強制します。

    code language-html
    <img src={REACT_APP_PUBLIC_URI + '/' +  logo} className="logo" alt="WKND Logo"/>
    
  6. src/components/Loading.js での画像の読み込みにも、同じ操作を行います。

    code language-javascript
    const { REACT_APP_PUBLIC_URI } = process.env;
    
    class Loading extends Component {
    
        render() {
            return (<div className="loading">
                <img src={REACT_APP_PUBLIC_URI + '/' + loadingIcon} alt="Loading..." />
            </div>);
        }
    }
    
  7. また、src/components/AdventureDetails.js での「戻る」ボタンの 2 つのインスタンス ​についても同様です。

    code language-javascript
    const { REACT_APP_PUBLIC_URI } = process.env;
    
    function AdventureDetail(props) {
        ...
        render() {
            <img className="Backbutton-icon" src={REACT_APP_PUBLIC_URI + '/' + backIcon} alt="Return" />
        }
    }
    

App.jsLoading.js および AdventureDetails.js ファイルは次のようになります。

静的リソース

AEM レスポンシブグリッド

SPA の編集可能な領域で SPA エディターのレイアウトモードをサポートするには、AEM のレスポンシブグリッド CSS を SPA に統合する必要があります。このグリッドシステムは編集可能なコンテナにのみに適用され、SPA のそれ以外の部分のレイアウトには任意のグリッドシステムを使用できるので、心配する必要はありません。

AEM レスポンシブグリッド SCSS ファイルを SPA に追加します。

  1. IDE で SPA プロジェクトを開きます。

  2. 次の 2 つのファイルをダウンロードして、src/styles にコピーします。

    • _grid.scss
      • AEM レスポンシブグリッド SCSS ジェネレーター
    • _grid-init.scss
      • SPA 固有のブレークポイント(デスクトップおよびモバイル)と列(12)を使用して、_grid.scss を呼び出します。
  3. src/App.scss を開いて、./styles/grid-init.scss を読み込みます。

    code language-scss
    ...
    @import './styles/grid-init';
    ...
    

_grid.scss および _grid-init.scss ファイルは次のようになります。

AEM レスポンシブグリッド SCSS

AEM コンテナに追加されたコンポーネントの AEM レイアウトモードをサポートするために必要な CSS が SPA に含まれるようになりました。

ユーティリティクラス

次のユーティリティクラスを React アプリプロジェクトにコピーします。

  • RoutedLink.js~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app/src/components/editable/core/RoutedLink.js
  • EditorPlaceholder.js~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app/src/components/editable/core/util/EditorPlaceholder.js
  • withConditionalPlaceholder.js~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app/src/components/editable/core/util/withConditionalPlaceholder.js
  • withStandardBaseCssClass.js~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app/src/components/editable/core/util/withStandardBaseCssClass.js

リモート SPA ユーティリティクラス

SPA の起動

これで、AEM との統合に向けた SPA のブートストラップが完了したので、SPA を実行して、どのように表示されるかを確認します。

  1. コマンドラインで、SPA プロジェクトのルートに移動します。

  2. 通常のコマンドを使用して SPA を起動します(まだ起動していない場合)。

    code language-shell
    $ cd ~/Code/aem-guides-wknd-graphql/remote-spa-tutorial/react-app
    $ npm install
    $ npm run start
    
  3. http://localhost:3000 で SPA を参照します。すべてがうまく表示されるはずです。

http://localhost:3000 で動作する SPA

AEM SPA エディターで SPA を開く

SPA が http://localhost:3000 で動作している状態で、AEM SPA エディターを使用して SPA を開きます。SPA ではまだ何も編集できません。AEM での SPA の動作を検証するだけです。

  1. AEM オーサーにログインします。

  2. Sites/WKND アプリ/米国/英語 ​に移動します。

  3. WKND アプリのホームページ ​を選択して「編集」をタップすると、SPA が表示されます。

    WKND アプリホームページの編集

  4. 右上のモード切り替えボタンを使用して「プレビュー」に切り替えます

  5. SPA の周りをクリックします

    http://localhost:3000 で実行される SPA

おめでとうございます。

AEM SPA エディターと互換性を持たせるために、リモート SPA でブートストラップを行います。次の方法を学習しました。

  • AEM SPA エディター JS SDK npm の依存関係を SPA プロジェクトに追加します
  • SPA の環境変数を設定します
  • ModelManager API と SPA を統合します
  • SPA の内部プロキシを設定して、適切なコンテンツリクエストを AEM にルーティングします
  • SPA エディターのコンテキストで解決される静的 SPA リソースの問題に対処します
  • AEM のレスポンシブグリッド CSS を追加して、AEM の編集可能なコンテナでのレイアウト処理をサポートします

次の手順

これで、AEM SPA エディターとの互換性のベースラインを達成したので、編集可能な領域の導入を開始できます。 まず、編集可能な固定コンポーネント を SPA に追加します。

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