この記事では、Liferay Single-Page Application (SPA)を扱う上で理解しておくべき重要な概念を紹介し、文書化します。 詳しくは Senna.jsドキュメント をご覧ください。
シングルページ出願
レイテンシー 、控えめな改善であっても、利用状況に測定可能な影響を与えることができます。 最も分かりやすい指標はロードタイムです。 これは、多くの要因によって影響されます:DNSルックアップ、ネットワーク速度、ページが表示されるまでに読み込む必要のあるリソース(スタイルシート、javascript、画像、フォントなど)、などです。
サイトでは、スタイルシートの最適化と最小化、画像の1つのスプライトへの統合、javascriptの読み込みの遅延、CDNからの静的ファイルの提供などがよく行われます。 全ては読み込み時間を短縮するためです。 しかし、キャッシュされたリソースがあっても、ブラウザはページロードのたびにCSSやJSを再パースして実行しなければならず、HTMLをレイアウトしてUIを再描画しなければならない。 このため、実際のナビゲーションが遅くなるのはもちろん、知覚的な遅さも加わり、しばしばホワイトフラッシュが発生することがあります。
ティム・バーナーズ・リーがウェブを発明したとき、彼はハイパーリンクと静的ページのみで、科学文書を遠隔地から公開するシステムを探していた。 ウェブアプリの作成は、静的なウェブ生まれのルールばかりで非常に時間がかかることがあります。 実際のレイテンシーと知覚されるレイテンシーを改善するために、多くのサイト がSPAモデルに移行しています。 つまり、最初のページがロードされると、それ以降のナビゲーションはすべて、ページの再ロードなしに処理されます。 追加コンテンツの読み込みには、 XMLHttpRequest
を使用し、 History API, を経由します。ページを更新することなくURLを更新できるため、ダイナミックサイトの共有やブックマークが可能です。 ページの状態ごとにURLを持つことで、コンテンツを検索エンジンに完全にクロールさせることができます。
機能
LiferayプラットフォームのGUIは、 AlloyUI toolkitの上に構築されています。 Liferayは、Liferayポータルにシングルページアプリケーション体験をもたらすために何かをする必要がありました。そして、AlloyUI Surfaceモジュールが誕生しました。これは、最新のWebベースアプリケーションを構築できるいくつかの低レベルAPIを提供する、非常に高速なシングルページアプリケーションエンジンです。
このモジュールは非常に有用であり、ゲームを変えるものであることがわかったため、AlloyUIから分離してスピンオフプロジェクトである Sennaを立ち上げました。
知覚遅延が少なく、ユーザーエクスペリエンスの良いシングルページアプリケーションを作成するためには、SPAエンジンは、例えば、多くの側面でネイティブブラウザの動作を処理する必要があります:
- SEO & ブックマーク性: リンクの共有やブックマークは、常に同じ内容を表示する必要があります。 友達にリンクを送ると、私たちがいた場所に来てくれるはずです。 それ以上に、検索エンジンがその同じコンテンツをインデックスすることができるようになります。
- ハイブリッドレンダリング: Ajax+サーバーサイドレンダリングにより、いつでもpushStateを無効にすることができ、プログレッシブエンハンスメントが可能です。 サーバーサイドのレンダリング方法は問題ではなく、単純なHTMLフラグメントでも、テンプレートビューでもかまいません。
- 状態の保持: スクロール、再読み込み、またはページの履歴をナビゲートすると、元あった場所に戻るようにします。
- UI フィードバック: 何らかのコンテンツが要求されたとき、ユーザーに何かが起こっていることを示す。
- 保留中のナビゲート: データが読み込まれるまでUIレンダリングをブロックし、コンテンツを一度に表示する。 ローディング中にUXのフィードバックをすることが重要です。
- タイムアウトの検出: リクエストの読み込みに時間がかかりすぎる場合や、他のリクエストが保留されている間に別のリンクに移動した場合にタイムアウトする。
- 履歴のナビゲーション: History APIを使用すると、ブラウザの履歴を操作できるため、ブラウザの戻る & 進むボタンを使用できます。
- キャッシュ可能な画面: ある画面を読み込むと、このコンテンツはメモリにキャッシュされ、後で追加のリクエストなしに取り出されます。 これにより、アプリケーションを大幅に高速化することができます。
- ページリソースの管理: ダイナミックに読み込まれたリソースからスクリプトやスタイルシートを評価する。 XMLHttpRequestを使用して読み込んだコンテンツをDOMに追加することができます。セキュリティ上の理由から、一部のブラウザは新しいフラグメントから <script> タグを評価しません。 したがって、SPAエンジンは、コンテンツからスクリプトを抽出し、スクリプトを読み込むためのブラウザの契約を尊重しながら、スクリプトを解析する処理を行う必要があります。
優れたSPAに必要な機能のリストが膨大であるだけでなく、現時点では、History APIは多くのクロスブラウザの不整合をもたらし、SPAエンジンなしで扱うにはかなり複雑になる可能性があります。
デスクトップ
SPAのニーズを容易にするために、Liferayはデスクトップという概念を生み出しました。
デスクトップナビゲーションが有効になっている場合、他のポートレットの中にないネストされたポートレットはすべてデスクトップを作成し、グリッド/テンプレートのようにページといくつかの側面を共有します。
ルート、スクリーン、サーフェス
- ルート:パスとルートハンドラ関数のタプル。
- スクリーンです:与えられた経路のルーティングを処理するクラスで、A.Screenを継承しています。
- 表面:ナビゲーションで更新されるページの部分。
Liferay SPAには、RenderURLScreenのように、Liferayポートレットのロジックを抽象化したり処理したりする画面が用意されています。 これらは通常、HTMLScreenの上に構築されます。HTMLScreenは、Ajaxを使用してサーバーサイドのリクエストにルートを解決する画面です(利用できる場合は、キャッシュから)。
例
1.) ルートを追加する
Surface.app.addScreenRoutes({ path: /\?section=/, screen: Liferay.Surface.RenderURLScreen });
Liferay.Surface.app
が作成された後にロードされることを考えると、画面ルートはどこにでも追加することが可能です。 何らかの理由で、スクリーンルートが特定のテーマでのみ使用される場合、テーマのYUIロードモジュールとしてiiを追加するのは良いアイデアかもしれません。 そうでなければ、adidas-web hook YUI-loadedモジュールとして追加する方が適切です。
2.) キャッシュのないHTMLScreen
スクリーンを作るのに最も簡単な方法は、既存のスクリーンを拡張することだったりします。
Surface.CachelessHTMLScreen = A.Component.create({ ATTRS: { cacheable: { value: false } }, EXTENDS: Surface.HTMLScreen, NAME: 'cachelessHTMLScreen' });
100%クライアントサイドで経路を解決する画面:
Surface.QueryStringScreen = Y.Base.create('queryStringScreen', A.Screen, [], { getSurfaceContent: function(surfaceId) { switch (surfaceId) { case 'header': return 'querystring1'; case 'body': return 'querystring2'; } } });
ヒント:Surfaceの内部構造を理解し、より多くの例を見るには、Surfaceのテストをガイドとして使用してください。
3.) 表面
サーフェスは、画面がルートを解決するたびに更新される領域です。 上の例では、ヘッダー画面とボディ画面を更新しています。
のようにidベースで契約します。
<div id="header"> <div id="header-defaultScreen"> Something else. </div> </div> <p>This won't change.</p> <div id="body"> <div id="body-defaultScreen"> Something else. </div> </div>
ナビゲーションが発生すると、コンテンツはヘッダーが querystring1
に、ボディーの div が querystring2
に置き換えられます。
Liferay SPA が更新するためには、オリジナルのコンテンツを id <parent>-defaultScreen を持つ内側の div の中に包む必要があります。 AlloyUIの場合、本来は <parent>-defaultのみです。
ポートレットのSPAを有効にすると、自動的にサーフェスが作成されるので、自分でサーフェスを追加する必要はありません。
SPAエンジンでファイルをアップロードする
ファイルをアップロードするためには、Multipartフォームデータが必要です。 LiferaySurfaceFormScreen
を webs/adidas-web/docroot/custom_jsps/html/js/liferay/surface_form.js
で追加しました。 これは、Liferayのフォームですぐに動作する特別なサーフェス画面です。
適切であれば、その後にキャッシュの無効化を使用することを忘れないでください。
注:ユーザーエクスペリエンスの低下を覚悟で、サーフェスフォーム送信後に常にキャッシュを無効化することを決定することもできます。 その場合は、Liferay.Form の _defaultSubmitFn
メソッド( webs/adidas-web/docroot/custom_jsps/html/js/liferay/form.js
のフックを参照)で移動する直前にキャッシュ無効化メソッドを呼び出してください。
キャッシュの無効化
状況によっては、ユーザーが新鮮なコンテンツを読み込むことを保証するために、キャッシュを無効化することが重要な場合があります。 Liferay.Surface.clearCache()
このような変更後にナビゲートする前に呼び出してください。 作成 / 更新 / 削除 のほとんどのアクションで、これが必要になります。
他のSPAエンジンとの互換性
Liferay SPAは、同時に使用されている他のSPAエンジンと干渉しないように設計されています。 エンジンによってルートが設定されていない場合は、何もしません。 しかし、開発を容易にし、一貫性を高めるために、Liferay SPAの一貫使用を推奨します。
テンプレート
テンプレートは、ページ、ネストしたポートレット、デスクトップ内で使用できるグリッドシステムです。 いくつかのテンプレートは、Liferayポータルの一部としてデフォルトで利用可能です。 その他はプラグインとしてインストールすることができます。
新規に作成する場合:
- プラグインリポジトリの
layouttpl
ディレクトリにcdします。 ./create.sh hello-world "Hello World"
- open new generated
hello-world-layouttpl/docroot
dir -
hello_world.png
という120x120のアイコンを作成し、テンプレートのサムネイルを表示する。 -
docroot/hello-world.tpl
ファイルを編集します。 -
docroot/hellow-rold.wap.tp
l に変更をコピーします。 - テンプレートを
で展開する ant
をそのルートディレクトリに展開する
ヒント:既存のテンプレートをベースとして使用します。
デスクトップとSPAの有効化
アディダスウェブ
デスクトップとSPAを有効にするには、ポータルをフックするためのadidas-web web pluginをインストールします。
cd liferay-plugins-ee/webs/adidas-web
ant deploy
desktop.navigation.enabled
と javascript.single.page.application.enabled
のキーは、SPAエンジンとデスクトップのアクティブ状態を制御します。 webs/adidas-web/docroot/WEB-INF/src/portal.properties
に掲載されています。
テーマ
デスクトップサポートで新しいテーマを作成する
cd liferay-plugins-ee/themes
`./create.sh hello-world "Hello World"
-
javascript.single.page.desktop.navigation.enabled=true
を<theme>/docroot/WEB-INF/cl/portal.properties
に追加し、フリーフォームテンプレートwithnested.portlets.layout.template.unsupported=freeform
を無効化します。 -
<theme>/docroot/WEB-INF/liferay-look-and-feel.xml
で以下のようにデスクトップナビゲーションを有効にしてください:
<?xml version="1.0"?> <!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 6.2.0//EN" "http://www.liferay.com/dtd/liferay-look-and-feel_6_2_0.dtd"> <look-and-feel> <compatibility> <version>6.2.0+</version> </compatibility> <theme id="adidas" name="Adidas"> <settings> <setting key="desktop.navigation.enabled" value="true" /> </settings> <color-scheme id="01" name="Basic"> <default-cs>true</default-cs> <css-class>adidas-basic</css-class> </color-scheme> <color-scheme id="02" name="NavigationMenu"> <css-class>adidas-navigation</css-class> </color-scheme> </theme> </look-and-feel>
ポートレット
SPAに対応させるためには、ポートレットの <portlet>/docroot/WEB-INF/portlet.xml
に init-param
を追加する必要があります。 必要なルーティングやスクリーンを追加することも忘れずに。
<name>single-page-application-enabled</name> <value>true</value> </init-param>
追加情報
- Liferayのマイグレーション
- Senna (SPAの仕組みを理解する上で、デモがとても役に立ちます。)
- Java Portlet Specification 2.0 (JSR 286)を理解する。