New release: Ocsigen Start 2.18
Ocsigen Start is a template for client-server Web and/or mobile app in OCaml or ReasonML. It contains many standard features like user management, notifications, and many code examples. Use it to learn Web/mobile development in OCaml or as a basis for your app.
Last features include:
See live examples here:
New release: Ocsigen Toolkit 2.7
Ocsigen Toolkit is a widget toolkit for developing mobile and Web apps with js_of_ocaml. It is designed to take advantage of Eliom’s multi-tier programming paradigm. All widgets can be created either on server or client side.
This version introduces a new widget: Ot_tongue. It is a swipable panel, coming from the bottom of the screen (or from another side). Try it online with a mobile phone in Ocsigen Start’s demo or on the app Mon club près de chez moi.
You can also test it on mobile apps:
New release: Ocsigen Start 2.15
Ocsigen Start is a template for client-server Web and/or mobile app in OCaml or ReasonML. It contains many standard features like user management, notifications, and many code examples. Use it to learn Web/mobile development in OCaml or to quickly create your own Minimum Viable Product. See an online demo.
Last features include:
New releases:
Ocsigen Start is a template for client-server Web and/or mobile app in OCaml or ReasonML. It contains many standard features like user management, notifications, and many code examples. Use it to learn Web/mobile development in OCaml or to quickly create your own Minimum Viable Product. See an online demo.
Last features include:
Ocsigen Server is a full featured Web Server.
Last features include:
Graffiti tutorial explains step by step how to write a multi-user client-server drawing application with Eliom.
It is the best starting point for beginners!
An updated version of this tutorial is now online, thanks to corentinjuvigny and chrismamo1.
The Ocsigen team is very happy to announce the first release of two major new projects:
Ocsigen Start: a Web/mobile application skeleton written with Js_of_ocaml and Eliom. You can use this skeleton as a basis for your own app, or to learn Web/mobile app development in OCaml.
Ocsigen Toolkit: a set of responsive widgets for your mobile and Web applications in OCaml.
Both projects are available via OPAM and released under the LGPL.
Before installing, you can try out a demo of Ocsigen Start. The demo is available
Ocsigen Start provides the basic features for user management (registration, activation links, password recovery, etc.), and some useful libraries. Remove the parts you don’t need for your own app.
Ocsigen Start also contains many examples of code: remote procedure calls, push notifications from the server, reactive pages, database interaction, session data, internationalization, and some widgets from Ocsigen Toolkit.
Ocsigen Toolkit contains common widgets for mobile and Web apps, written natively in OCaml and specifically designed for Eliom’s multi-tier and multi-platform programming style. You can also use them in client-only Js_of_ocaml programs. Many new widgets will be added in future versions.
Ocsigen Start and Ocsigen Toolkit are developed by the Ocsigen team at Be Sport, at the Paris Diderot University, and at the IRILL.
The Eliom framework is the part of the ocsigen project that aims to provide high level libraries for developing client/server web applications. It contains a language extension of OCaml that allows implementing both the client and the server parts of your application as a single program. It also contains several libraries and utilities to facilitate web programming.
The various Ocsigen libraries have received a lot of care lately. Notably, we have reworked the service API, we have added support for mobile applications and, we have developed ocsigen-start.
Today, I will not talk about the ocsigen libraries. I will talk solely about the language extension.
The Eliom language extension extends OCaml with various annotations that allows specifying where things are to be defined and executed.
The semantics is that the server part is executed first, then the web page is sent to the client, then the client part is executed. See the documentation for detail on the current extension.
The language extension is currently implemented using a PPX extension and a custom (and a bit sophisticated) compilation scheme. Note here that I used the word “language” extension on purpose: this is not a simple syntax extension, the Eliom language has its own type system, semantics and compilation scheme, which are extensions of the OCaml ones.
The current implementation of our language, based on PPX, started to show its limits in terms of flexibility, convenience and with respect to the safety guarantees it can provide. This is why I started, as part of my PhD thesis, to redesign and improve it.
Our first goal was to formalize the Eliom language as an extension of the OCaml language. Formalizing the language allowed us to better understand its type system and semantics, which led to various improvements and bug fixes. The formalization was published in APLAS 2016. In this paper, we present a (rather simple) type system based on two distinct type universes and the notion of converters, that allows passing values from the server to the client. We also show that the intuitive semantics of Eliom, that server code is executed immediately and client code is executed later in the exact same order it was encountered, does correspond to the compilation scheme used to slice Eliom programs into a server program and a client program.
In the the current implementation, when passing
a server value of type Foo.t
to the client. It also has type Foo.t
,
but the type is now the one available on the client. The actual object
can also be transformed while passing the client/server boundary using
wrappers. Unfortunately, this API is very difficult to use, not
flexible and quite unsafe. Instead, we propose to use converters.
Converters can be though as a pair of function: a server serialization
function ty_server -> string
and a client deserialization function
string -> ty_client
(the actual implementation will be a bit different to make (de)serializer composable).
The correctness of a converter depends of course on the good behavior of these
two functions, but the language guarantees that they will be used together
properly and each sides will properly respect the types of the converter.
By using converters, we can provide a convenient programming model and make Eliom much easier to extend. We demonstrated this with multiple examples in another paper published in IFL 2016. Unfortunately, a proper implementation of converters is only possible with some form of ad-hoc polymorphism, which involve using modular implicits.
In order to actually implement all these new things, I started to work on an extension of the OCaml compiler capable of handling the Eliom language constructs. Working directly in the compiler has several advantages:
The current work-in-progress compiler is available in the repository ocsigen/ocaml-eliom. A minimal runtime, along with various associated tools are available in ocsigen/eliomlang. A (perpetually broken) playground containing an extremely bare-bone website using eliomlang without the complete framework is available in ocsigen/eliomlang-playground.
Finally, the work on using this new compiler to compile the Eliom framework can be followed via this pull-request.
A more in-depth presentation of the Eliom language can be found here. The APLAS paper is quite formal and is mostly aimed at people that want to really understand the minute details of the language. The IFL paper, on the other hand, should be accessible to most OCaml programmers (even those who don’t know Eliom) and demonstrates how to use the new Eliom constructs to build nice, tierless and typesafe libraries for client/server web programming.
The work on the Eliom language is far from done. A current area of work is to extend the OCaml module language to be aware of the Eliom annotations. A particularly delicate (but promising!) area is the ability to use Eliom annotations inside functors. A second area of work is that of stabilizing, debugging and documenting the patched compiler. Finally, a difficulty raised by this new compiler is that existing build systems, and in particular ocamlbuild, do not handle the Eliom compilation scheme very well. Some details on this can be found here.
I wish this progress report has awaken your appetite for well-typed and modular tierless programming in OCaml. I hope I will be able to share more news in a few months.
Happy Eliom programming!
Lwt 2.7.0 was released today. This release aims to (1) improve communication between maintainers and users, and (2) prepare for (minor) breaking changes to some APIs in Lwt 3.0.0 (planned for April).
To this end:
[@deprecated]
), especially for upcoming breaking changes. This required dropping support for OCaml 4.01.If you are releasing a package to OPAM that depends on Lwt, it is not recommended to constrain Lwt to its current major version. A major release of Lwt will break only a few APIs, and your package is likely not to be affected – if it is, you will be notified. You may, however, wish to constrain Lwt to a major version in your private or production code.
lwt
is getting rid of some optional dependencies in 3.0.0, which are now installable through separate OPAM packages lwt_ssl
, lwt_glib
, lwt_react
. This is to reduce recompilation of Lwt when installing OPAM packages ssl
, lablgtk
, and react
.'a Lwt.t
are now called promises rather than threads. This should eliminate a lot of confusion for beginners.Lwt 2.7.0 also has a number of more ordinary changes, such as bug fixes
and the addition of bindings to writev
and readv
. See the full
changelog.
I am working on an all-new manual, including fully rewritten API documentation with examples. It should be ready towards the end of winter.
My hope is that all the above allows Lwt to be taken progressively into the future, at the same time making development more open and more humane.
Discuss on reddit!
We are very happy to announce the release of Ocsigen Eliom 6.0, which follows the recent releases of Ocsigen Server 2.8 and Ocsigen Js_of_ocaml 2.8.x.
New features include a friendlier service API that retains the expressive power of our service system. Additionally, Eliom can now be used to build cross-platform Web/mobile applications (Android, iOS, …).
Eliom is a framework for developing client/server web applications. Both the server and the client parts of the application are written in OCaml, as a single program. Communication between server and client is straightforward, e.g., one can just call a server-side function from client-side code.
Eliom makes extensive use of the OCaml language features. It provides advanced functionality like a powerful session mechanism and support for functional reactive Web pages.
Services are a key concept in Eliom, used for building the pages that are sent to the user, for accessing server-side data, for performing various actions, and so on. Eliom 6.0 provides a friendlier API for defining and registering services, thus making Eliom more approachable.
The new API makes extensive use of OCaml’s GADTs, and provides a single entry-point that supports most kinds of services (Eliom_service.create). For more information, refer to the Eliom manual.
Eliom 6.0 allows one to build applications for multiple mobile platforms (including iOS, Android, and Windows) with the same codebase as for a Web application, and following standard Eliom idioms.
To achieve this, we have made available the Eliom service APIs on the client. Thus, the user interface can be produced directly on the mobile device, with remote calls only when absolutely necessary.
To build an Eliom 6.0 mobile application easily, we recommend that you use our soon-to-be-released Ocsigen Start project, which provides a mobile-ready template application (walkthrough).
Eliom 6.0 supports the last 3 major versions of OCaml (4.02 up to 4.04). Additionally, Eliom is compatible with and builds on the latest Ocsigen releases, including Ocsigen Server 2.8, Js_of_ocaml 2.8.x, and TyXML 4.0.x.
The Ocsigen team is busy working on new features. Notably, we are developing an OCaml compiler specifically tuned for Eliom. Additionally, we are planning a transition to the Cohttp HTTP backend.
#ocsigen
on irc.freenode.net
It is with great pleasure that we are announcing the release of TyXML 4.0.0. The major features of this new release are a new PPX syntax extension that allows to use the standard HTML syntax and an improved user experience for both old and new TyXML users.
TyXML is a library for building statically correct HTML5 and SVG documents. It provides a set of combinators which use the OCaml type system to ensure the validity of the generated document. TyXML’s combinators can be used to build textual HTML and SVG, but also DOM trees or reactive interfaces, using Eliom and Js_of_ocaml.
A new TyXML manual is now available here. The documentation of the various TyXML modules was also improved. Do not hesitate to provide feedback via our bug tracker!
It is now possible to use the standard HTML syntax:
It supports insertion of OCaml code inside the HTML and can be used with all the TyXML modules (such as Js_of_ocaml and Eliom) and with SVG. A complete overview can be found in the manual.
This new PPX syntax extension leverages the (awesome) Markup.ml library and was contributed by Anton Bachin.
The HTML and SVG combinators have received numerous improvements to make them more consistent and easier to use. This means that several modules and functions have been renamed and some types have been changed, which breaks compatibility with previous TyXML versions.
A healthy amount of new elements and attributes.
The full changelog is available here.
This new version breaks compatibility. Compatible versions of js_of_ocaml
and Eliom are available in the respective master
branches.
A compatible js_of_ocaml
version should be released shortly™.
TyXML 4.0.0 is only available on OCaml >= 4.02.
While nothing is decided yet, some work has already started to enhance the syntax extension with type safe templating.
Happy HTML and SVG hacking!
This is the end of the tutorial about writing a collaborative Web drawing in OCaml. Have a look at the full tutorial if you haven’t read the first part or if you want a version with full colors and links.
In the last part, we’ve seen how to create a client-server Web application in OCaml. The server generates a Web page and sends it together with an OCaml program (compiled to JavaScript) to the browser.
We will now see how to draw on the canvas, program mouse events with Lwt, and do server to client communication on a bus.
We now want to draw something on the page using an HTML5 canvas. The
drawing primitive is defined in the client-side function called
draw
that just draws a line between two given points in a canvas.
To start our collaborative drawing application, we define another
client-side function init_client
, which just draws a single
line for now.
Here is the (full) new version of the program:
Here we use the function Js.string
from Js_of_ocaml’s library to convert an OCaml string
into a JS string.
What sounds a bit weird at first, is a very convenient practice for processing request in a client-server application: If a client value is created while processing a request, it will be evaluated on the client once it receives the response and the document is created; the corresponding side effects are then executed. For example, the line
creates a client value for the sole purpose of performing side
effects on the client. The client value can also be named (as
opposed to ignored via _
), thus enabling server-side
manipulation of client-side values (see below).
(Lwt, Mouse events with Lwt)
We now want to catch mouse events to draw lines with the mouse like
with the brush tools of any classical drawing application. One
solution would be to mimic typical JavaScript code in OCaml; for
example by using function Dom_events.listen
that is the Js_of_ocaml’s equivalent of
addEventListener
. However, this solution is at least as verbose
as the JavaScript equivalent, hence not satisfactory. Js_of_ocaml’s
library provides a much easier way to do that with the help of Lwt.
Replace the init_client
of the previous example by the
following piece of code, then compile and draw!
We use two references x
and y
to record the last mouse
position. The function set_coord
updates those references from
mouse event data. The function compute_line
computes the
coordinates of a line from the initial (old) coordinates to the new
coordinates–the event data sent as a parameter.
The last four lines of code implement the event-handling loop. They
can be read as follows: for each mousedown
event on the canvas,
do set_coord
, then line
(this will draw a dot), then
behave as the first
of the two following lines that terminates:
line
(never
terminates)line
.Functions in Eliom and Js_of_ocaml which do not implement just a
computation or direct side effect, but rather wait for user activity,
or file system access, or need a unforeseeable amount of time to return
are defined with Lwt; instead of returning a value of type a
they return an Lwt thread of type a Lwt.t
.
The only way to use the result of such functions (ones that return
values in the Lwt monad), is to use Lwt.bind
.
It is convenient to define an infix operator like this:
Then the code
is conceptually similar to
but only for functions returning a value in the Lwt monad.
For more clarity, there is a syntax extension for Lwt, defining
let%lwt
to be used instead of let
for Lwt functions:
Lwt.return
creates a terminated thread from a value: Lwt.return : 'a -> 'a Lwt.t
Use it when you must
return something in the Lwt monad (for example in a service handler,
or often after a Lwt.bind
).
An Eliom application is a cooperative program, as the server must be able to handle several requests at the same time. Ocsigen is using cooperative threading instead of the more widely used preemptive threading paradigm. It means that no scheduler will interrupt your functions whenever it wants. Switching from one thread to another is done only when there is a cooperation point.
We will use the term cooperative functions to identify functions
implemented in cooperative way, that is: if something takes
(potentially a long) time to complete (for example reading a value
from a database), they insert a cooperation point to let other threads
run. Cooperative functions return a value in the Lwt monad
(that is, a value of type 'a Lwt.t
for some type 'a
).
Lwt.bind
and Lwt.return
do not introduce cooperation points.
In our example, the function Lwt_js_events.mouseup
may introduce
a cooperation point, because it is unforeseeable when this event
happens. That’s why it returns a value in the Lwt monad.
Using cooperative threads has a huge advantage: given that you know precisely where the cooperation points are, you need very few mutexes and you have very low risk of deadlocks!
Using Lwt is very easy and does not cause trouble, provided you never use blocking functions (non-cooperative functions). Blocking functions can cause the entre server to hang! Remember:
Lwt_unix
instead of module
Unix
,Lwt_preemptive.detach
,Lwt_unix.yield
,Lwt.bind
does not introduce any cooperation point.The module Lwt_js_events
allows easily defining event listeners using Lwt. For example,
Lwt_js_events.click
takes a
DOM element and returns an Lwt thread that will wait until a click
occures on this element.
Functions with an ending “s” (Lwt_js_events.clicks
,
Lwt_js_events.mousedowns
, …) start again waiting after the
handler terminates.
Lwt.pick
behaves as the first thread
in the list to terminate, and cancels the others.
(Client server communication)
In order to see what other users are drawing, we now want to do the following:
We first declare a type, shared by the server and the client, describing the color (as RGB values) and coordinates of drawn lines.
We annotate the type declaration with [@@deriving json]
to allow
type-safe deserialization of this type. Eliom forces you to use this
in order to avoid server crashes if a client sends corrupted data.
This is defined using a JSON plugin for
ppx_deriving, which you
need to install. You need to do that for each type of data sent by the
client to the server. This annotation can only be added on types
containing exclusively basic types, or other types annotated with
[@@deriving json]
.
Then we create an Eliom bus to broadcast drawing events to all client
with the function Eliom_bus.create
.
This function take as parameter the type of
values carried by the bus.
To write draw commands into the bus, we just replace the function
line
in init_client
by:
Finally, to interpret the draw orders read on the bus, we add the
following line at the end of function init_client
:
Now you can try the program using two browser windows to see that the lines are drawn on both windows.
Eliom provides multiple ways for the server to send unsolicited data to the client:
Eliom_bus.t
are broadcasting channels where
client and server can participate (see also «a_api project=”eliom”
subproject=”client” | type Eliom_bus.t » in the client
API).Eliom_react
allows sending
React events from
the server to the client, and conversely.Eliom_comet.Channel.t
are one-way communication channels
allowing finer-grained control. It allows sending Lwt_stream
to the client.
Eliom_react
and Eliom_bus
are implemented over
Eliom_coment
.
It is possible to control the idle behaviour with module
Eliom_comet.Configuration
.
(Widgets with Ocsigen-widgets)
In this section, we add a color picker and slider to choose the size
of the brush. For the colorpicker we used a widget available in
Ocsigen-widgets
.
To install Ocsigen widgets, do:
opam pin add ocsigen-widgets https://github.com/ocsigen/ocsigen-widgets.git
opam install ocsigen-widgets
In Makefile.options
, created by Eliom’s distillery, add
ocsigen-widgets.client
to the
CLIENT_PACKAGES
:
CLIENT_PACKAGES := ... ocsigen-widgets.client
To create the widget, we add the following code in the
init_client
immediately after canvas configuration:
We subsequently add a simple HTML5 slider to change the size of the
brush. Near the canvas_elt
definition, simply add the following
code:
Form.int
is a typing information telling that this input takes
an integer value. This kind of input can only be associated to
services taking an integer as parameter.
We then add the slider to the page body, as follows:
To change the size and the color of the brush, we replace the last
line of the function compute_line
in init_client
by:
Finally, we need to add a stylesheet in the headers of our page. To
easily create the head
HTML element, we use the function
Eliom_tools.F.head
:
You need to install the corresponding stylesheets and images into your
project. The stylesheet files should go to the directory
static/css
.
File graffiti.css is a custom-made CSS file.
You can then test your application (make test.byte
).
Ocsigen-widgets is a Js_of_ocaml library providing useful widgets for your Eliom applications. You can use it for building complex user interfaces.
(Services sending other data types)
To finish the first part of the tutorial, we want to save the current drawing on server side and send the current image when a new user arrives. To do that, we will use the Cairo binding for OCaml.
For using Cairo, first, make sure that it is installed (it is
available as cairo2
via OPAM). Second, add it to the
SERVER_PACKAGES
in your Makefile.options
: SERVER_PACKAGES := ... cairo2
The draw_server
function below is the equivalent of the
draw
function on the server side and the image_string
function outputs the PNG image in a string.
We also define a service that sends the picture:
The module Eliom_registration
defines several modules with
registration functions for a variety of data types. We have already
seen Eliom_registration.Html5
and Eliom_registration.App
.
The module Eliom_registration.String
sends arbitrary byte output
(represented by an OCaml string). The handler function must return
a pair consisting of the content and the content-type.
There are also several other output modules, for example:
Eliom_registration.File
to send static filesEliom_registration.Redirection
to create a redirection towards another pageEliom_registration.Any
to create services that decide late what
they want to sendEliom_registration.Ocaml
to send any OCaml data to be used in a
client side programEliom_registration.Action
to create service with no output
(the handler function just performs a side effect on the server)
and reload the current page (or not). We will see an example of actions
in the next chapter.We now want to load the initial image once the canvas is created. Add the following lines just between the creation of the canvas context and the creation of the slider:
You are then ready to try your graffiti-application by
make test.byte
.
Note, that the Makefile
from the distillery automatically adds
the packages defined in SERVER_PACKAGES
as an extension in your
configuration file local/etc/graffiti/graffiti-test.conf
:
<extension findlib-package="cairo2" />
This post (and the following one) is a step by step tutorial about client-server Web applications in OCaml. You can find the full tutorial here. It introduces the basics of Web programming with OCaml: type-checking HTML, defining services, using lightweight threads, writing a client-server program …
We will write a collaborative drawing application. It is a client-server Web application displaying an area where users can draw using the mouse, and see what other users are drawing at the same time and in real-time.
The final eliom code is available for download on github. Git tag eliom-5.0 has been tested against Eliom 5.0.
The application is running online here.
To get started, we recommend using Eliom’s distillery, a program which creates scaffolds for Eliom projects. The following command creates a very simple project called graffiti in the directory graffiti:
$ eliom-distillery -name graffiti -template basic.ppx -target-directory graffiti
(Services, Configuration file, Static validation of HTML)
Our web application consists of a single page for now. Let’s start by creating a very basic page. We define the service that will implement this page by the following declaration:
If you are using eliom-distillery just replace the content of the eliom-file by the above lines and run
$ make test.byte
This will compile your application and run ocsigenserver on it. (Refer to the manual on how to compile your project “by hand”.)
Your page is now available at URL http://localhost:8080/graff
.
Unlike typical web programming techniques (CGI, PHP, …), with Eliom you do not need to write one file per URL. The application can be split into multiple files as per the developer’s style. What matters is that you eventually produce a single module (*.cmo or *.cma) for the whole website.
Module Eliom_service allows to create new entry points to your web site, called services. In general, services are attached to a URL and generate a web page. Services are represented by OCaml values, through which you must register a function that will generate a page.
Parameter ~path
corresponds to the URL where you want to attach your service. It is a list of strings. The value ["foo"; "bar"]
corresponds to URL foo/bar
. ["dir"; ""]
corresponds to URL dir/
(that is: the default page of the directory dir).
In the directory of the project created by the Eliom-distillery, you can find the file graffiti.conf.in
. This file is used in conjunction with the variables in Makefile.options to generate the ocsigenserver configuration file.
Once you start up your application via make test.byte
, the configuration file becomes available at local/etc/graffiti/graffiti-test.conf
. It contains various directives for Ocsigen server (port, log files, extensions to be loaded, etc.), taken from Makefile.options, and something like:
<host>
<static dir="static" />
<eliommodule module="/path_to/graffiti.cma" />
<eliom />
</host>
Line <eliommodule ... />
asks the server to load Eliom module
graffiti.cma
, containing the Eliom application, at startup and
attach it to this host (and site).
Extensions <static ... />
(staticmod) and <eliom />
are called successively:
/path_to/graffiti/static
will be served,<eliom />
),There are several ways to create pages for Eliom. You can generate pages as strings (as in other web frameworks). However, it is preferable to generate HTML in a way that provides compile-time HTML correctness guarantees. This tutorial achieves this by using module Eliom_content.Html5.D, which is implemented using the TyXML library. The module defines a construction function for each HTML5 tag.
Note that it is also possible to use the usual HTML syntax directly in OCaml.
The TyXML library (and thus Eliom_content.Html5.D) is very strict and compels you to respect HTML5 standard (with some limitations). For example if you write:
You will get an error message similar to the following, referring to the end of line 2:
Error: This expression has type ([> `PCDATA ] as 'a) Html5.elt
but an expression was expected of type
Html5_types.head_content_fun Html5.elt
Type 'a is not compatible with type Html5_types.head_content_fun =
[ `Base
| `Command
| `Link
| `Meta
| `Noscript of [ `Link | `Meta | `Style ]
| `Script
| `Style ]
The second variant type does not allow tag(s) `PCDATA
where Html5_types.head_content_fun
is the type of content allowed inside <head>
(<base>
, <command>
, <link>
, <meta>
, etc.). Notice that <PCDATA
(i.e. raw text) is not included in this polymorphic variant type.
Most functions take as parameter the list representing its contents. See other examples below. Each of them take un optional ?a
parameter for optional HTML attributes. Mandatory HTML attributes correspond to mandatory OCaml parameters. See below for examples.
Important warning: All the functions you write must be written in a cooperative manner using Lwt. Lwt is a convenient way to implement concurrent programs in OCaml, and is now also widely used for applications unrelated to Ocsigen.
For now we will just use the Lwt.return
function as above. We will come back to Lwt programming later. You can also have a look at the Lwt programming guide.
(Service sending an application, Client and server code, Compiling a web application with server and client parts, Calling JavaScript methods with Js_of_ocaml)
To create our first service, we used the function Eliom_registration.Html5.register_service, as all we wanted to do was return HTML5. But we actually want a service that corresponds to a full Eliom application with client and server parts. To do so, we need to create our own registration module by using the functor Eliom_registration.App
:
It is now possible to use My_app
for registering our main service
(now at URL /
):
We can now add some OCaml code to be executed by the browser. For this purpose, Eliom provides a syntax extension to distinguish between server and client code in the same file. We start by a very basic program, that will display a message to the user by calling the JavaScript function alert. Add the following lines to the program:
After running again make test.byte, and visiting http://localhost:8080/
, the browser will load the file graffiti.js
, and open an alert-box.
At the very toplevel of your source file (i.e. not inside modules or other server- /client-parts), you can use the following constructs to indicate which side the code should run on.
[%%client ... ]
: the list of enclosed definitions is client-only code (similarly for [%%server ... ]
). With [%%shared ... ]
, the code is used both on the server and client.let%client
, let%server
, let%shared
: same as above for a single definition.[%%client.start]
, [%%server.start]
, [%%shared.start]
: these set the default location for all definitions that follow, and which do not use the preceding constructs.If no location is specified, the code is assumed to be for the server.
The above constructs are implemented by means of PPX, OCaml’s new mechanism for implementing syntax extensions. See Ppx_eliom for details.
Client parts are executed once, when the client side process is launched. The client process is not restarted after each page change.
In the Makefile
created by the distillery, we automatically split the code into client and server parts, compile the server part as usual, and compile the client part to a JavaScript file using js_of_ocaml
.
Additionally, it is possible to create client values within the server code by the following quotation:
where typ
is the type of an expression expr
on the client. Note, that such a client value is abstract on the server, but becomes concrete, once it is sent to the client with the next request.
(typ
can be ommitted if it can be inferred from the usage of the client value in the server code.)
Client values are executed on the client after the service returns. You can use client values when a service wants to ask the client to run something, for example binding some event handler on some element produced by the service.
The client-side parts of the program are compiled to JavaScript by js_of_ocaml
. (Technically, js_of_ocaml
compiles OCaml bytecode to JavaScript.) It is easy to bind JavaScript libraries so that OCaml programs can call JavaScript functions. In the example, we are using the Dom_html module, which is a binding that allows the manipulation of an HTML page.
Js_of_ocaml is using a syntax extension to call JavaScript methods:
obj##m a b c
to call the method m
of object obj
with parameters a
, b
, c
,obj##.m
to get a property,obj##.m := e
to set a property, andnew%js constr a b c
to call a JavaScript constructor.More information can be found in the Js_of_ocaml manual, in the module Ppx_js.
(Executing client side code after loading a page, Sharing server side values, Converting an HTML value to a portion of page (a.k.a. Dom node), Manipulating HTML node ‘by reference’)
The client side process is not strictly separated from the server side. We can access some server variables from the client code. For instance:
Here, we are increasing the reference count each time the page is accessed. When the page is loaded and the document is in-place, the client program initializes the value inside [%client ... ]
, and thus triggers an alert window. More specifically, the variable c
, in the scope of the client value on the server is made available to the client value using the syntax extension ~%c
. In doing so, the server side value c
is displayed in a message box on the client.
###Injections: Using server side values in client code
Client side code can reference copies of server side values using syntax ~%variable
. Values sent that way are weakly type checked: the name of the client side type must match the server side one. If you define a type and want it to be available on both sides, declare it in [%%shared ... ]
. The Eliom manual provides more information on the Eliom’s syntax extension and its compilation process.
Note that the value of an injection into a [%%client ... ]
section is sent only once when starting the application in the browser, and not synced automatically later. In contrast, the values of injections into client values which are created during a request are sent alongside the next response.
In next tutorial, we will turn the program into a collaborative drawing application, and learn:
js_of_ocaml
,The impatient can find the full tutorial here.
This short tutorial is an example of client-server Eliom application. It gives an example of client-server widgets. You can find the original version of this tutorial (and many others) here.
It is probably a good starting point if you know OCaml well, and want to quickly learn how to write a client-server Eliom application with a short example and concise explanations. For more detailed explanations, see the “Graffiti” tutorial, or read the manuals.
The goal is to show that, unlike many JavaScript libraries that build their widgets programmatically (by instantiating classes or calling functions), Eliom enables server-side widget generation, before sending them to the client. Pages can thus be indexed by search engines.
This tutorial also shows that it is possible to use the same code to build the widget either on client or server side.
We choose a very simple widget, that could be the base for example for implementing a drop-down menu. It consists of several boxes with a title and a content. Clicking on the title opens or closes the content. Furthermore, it is possible to group some of the boxes together to make them behave like radio buttons: when you open one of them, the previously opened one is closed.
The following code defines a client-server Web application with only one service, registered at URL / (the root of the website).
The code also defines a client-side application (section [%%client ... ]
) that appends a client-side generated widget to the page. Section [%%shared ... ]
is compiled on both the server and client side programs. Alternatively, you can write let%client
, let%server
or let%shared
(default) to define values on client side, on server side, or on both sides.
To compile it, first create a project by calling
eliom-distillery -name ex -template basic.ppx
The name of the project must match the name given to the functor Eliom_registration.App
.
After you adapt the file ex.eliom
, you can compile by calling make, and run the server by calling make test.byte
. Download the CSS file and place it in directory static/css
. Then open a browser window and go to URL http://localhost:8080
.
Screenshot:
This section gives very quick explanations on the rest of the program. For more detailed explanations, see the tutorial for the graffiti app or the manual of each of the projects.
Ex_app
).##
is used to call a JS method from OCaml and ##.
to access a JS object field (See Js_of_ocaml’s documentation: Ppx_js).Lwt
is the concurrent library used to program threads on both client and server sides. The syntax let%lwt a = e1 in e2
allows waiting (without blocking the rest of the program) for an Lwt thread to terminate before continuing. e2
must ben a Lwt thread itself. Lwt.return
enables creating an already-terminated Lwt thread.Lwt_js_events
defines a convenient way to program interface events (mouse, keyboard, …). For example, Lwt_js_events.onload
is a Lwt thread that waits until the page is loaded. There are similar functions to wait for other events, e.g., for a click on an element of the page, or for a key press.To make the widget work, we must bind the click event. Replace function mywidget
by the following lines:
Lwt_js_events
. Function clicks
is used to bind a handler to clicks on a specific element.async
runs an Lwt
thread asynchronously (without waiting for its result).Lwt_js_events.clicks elt f
calls function f
for each mouseclick on element elt
.To_dom.of_element
, Js.string
and Js.to_bool
are conversion functions between OCaml values and JS values.The following version of the program shows how to generate the widget on server side, before sending it to the client.
The code is exactly the same, with the following modifications:
[%client (... : unit) ]
. This code will be executed by the client-side program when it receives the page. Note that you must give the type (here unit
), as the type inference for client values is currently very limited. The client section may refer to server side values, using the ~%x
syntax. These values will be serialized and sent to the client automatically with the page.If you make function mywidget
shared, it will be available both on server and client sides:
Screenshot:
To implement this, we record a client-side reference to a function for closing the currently opened window.
Now we want to enable several sets of widgets in the same page. A single reference no longer suffices. In the following version, the server-side program asks the client-side program to generate two different references, by calling function new_set
. This function returns what we call a client value. Client values are values of the client side program that can be manipulated on server side (but not evaluated). On server side, they have an abstract type.
Screenshot:
An important feature missing from this tutorial is the ability to call server functions from the client-side program (“server functions”). You can find a quick description of this in this mini HOWTO or in Eliom’s manual.
For many applications, you will need several services. By default, client-side Eliom programs do not stop when you follow a link or send a form. This enables combining rich client side features (playing music, animations, stateful applications …) with traditional Web interaction (links, forms, bookmarks, back button …). Eliom proposes several ways to identify services, either by the URL (and parameters), or by a session identifier (we call this kind of service a coservice). Eliom also allows creating new (co-)services dynamically, for example coservices depending on previous interaction with a user. More information on the service identification mechanism in Eliom’s manual.
Eliom also offers a rich session mechanism, with scopes (see Eliom’s manual).
Following last week release, I’m starting today a series of tutorials about the Ocsigen framework. For the impatient, most of these tutorials are already available on Ocsigen’s Web site.
In this first tutorial, we show how to use the Ocsigen framework (mainly Eliom) to write a lightweight Web site by generating pages using OCaml functions. Even though Eliom makes it possible to write complete client-server Web and mobile apps, you can still use Eliom even if you don’t need all these features (for example if you don’t want HTML type checking or client side features). Besides, this will allow you to extend your Web site in a full Web application if you need, later on. This tutorial is also a good overview of the basics of Eliom.
The following code shows how to create a service that answers requests at URL http://.../aaa/bbb
, by invoking an Ocaml function f
of type:
Function f
generates HTML as a string, taking as argument the list of URL parameters (GET parameters).
Eliom_paramer.any
means that the service takes any GET parameter.
We recommend to use the program eliom-distillery to generate a template for your application (a Makefile and a default configuration file for Ocsigen Server).
$ eliom-distillery -name mysite -template basic.ppx -target-directory mysite
Put the piece of code above in file mysite.eliom, compile and run the server by doing:
$ make test.byte
Your page is now available at URL http://localhost:8080/aaa/bbb.
If you dont want to use the Makefile provided by eliom-distillery, just replace mysite.eliom by a file mysite.ml, compile and run with
$ ocamlfind ocamlc -package eliom.server -thread -c mysite.ml
$ ocsigenserver -c mysite.conf
where mysite.conf
is adapted from local/etc/mysite/mysite-test.conf
by replacing mysite.cma
by your cmo.
Services using the POST HTTP method are created using the function Eliom_service.Http.post_service
. To create a service with POST parameters, first you must create a service without POST parameters, and then the service with POST parameters, with the first service as fallback. The fallback is used if the user comes back later without POST parameters, for example because he put a bookmark on this URL.
That is probably all you need for a very basic Web site in OCaml. But Ocsigen provides many tools to write more advanced Web sites and applications:
Instead of generating HTML in OCaml strings, we highly recommend to use
typed HTML. It is very easy to use, once you have learned the basics,
and helps a lot to efficiently write modular and valid HTML.
To do this, use module
Eliom_registration.Html5
instead of
Eliom_registration.Html_text
.
See this
tutorial
for more information, a comprehensive documentation
here,
and a more advanced manual
here.
Have a look at Eliom’s API documentation to see other kinds of services,
for example Eliom_registration.Redirection
to create HTTP redirections.
Eliom also has a way to typecheck forms and GET or POST parameters. By giving a description of the parameters your service expects, Eliom will check their presence automatically, and convert them for you to OCaml types. See this tutorial and this manual page.
Eliom also has other ways to identify services (besides just the PATH in the URL). For example Eliom can identify a service just by a parameter (whatever the path is). This is called non-attached coservices and this makes it possible for instance to have the same feature on every page (for example a connection service). See this tutorial and this manual page.
One of the main features of Eliom is the ability to write complete Web and mobile applications in OCaml. Annotations are used to separate the code to be executed server-side from the client code. Client functions are translated into Javascript using Ocsigen Js_of_ocaml. See this tutorial for a quick introduction, or this one for a more comprehensive one. You can also have a look at this manual page.
Another interesting feature of Eliom is its session model, that uses a very simple interface to record session data server-side. It is even possible to choose the scope of this data: either a browser, or a tab, or even a group of browsers (belonging for instance to a same user). See this section and the beginning of this manual page.
We suggest to continue your reading by one of these tutorials:
We are excited to announce the releases of
These releases are the result of many months of work by the Ocsigen team, and bring a range of improvements.
Eliom 5.0 comes with a PPX-based language (for OCaml 4.02.x). This follows our PPX extensions for js_of_ocaml and Lwt. The new syntax is more flexible than our previous Camlp4-based one, and we recommend it for new projects. Nevertheless, the Camlp4-based syntax remains available.
Recent versions of Eliom provided client-side support for (functional) reactive programming. Eliom 5.0 additionally supports “shared” (client-server) reactive programming, where the reactive signals have meaning both on the server and the client. This means that the initial version of the page is produced (on the server) with the same code that takes care of the dynamic updates (on the client).
The js_of_ocaml library provides additional bindings for established JavaScript APIs. This includes
A new JavaScript-specific table module is also available.
js_of_ocaml provides a new JSON plugin for ppx_deriving. This can be used for serializing OCaml data structures to JSON in a type-safe way. The plugin remains compatible with its Camlp4-based predecessor with respect to the serialization format.
In addition to providing various fixes, we have improved the performance of various Ocsigen components. Notably:
A range of patches related to request data result in measurably smaller size for the produced pages.
The js_of_ocaml compiler becomes faster via improvements in bytecode parsing.
reactiveData employs diffing to detect data structure changes, leading to more localized incremental updates.
The Ocsigen team always welcomes your feedback and contributions. Stay in touch via GitHub and our mailing list!
TodoMVC is a project which offers the same Todo application implemented using MV* concepts in most of the popular JavaScript MV* frameworks. One of the aims of TodoMVC is to enable a fair comparison between several frameworks, by providing implementations of the same application. A js_of_ocaml (JSOO) version is now available:
Our version is powered by the React
module for functional
reactive programming (FRP).
In this post, we outline the architecture of our implementation, with a particular emphasis on how it applies MVC and FRP concepts.
MVC, which stands for Model-View-Controller, is a software architecture very commonly used for implementing user interfaces. MVC divides an application into three components:
the Model manages the data, logic and rules of the application;
the Controller manages events from the view, and accordingly updates the model;
the View generates an output presentation (a web page for instance) based on the model data.
For the Todo application, we have three corresponding OCaml
modules. Model
mainly contains the task list and the new
task field value. It uses Deriving_Json
to convert
the data to JSON and vice versa, in order to be able to save and
restore the application state. This module is otherwise written with
basic OCaml code. Controller
produces new models
according to the actions it receives. Whenever a new model is built,
the model becomes the new reactive signal value. We will elaborate on
this point later. View
builds the HTML to display the
page. It receives as input the dynamic data from the model. The HTML
also contains the event management code needed to emit the
corresponding actions.
Besides these three MVC modules, the application uses three
helpers. Storage
contains the functions to read and write a string value in the browser
local storage. This module is used to save and restore the application
data in JSON
format. Action
contains all the actions available from the user
interface. ReactList
contains a single function to ease the creation of a reactive list via
the ReactiveData
library.
React is an OCaml module for functional reactive programming
(FRP). In our TodoMVC example, React
provides a way to
automatically refresh the view whenever a new model is built by the
controller. To achieve this goal, the application uses a reactive
signal which carries the model values (which vary over time). The
model value may initially be equal to the empty model. When
this value is modified by the controller, i.e., after a new model
has been generated, the view automatically refreshes its reactive
parts.
The following figure shows what happens when the user interacts with the application, e.g., by adding a new task, or by clicking on a checkbox to select a specific task:
the view sends the action to the controller;
the controller gets the current model from the reactive signal, and builds a new model accordingly to the action;
the controller sets this new model as the new reactive signal value;
the view reacts to the newly-available model (new signal value) and updates itself with the corresponding data.
We proceed to describe our implementation of the above scheme, with an emphasis on the reactive features.
The main function creates the reactive signal with an initial
(possibly empty) model. The m
value is of type Model.t
:
React.S.create
returns a tuple, the first part of which is a
primitive signal; the second part is a function used by the controller
to set a new model as the new signal value.
We first explain how the CSS style of a HTML node becomes
reactive. In the Todo application, the task list is
displayed in a <section>
HTML tag. The CSS style of this HTML node
must contain visibility: hidden;
if the tasks list is empty, and
visibility: visible;
otherwise (i.e., if the number of tasks is
greater than zero). The style attribute of this <section>
node must
therefore change according to the model content:
We use the Tyxml_js
module to safely build the HTML
code. The first thing to note is that we use the reactive R.Html5
submodule, not the plain Html5
submodule. The a_style
function
implements a reactive attribute; it expects a reactive signal as its
argument. Here we use React.S.map
, which has the signature ('a ->
'b) -> 'a React.signal -> 'b React.signal
. The first argument to
map
is the css_visibility
function:
As you can see, css_visibility
receives a model m
as its
argument. When wrapped by React.S.map
as above, css_visibility
operates on signals. The function returns the right style, depending
on whether the list of tasks is empty or not.
The second argument to React.S.map
is the value named r
, which is
the primitive signal. r
is the first value returned by the
React.S.create
function.
Each time the signal value gets updated by the controller, the
css_visibility
function is automatically called with the new signal
value (a new model) as its argument, and the style attribute is
automatically modified.
Reactive attributes alone would not suffice to build a user
interface. We also need a reactive list of child nodes. Such a list is
for example needed to display the task list. (The source code section
is the same as for the first
example.) It
is a list of <li>
nodes contained in a <ul>
node. We accordingly
have a reactive node, as follows:
As before, we use the R.Html5
module. This time we do not use
R.Html5
to build an attribute, but rather a (<ul>
) node. rl
contains the node’s children:
We create the reactive list via the helper module
ReactList. As for the previous example, we use
React.S.map
to build a reactive signal, r
being again the
primitive signal. The visible_tasks
function generates the <li>
elements from the task list, filtered by the current selected
visibility:
Following the same principle as for the reactive attribute, each time
the signal value gets updated by the controller, the <li>
nodes are
automatically refreshed.
You may have noticed that the code includes the following types:
These types are used whenever type annotations are required, e.g.,
for the update
function from the Controller
module:
Elm is a functional programming language dedicated to frontend web application development. Elm was designed by Evan Czaplicki. The language should feel familiar to OCaml programmers.
Our TodoMVC example is based on the Elm
implementation, which follows
the structure used in all Elm
programs: a
model, an update function, and a view. Like Elm, our example uses the
functional reactive programming style, enabled in our case by the
React
library and the reactive modules Tyxml_js.R
and
ReactiveData
.
The combination of OCaml, js_of_ocaml, and functional reactive programming provides a killer feature combination for building rich web clients. Additionally, OCaml static typing can provide compile-time HTML validity checking (via TyXML), thus increasing reliability.
We are happy to announce the releases of
We also welcome a new member in the ocsigen team, Vasilis Papavasileiou.
Key changes in the various releases:
PPX support for js_of_ocaml with OCaml >= 4.02.2. See documentation here.
This was also the occasion to introduce a new syntax for object literals, and to improve the Camlp4 syntax (w.r.t. to locations). Both syntaxes emit the same code, and are perfectly compatible.
Support for dynlink in js_of_ocaml.
Logging improvements in Eliom and Server, in particular on the client side.
A healthy amount of bugfixes.
The next releases will probably see major changes. The current plan is:
Replace Server’s internals with cohttp, as part of our move towards Mirage-compatible libraries. See here.
Shared_react, which allows to build reactive pages from server side. See here.
PPX for Eliom.
Support for async/core in js_of_ocaml.
Have fun with Ocsigen!
The Ocsigen project finally has a blog. We are planning to publish news from the wider Ocsigen community, tutorials, and more.
Ocsigen encompasses the building blocks that you need in order to efficiently develop Web applications in OCaml. Among other libraries and tools, Ocsigen provides:
js_of_ocaml, which is a compiler from OCaml to JavaScript;
Ocsigen Server, which is a web server implemented in OCaml;
Lwt, which is a cooperative thread library for OCaml;
TyXML, which is a library for generating valid HTML and SVG content; last but not least,
Eliom, which puts everything together to provide a modern language for developing web applications, with tight integration between client and server.
Happy hacking, and stay tuned!