jakartaee / faces

Jakarta Faces
Other
103 stars 55 forks source link

Discuss new client side synchronization #1588

Open nimo23 opened 2 years ago

nimo23 commented 2 years ago

Currently, JSF uses its client side javascript library to include or replace html-fragments (by ajax XmlHttpResponse). The XmlHttpResponse consists of xml-snippets with all its html-tags and values set by the server.

Would it be possible to have an improved version of that so that it is more like a client application? For example, replacing only the values in the html pages that are changed and leaving the rest (tags,..) unchanged. React (uses a vdom) or native WebComponents makes this diffing (between old and new "view state") in a more performant way (https://codeburst.io/a-night-experimenting-with-lit-html-585a8c69892a?gi=3b622d2fbc77). Maybe JSF can improve its client side (re-)rendering phase so that it can improve the overall performance of its html rendering by only changing what has been really changed?

tandraschko commented 2 years ago

stephan and me did something similar in the past: https://github.com/stephanrauh/BabbageFaces but its not worth adding it in this way

in general its quite complex as if the value changes, you also have e.g. to reinit the JS widget in PF

nimo23 commented 1 year ago

you also have e.g. to reinit the JS widget in PF

Yes, however. Maybe "faces api" could introduce a new synchronization contract to client libs like PF. I think https://github.com/jakartaee/faces/issues/1598#issuecomment-1047152803 would be a step in the right direction to allow synchronization behind the scenes (i.e. by Server-JSF->Client-JS->Client-HTML) instead of always rerendering the component tree on partial updates (which forces PF a reinit of its JS widgets).

For example: if faces is able to consume and produce json data (consisting of only the model data), then PF would consume this json and update the view by javascript. It's like a little REST (or graphQL) for JSF, i.e. JSF communicates through REST (or graphQL) with its clients or JSF has an intermediate layer (called REST or graphQL) which allows the clients to interacting through REST (or graphQL) to JSF.

I know, it's easier said than done, since JSF actually can't easily fully communicate by REST or graphQL (e.g. because of the "JSF life cycle"-contract - however, maybe some concepts of JSF should be reconsidered and possibly separated out in order to meet the future requirements of modern (html) client applications.

tandraschko commented 1 year ago

IMO it would be MUCH easier to e.g. partially use a PrimeVue DataTable inside your JSF view

PrimeFaces and any other component would need to implement a "render logic" 2 times on the server and client not sure if this is worth compared to PrimeVue

nimo23 commented 1 year ago

IMO it would be MUCH easier to e.g. partially use a PrimeVue DataTable inside your JSF view

Yes, today (with the current faces api), it would be much easier to use PrimeVue or any other client side framework. However, this issue is about how Faces API can be improved to compete with the todays client side frameworks or better: how the Faces API can be enhanced to work seamlessly in any client-side framework. I think, if Faces API sits on top (or makes use) of REST or GraphQl, then it can be leveraged to a higher level.

nimo23 commented 1 year ago

I come up with the following idea:

JSF can renew all of its "client-side synchronization" (which actually works by replacing HTML pieces within HTML pages) with the standardized WebComponents.

JSF can then be seen as an abstraction or a wrapper around WebComponents. For example, when we have this in JSF...:

<h:outputText value = "{user.name}" />
<h:commandButton value = "Update"="{bean.update}" />

... then JSF can use WebComponents to build these components on client side. On server side the tags are still the same as today (e.g. h:outputText), but on client side those tags are built by WebComponents. I think the benefits are clear (JSF can be used along PWA and the overall web page can be rerendered much faster (https://webcomponents.dev/blog/all-the-ways-to-make-a-web-component/).

For a more complex example, imagine the following use case:

PrimeFaces has complex components which interacts with JSF. If JSF built its client-side synchronization" with WebComponents, then PrimeFaces could built its whole components as WebComponents (by the way, actually PF has React and Vue implementation, however, both are not standardized, whereas WebComponents is). On server side the components lib is still the same to further allow the use of EL (e.g. #{bean.update}), but on client side those components are built by WebComponents - JSF uses the bridge to WebComponents to communicate with the server side.

BalusC commented 1 year ago

Technically speaking, you can achieve that by plugging in another RenderKit.