カスタム要素を使用したルートの使用
Liferay 7.4以降
カスタム要素クライアント拡張機能は、Liferayのフロントエンドインフラストラクチャを使用して、外部アプリケーションをLiferayプラットフォームに登録し、ウィジェットとしてレンダリングします。 複数のルートを含むアプリケーション (例: React Router) の場合、リモートアプリケーションプロパティを定義して、実行時にウィジェットに使用されるルートを決定できます。 これらのプロパティは、Liferayのリモートアプリケーションメニュー、またはデプロイ後のウィジェットの設定オプションからアプリケーションに設定することができます。
他のタイプのクライアント拡張機能と同様にカスタム要素や IFrame をデプロイすることは、Liferay 7.4 の ベータ機能 です。 このチュートリアルでは、カスタム要素リモートアプリケーションのデプロイ方法を通常とは異なる方法で説明していますが、今後のアップデートまではこの方法が推奨されます。
このチュートリアルでは、Liferay の create_custom_element.sh スクリプトを使用して基本的な React アプリケーションを作成します。このスクリプトは、次の 3 つのルートを持つサンプル アプリケーションを生成します。 hello-world、 hello-foo、 hello-bar。 アプリケーションをコンパイルし、 .js および .css ファイルをホストした後、アプリケーションを Liferay に登録し、ページウィジェットとしてデプロイします。 最後に、それぞれの代替ルートを使用するように設定します。

カスタム要素クライアント拡張機能は、構築方法、パッケージ化方法、ホスティング方法に関係なく、あらゆるテクノロジーを使用できます。 このチュートリアルでは、基本的なルーティング機能を備えたカスタム要素アプリケーションのサンプルのみを提供します。
create_custom_element.shを実行するには、Node.JS、NPM、YARNの最新バージョンが必要です。 先に進む前に、これらのツールがインストールされていることを確認してください。
Reactアプリケーションの作成、構築、およびホスティング
-
新しいLiferay DXP 7.4+コンテナを起動します。 コンテナの起動中に、次の手順に進むことができます。
docker run -it -m 8g -p 8080:8080 liferay/dxp:2026.q1.9-lts -
別のターミナルでこのコマンドを実行して、Reactアプリケーションを生成してください。
curl -Ls https://github.com/liferay/liferay-portal/raw/master/tools/create_custom_element.sh | bash -s j1v3-custom-element react -
アプリケーションが正常に作成されたことを確認します。
このスクリプトは、
j1v3-custom-elementという名前の新しい React アプリケーションを作成し、以下の要素を含みます。j1v3-custom-element ├── node_modules ├── README.md ├── package.json ├── public │ └── index.html ├── src │ ├── common │ │ ├── services │ │ │ └── liferay │ │ │ ├── api.js │ │ │ └── liferay.js │ │ └── styles │ │ ├── hello-world.scss │ │ ├── index.scss │ │ └── variables.scss │ ├── index.js │ └── routes │ ├── hello-bar │ │ └── pages │ │ └── HelloBar.js │ ├── hello-foo │ │ └── pages │ │ └── HelloFoo.js │ └── hello-world │ └── pages │ └── HelloWorld.js └── yarn.lock -
新しい
j1v3-custom-elementフォルダーに移動して、アプリケーションをビルドします。cd j1v3-custom-element糸ビルド -
ビルドが成功したことを確認し、アプリケーションの
.jsおよび.cssファイルを確認してください。最適化された本番環境ビルドを作成しています... コンパイルに成功しました。 gzip圧縮後のファイルサイズ: 43.51 kB build/static/js/main.114dde4a.js 121 B build/static/css/main.9877909d.css -
<、http://localhost:8080、>のいずれかの URL から、メールアドレス「test@liferay.com」とパスワード「test」を使用して Liferay にログインしてください。 プロンプトが表示されたら、パスワードを learn に変更してください。 -
サイトメニュー (
を開き、 コンテンツ & データを展開し、 ドキュメントとメディア に移動します。 -
追加 (
) をクリックし、 複数ファイルアップロード を選択します。 -
.jsおよび.cssファイルをアップロードエリアにドラッグアンドドロップしてください。
-
をクリックして公開 します。
これにより、ファイルがLiferayドキュメントライブラリに追加され、リモートアプリケーションを作成する際に使用する固有のWebDAV URLが割り当てられます。
このチュートリアルでは、デモンストレーション目的で、アプリケーションの静的リソースをLiferayのドキュメントライブラリに格納します。 本番環境では、アプリケーションのファイルは静的リソースのホスティングに最適化されたサーバーにホストする必要があります。
各ファイルのURLを表示するには、 情報 アイコン (
) をクリックし、一度に1つのファイルを選択します。 各ファイルの WebDAV URL をコピーして、次のステップで使用するために保存します。

例:
http://localhost:8080/webdav/guest/document_library/main.114dde4a.jshttp://localhost:8080/webdav/guest/document_library/main.9877909d.css
アプリケーションの登録と展開
-
グローバルメニュー (
を開き、 アプリケーション タブをクリックし、 リモートアプリ に移動します。 -
をクリックして (
を追加)します。 -
次の値を入力します。
分野 価値 名前 J1V3カスタム要素 タイプ カスタム要素 HTML要素名 j1v3カスタム要素URL .jsファイルの WebDAV URLCSS URL .cssファイルの WebDAV URLインスタンス化可能 ✔ ポートレットカテゴリ名 リモートアプリ -
をクリックして保存します。
保存すると、LiferayはJ1V3-Custom-Elementという名前のウィジェットを作成し、他のページウィジェットと同様にサイトページにデプロイすることができます。 選択したポートレットカテゴリ名の下に表示されます。
J1V3-Custom-Elementはインスタンス化可能なので、1つのページに多数追加し、それぞれを独立した構成にすることが可能です。 この例では、1つのページに2回ウィジェットを追加します.

ルート プロパティを使用する
自動生成されたアプリには、3つのルートが含まれています。 hello-world、hello-foo、hello-barです。 デフォルトでは、アプリケーションは hello-world のルートを使用します。 ただし、リモートアプリケーションのプロパティを使用して、別のルートを使用するように設定することができます。 これらのプロパティは、リモートアプリケーションまたは ウィジェットの設定オプションで設定することが可能です。
リモートアプリメニューからルートプロパティを定義する
-
グローバルメニュー (
を開き、 アプリケーション タブをクリックし、 リモートアプリ に移動します。 -
J1V3-Custom-Element を選択します。

-
プロパティフィールドに
route=hello-fooと入力します。
-
をクリックして公開 します。
-
デプロイされた両方のウィジェットが
HelloFooルートを使用していることを確認してください。
ウィジェット設定によるルートプロパティの定義
-
J1V3-Custom-Elementウィジェットを含むページを編集します。
-
ウィジェットヘッダーの オプション (
) をクリックし、 設定 をクリックします。
注記Liferay DXP 2025.Q1/Portal GA132より前は、設定オプションはウィジェットの右上隅に表示されていました。
-
プロパティフィールドに
route=hello-barと入力します。
-
をクリックして保存します。
-
設定済みのウィジェットが
hello-barルートを使用している一方で、もう一方のウィジェットは依然としてhello-fooルートを使用していることを確認します。
ルートコードの分析
import React from 'react';
import {createRoot} from 'react-dom/client';
import api from './common/services/liferay/api';
import {Liferay} from './common/services/liferay/liferay';
import HelloBar from './routes/hello-bar/pages/HelloBar';
import HelloFoo from './routes/hello-foo/pages/HelloFoo';
import HelloWorld from './routes/hello-world/pages/HelloWorld';
import './common/styles/index.scss';
const App = ({route}) => {
if (route === 'hello-bar') {
return <HelloBar />;
}
if (route === 'hello-foo') {
return <HelloFoo />;
}
return (
<div>
<HelloWorld />
</div>
);
};
class WebComponent extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
createRoot(this).render(
<App
route={this.getAttribute('route')}
/>,
this
);
if (Liferay.ThemeDisplay.isSignedIn()) {
api('o/headless-admin-user/v1.0/my-user-account')
.then((response) => response.json())
.then((response) => {
if (response.givenName) {
const nameElements = document.getElementsByClassName(
'hello-world-name'
);
if (nameElements.length) {
nameElements[0].innerHTML = response.givenName;
}
}
});
}
}
}
const ELEMENT_ID = 'j1v3-custom-element';
if (!customElements.get(ELEMENT_ID)) {
customElements.define(ELEMENT_ID, WebComponent);
}
このindex.jsファイルはWebComponentクラスを作成し、HTMLElementインターフェイスを拡張します。 このクラスは、インターフェースのconnectedCallback()関数を実装し、AppをパラメータとしてReactDOM.renderに呼び出します。 アプリ が呼び出されると、定義されている "ルート" 属性をチェックし、その値を使用可能なルートと比較します。 hello-fooまたはhello-barのいずれかにマッチする場合、該当するルートを返して描画します。 そうでない場合は、hello-worldを返して描画します。
各ルートは、routesフォルダーからindex.jsファイルにインポートされます。
routes
├── hello-bar
│ └── pages
│ └── HelloBar.js
├── hello-foo
│ └── pages
│ └── HelloFoo.js
└── hello-world
└── pages
└── HelloWorld.js
HelloWorld.js
const HelloWorld = () => (
<div className="hello-world">
<h1>
Hello <span className="hello-world-name">World</span>
</h1>
</div>
);
HelloFoo.js
const HelloFoo = () => (
<div className="hello-foo">
<h1>Hello Foo</h1>
</div>
);
HelloBar.js
const HelloBar = () => (
<div className="hello-bar">
<h1>Hello Bar</h1>
</div>
);