Warning: Reason support is experimental. We are looking for beta-tester and contributors.

Quick Start

This guide walks you through creating your first js_of_ocaml application.

Installation

opam install js_of_ocaml js_of_ocaml-ppx

Project setup

Create a new directory and initialize a dune project:

mkdir hello_jsoo && cd hello_jsoo

Create the following files:

dune-project

(lang dune 3.0)

dune

(executable
 (name main)
 (modes js)
 (preprocess (pps js_of_ocaml-ppx)))

main.ml

open Js_of_ocaml

let () =
  let message = Js.string "Hello from OCaml!" in
  Dom_html.window##alert message

Build

dune build

This produces _build/default/main.bc.js.

Run in browser

Create an HTML file to load the JavaScript:

index.html

<!DOCTYPE html>
<html>
<head>
  <title>Hello js_of_ocaml</title>
</head>
<body>
  <script src="_build/default/main.bc.js"></script>
</body>
</html>

Open index.html in a browser. You should see an alert with "Hello from OCaml!".

Run in Node.js

node _build/default/main.bc.js

Note: alert is not available in Node.js. For Node.js, use:

let () = print_endline "Hello from OCaml!"

DOM manipulation example

Here's a more complete example that manipulates the DOM:

main.ml

open Js_of_ocaml

let create_button text onclick =
  let doc = Dom_html.document in
  let button = Dom_html.createButton doc in
  button##.textContent := Js.some (Js.string text);
  button##.onclick := Dom_html.handler (fun _ ->
    onclick ();
    Js._true);
  button

let () =
  let doc = Dom_html.document in
  let body = doc##.body in

  (* Create a counter display *)
  let counter = ref 0 in
  let display = Dom_html.createDiv doc in
  let update_display () =
    display##.textContent := Js.some (Js.string (string_of_int !counter))
  in
  update_display ();

  (* Create buttons *)
  let incr_btn = create_button "+" (fun () ->
    incr counter;
    update_display ()
  ) in
  let decr_btn = create_button "-" (fun () ->
    decr counter;
    update_display ()
  ) in

  (* Add to page *)
  Dom.appendChild body decr_btn;
  Dom.appendChild body display;
  Dom.appendChild body incr_btn

index.html

<!DOCTYPE html>
<html>
<head>
  <title>Counter</title>
  <style>
    button { font-size: 24px; margin: 10px; }
    div { font-size: 48px; display: inline-block; min-width: 100px; text-align: center; }
  </style>
</head>
<body>
  <script src="_build/default/main.bc.js"></script>
</body>
</html>

Development workflow

For faster iteration during development, use:

dune build -w

This watches for file changes and rebuilds automatically.

Next steps