Blogs
Single Page Applications with SennaJS and Liferay Faces
One of Liferay 7’s most exciting new features is SennaJS, a Single Page Application engine. SennaJS makes the portal more user-friendly in many ways. For example, when a link is clicked and navigation occurs, SennaJS requests the necessary portlet markup via XHR and renders it in the browser so that the whole portal page is not reloaded. As part of our latest release of Liferay Faces, we’ve added support for SennaJS so that JSF portlet developers can take advantage of this amazing feature.
How do I use SennaJS with Liferay Faces portlets?
Liferay Faces Bridge enables support for SennaJS in Liferay 7 by default. Utilizing SennaJS is as simple as using h:link
, h:outputLink
, or any other component which renders an <a>
tag.1 If the link navigates to another page in your portal, SennaJS will automatically handle the navigation and cause an XHR GET
which will load only the changed parts of the page. You can try this live in the Liferay Faces Showcase h:link
example by clicking the To Param page > link. Clicking the link causes an XHR GET
via SennaJS which is shown visually with a blue loading bar at the top of the page. You can compare this to a full-page GET
by changing the end of the URL from param
back to navigation
and hitting enter. The full-page navigation is not only slower, but it causes more blinking and changes on the page.
Disabling SennaJS
Although SennaJS improves the user experience, it may be unnecessary for (or, rarely, incompatible with) certain use cases. If your portlet requires that SennaJS be disabled, then simply add <single-page-application>false</single-page-application>
to the <portlet>
section of your liferay-portlet.xml
. You can also disable SennaJS on a portal-wide basis (by adding javascript.single.page.application.enabled=false
to your portal-ext.properties
file) or an element by element basis (Ex: <a data-senna-off="true">
).
Under The Hood: How Liferay Faces Integrates with SennaJS
The Liferay Faces team worked closely with Bruno Basto, a Liferay front-end engineer, and Eduardo Lundgren, one of the creators of SennaJS, to ensure that Liferay 7’s usage of SennaJS would be compatible with Liferay Faces. Fortunately, SennaJS and Liferay 7 were already working together elegantly before we attempted to add Liferay Faces to the mix. Liferay 7 required only a few minor tweaks to allow Liferay Faces to take advantage of SennaJS. Bruno Basto implemented these changes. Thanks to him, SennaJS avoids loading duplicate resources in the <head>
section by automatically tracking all CSS and JS resources and assuming that JS resources should not be unloaded.2,3
Since SennaJS is enabled by default in Liferay 7, the Liferay Faces team only needed to disable it for JSF components which were incompatible with its features. SennaJS assumes all links cause navigation, and it uses an XHR to obtain the markup that would otherwise be obtained via a full-page GET
. Since JSF commandLink
components are intended to submit a form rather than simply navigate to another page, they must not invoke SennaJS’s functionality. Likewise, SennaJS automatically causes forms to submit via XHR. However this feature is not compatible with JSF, since JSF expects to be in total control of form submissions.4 In order to avoid these incompatibilities, we used the data-senna-off
attribute to disable SennaJS for all commandLink
s and form
s in Liferay 7.
With the minor changes listed above, Liferay Faces now allows JSF developers to enjoy the major benefits of SennaJS in Liferay 7!
- …with the exception of
commandLink
components. See the “Under the Hood” section for more details. ↵ - Even though SennaJS tracks all the JavaScript files that are loaded, there is no way for it to generically unload all the components from those files, so it assumes it should not unload a JS element. This has the beneficial side effect of not reloading the same JS multiple times when a user navigates from one page to another and back again with SennaJS. ↵
- All of these improvements benefit Liferay portlet developers who use JSP technology as well. ↵
- Of course, JSF has its own functionality for submitting forms via ajax. ↵