Starting with Eliom 6.0, services can have client-side handlers. Registering client-side handlers for services allows us to perform most of the operations (e.g., building the user interface) locally, and only call the server for operations that are by necessity non-local (e.g., retrieving database data).
Client-side service implementation is required for building mobile applications with Eliom, but can also be used to change page faster within a Web application. In this manual chapter, we focus on the client-side service mechanics and do not go into the details of setting up a complete mobile application. The complete setup needed is discussed in the mobile applications chapter of this manual.
Service creation and registering
The first step (creation) can only happen on the server; allowing the opposite would permit "creating" on the client services that are not actually provided by the server. To allow client-side service manipulation, services can be injected, as demonstrated by the following example:
let%server s = Eliom_service.create ~meth:(Eliom_service.Get Eliom_parameter.unit) ~path:(Eliom_service.Path ["content"]) () let%client s = ~%s
The above style makes the service available under the same identifier (here s) on both sides. Subsequently, the service can be registered on both sides with the same Eliom_registration APIs. For example:
let%shared () = Eliom_registration.Html.register s (fun () () -> Lwt.return (Eliom_tools.F.html ~title:"hybrid" Html.F.(body [ h1 [txt "Salut !"]; ])))
The types of the handlers are compatible between the two sides. For instance, Eliom_registration.Html expects a function that produces a Html_types.html Eliom_content.Html.D.elt Lwt.t, for Eliom_registration.Action we must return unit Lwt.t, and so on. The behavior of all services is compatible to the extent possible, e.g., actions perform a reload after performing their side effect.
For application services, the Eliom_registration.App functor needs to be called just like on the server. The signatures are compatible between the two sides, and therefore the functor invocation can happen in a shared section.
A service registered as above can be called via links (e.g., Eliom_content.Html.D.a) and forms just like a standard server-only service. Eliom detects the existence of a client-side implementation and calls that instead of performing a request to the server. If no client-side implementation exists, a standard server request is performed, which may cause problems in the context of mobile applications.
Service routing is the operation of choosing a service based on a URL and a collection of POST parameters. This is clearly a key operation on the server, allowing Eliom to respond on different paths. Routing has also become available on the client via the function Eliom_client.change_page_uri. This function can be used for example in order to open a link inside a mobile application without launching the Web browser.