# What is the current state of OCaml-ish in the browser?

**URL:** https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284
**Category:** Learning
**Created:** [February 1, 2023, 1:40am UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284 "2023-02-01T01:40:39Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![zeroexcuses](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zeroexcuses/32/1692_2.png) [@zeroexcuses](https://discuss.ocaml.org/u/zeroexcuses)
#### Post date: [February 1, 2023, 1:40am UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/1 "2023-02-01T01:40:39Z")

</div>

My current understanding is:

js\_of\_ocaml: OCaml → bytecode → js  
Reason: OCaml w/ syntax changes → bytecode → js (via js\_of\_ocaml)  
ReScript: new language, similar to OCaml; compiler written in OCaml, does \*.res → js directly

In particular we have:

js\_of\_ocaml, Reason: use OCaml compiler to get OCaml bytecode, convert bytecode to js

ReScript: reason → JS directly (and thus more readable JS)

Does this cover the higher order bits? If I got anything wrong / am missing anything, please let me know. Main interest is running OCaml in the browser, as TypeScript’s type system is a bit frustrating to use.

---

<div class="post-metadata">

### Author: ![jeffsco](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeffsco/32/45_2.png) [@jeffsco](https://discuss.ocaml.org/u/jeffsco)
#### Post date: [February 1, 2023, 4:22am UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/2 "2023-02-01T04:22:40Z")

</div>

I stopped using ReScript because they didn’t seem to be supporting the original OCaml syntax (which I like) very well if at all.

I haven’t tried it out, but I hear that Melange ([GitHub - melange-re/melange: A mixture of tooling combined to produce JavaScript from OCaml & Reason](https://github.com/melange-re/melange)) is a fork of the old Bucklescript project that’s staying closer to OCaml than ReScript. Not sure exactly what that means.

I’ve been using Js\_of\_ocaml for a few months and it seems very good. After thinking about it a few years I realized I don’t really care about the readability of the generated JavaScript! I never look at it.

---

<div class="post-metadata">

### Author: ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)
#### Post date: [February 1, 2023, 5:52am UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/3 "2023-02-01T05:52:33Z")

</div>

ReScript is not just a new compiler written in OCaml. It’s a modified version of the OCaml compiler, which takes a higher-level IR and transforms it into JavaScript. In particular, it has pretty much exactly the same type system as OCaml. The adjustments it makes are all intended to allow a better fit in the JS platform.

One of the most significant innovations of BuckleScript and hence ReScript, in my opinion, is managing to ship a complete toolchain that works out of the box for every major platform including Windows, with no Cygwin/MSYS/WSL/etc. hacks needed.

---

<div class="post-metadata">

### Author: ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)
#### Post date: [February 1, 2023, 11:27am UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/4 "2023-02-01T11:27:30Z")

</div>

> [@jeffsco](#):
>
> I don’t really care about the readability of the generated JavaScript! I never look at it.

There is one virtue to producing readable JS that’s often overlooked I feel, probably because it’s hard to empirically measure, but readable JS is more amenable to minifiers, treeshakers, produces smaller and faster artifacts overall. That has been my experience anyway, could just be correlation.

One less debatable virtue is that you can just inspect the JS code to see how you’ll interop with it, or to debug it.

> [@yawaramin](#):
>
> One of the most significant innovations of BuckleScript and hence ReScript, in my opinion, is managing to ship a complete toolchain that works out of the box for every major platform including Windows, with no Cygwin/MSYS/WSL/etc. hacks needed.

Is it because they rely on the nodejs runtime for their toolchain? How do they do it?

---

<div class="post-metadata">

### Author: ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)
#### Post date: [February 1, 2023, 2:15pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/5 "2023-02-01T14:15:03Z")

</div>

> [@hyphenrf](#):
>
> How do they do it?

Not by Node.js alone. They went to some trouble to use platform-agnostic tools, like the Ninja build system, npm for packaging, and avoiding any use of platform-specific tools like even make.

---

<div class="post-metadata">

### Author: ![jeffsco](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeffsco/32/45_2.png) [@jeffsco](https://discuss.ocaml.org/u/jeffsco)
#### Post date: [February 2, 2023, 4:27pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/6 "2023-02-02T16:27:58Z")

</div>

Anecdotally, I have a card-game-playing app that’s 26,000 lines of OCaml, and the minified JavaScript is much smaller when using Js\_of\_ocaml than it was with Bucklescript.

The node.js ecosystem is a bit overwhelming, so this may be due to my choosing a poor minifier for the Bucklescript code. On the other hand, i can use the output produced by Js\_of\_ocaml without minifying it further.

Bucklescript size: 760878  
Js\_of\_ocaml size: 375304

(You can play the game at [Master Schnapsen/66](http://schnapsen.psellos.com/.))

---

<div class="post-metadata">

### Author: ![hhugo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hhugo/32/1143_2.png) [@hhugo](https://discuss.ocaml.org/u/hhugo)
#### Post date: [February 2, 2023, 9:30pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/7 "2023-02-02T21:30:02Z")

</div>

> [@hyphenrf](#):
>
> There is one virtue to producing readable JS that’s often overlooked I feel, probably because it’s hard to empirically measure, but readable JS is more amenable to minifiers, treeshakers, produces smaller and faster artifacts overall. That has been my experience anyway, could just be correlation.

There seems to be a belief that js\_of\_ocaml doesn’t do dead code elimination (or “treeshaking”) and I’m not where it comes from.

Js\_of\_ocaml performs deadcode elimination and minify its out.

> [@jeffsco](#):
>
> I have a card-game-playing app that’s 26,000 lines of OCaml, and the minified JavaScript is much smaller when using Js\_of\_ocaml than it was with Bucklescript.

Thanks for the feedback.

---

<div class="post-metadata">

### Author: ![lambda\_foo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lambda_foo/32/275_2.png) [@lambda\_foo](https://discuss.ocaml.org/u/lambda_foo)
#### Post date: [February 2, 2023, 9:32pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/8 "2023-02-02T21:32:25Z")

</div>

I would include [Melange](https://github.com/melange-re/melange) as a fork of Bucklescript that produces JavaScript from OCaml & Reason. There is a lot of work going on in Dune to [support it](https://github.com/ocaml/dune/pulls?q=is%3Apr+melange). Personally I am using JSOO over the other options because I have existing OCaml code and I prefer OCaml syntax over Reason.

Looking at this last year I put together a [high-level diagram](https://gist.github.com/tmcgilchrist/1bb5b67e60a2224f0ba8d58546b1d1cd) of how each of the options works. It might be of interest.

---

<div class="post-metadata">

### Author: ![hhugo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hhugo/32/1143_2.png) [@hhugo](https://discuss.ocaml.org/u/hhugo)
#### Post date: [February 2, 2023, 9:40pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/9 "2023-02-02T21:40:09Z")

</div>

Looking at your diagram, I don’t know what you mean by “Javascript code (Bytecode interpreter)”.

Also note that all features/optimizations mentioned in the melange box can also apply to the js\_of\_ocaml one.

---

<div class="post-metadata">

### Author: ![lambda\_foo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lambda_foo/32/275_2.png) [@lambda\_foo](https://discuss.ocaml.org/u/lambda_foo)
#### Post date: [February 2, 2023, 9:57pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/10 "2023-02-02T21:57:43Z")

</div>

> I don’t know what you mean by “Javascript code (Bytecode interpreter)”.

I meant to indicate that the byte code interpreter is running as a JS program, as compared to the regular byte code interpreter which is a native executable.

True the features/optimizations apply to js\_of\_ocaml, I hadn’t finished my work in detailing that section of the diagram.

---

<div class="post-metadata">

### Author: ![hhugo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hhugo/32/1143_2.png) [@hhugo](https://discuss.ocaml.org/u/hhugo)
#### Post date: [February 2, 2023, 10:06pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/11 "2023-02-02T22:06:31Z")

</div>

> [@lambda\_foo](#):
>
> I meant to indicate that the byte code interpreter is running as a JS program, as compared to the regular byte code interpreter which is a native executable.

The code emitted by js\_of\_ocaml is not a bytecode interpreter. It compiles bytecode into javascript.

For example

```ocaml
let rec fib n = match n with 0 | 1 -> 1 | n -> fib (n - 1) + fib (n - 2)

```

gets compiled to

```javascript
function fib(n)
    {if(1 < n >>> 0){var _a_=fib(n - 2 | 0);return fib(n - 1 | 0) + _a_ | 0}
     return 1}

```

---

<div class="post-metadata">

### Author: ![lambda\_foo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lambda_foo/32/275_2.png) [@lambda\_foo](https://discuss.ocaml.org/u/lambda_foo)
#### Post date: [February 2, 2023, 10:15pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/12 "2023-02-02T22:15:48Z")

</div>

That’s embarrassing, I’ve incorrectly thought that for some time. Thanks for setting me straight.

Is there technical documentation outside of me reading the code (which I intend to do) that covers the features / optimisations that js\_of\_ocaml does?  
I’ve been compiling a high level presentation on js\_of\_ocaml to give to an interested technical audience that is used to JS/Typescript or Rust/WASM, and wanted to compare it.

---

<div class="post-metadata">

### Author: ![hhugo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hhugo/32/1143_2.png) [@hhugo](https://discuss.ocaml.org/u/hhugo)
#### Post date: [February 2, 2023, 10:21pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/13 "2023-02-02T22:21:06Z")

</div>

There is old paper from 2011 ([https://www.irif.fr/~balat/publications/vouillon\_balat-js\_of\_ocaml.pdf](https://www.irif.fr/~balat/publications/vouillon_balat-js_of_ocaml.pdf)). It’s a bit outdated but gives useful information about the general compilation strategy.

---

<div class="post-metadata">

### Author: ![ancolie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ancolie/32/6189_2.png) [@ancolie](https://discuss.ocaml.org/u/ancolie)
#### Post date: [February 4, 2023, 12:38pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/14 "2023-02-04T12:38:45Z")

</div>

As a part of my PhD, @chambart and I are working on a Wasm backend for OCaml. We presented our prototype and experiments at the WasmGC working group. [The slides and the meeting notes](https://github.com/WebAssembly/meetings/blob/main/gc/2023/GC-01-10.md) are available. At some point we’ll write blogposts/papers on the topic and we’ll announce them on discuss. It’s probably too early to tell more about it.

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [February 4, 2023, 1:53pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/15 "2023-02-04T13:53:22Z")

</div>

Interesting, thanks.

Personally I’m always more interested in accessing the browsers APIs (via [`brr`](https://erratique.ch/software/brr) of course) and so far never found myself too limited by `js_of_ocaml`’s performance.

So my usual question about wasm, what’s the JavaScript FFI story ?

Do you think there would a way to reuse the large amount of extremely boring work I put in `brr` for binding a [non-trivial amount](https://erratique.ch/software/brr/doc/#supported_apis) of browsers APIs in an OCaml friendly way ?

For example by subverting the [`js_of_ocaml` FFI primitives](http://ocsigen.org/js_of_ocaml/latest/api/js_of_ocaml-compiler/Jsoo_runtime/Js/index.html) ?

---

<div class="post-metadata">

### Author: ![zeroexcuses](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zeroexcuses/32/1692_2.png) [@zeroexcuses](https://discuss.ocaml.org/u/zeroexcuses)
#### Post date: [February 4, 2023, 3:40pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/16 "2023-02-04T15:40:12Z")

</div>

@dbuenzli : I’m looking at your project [ocaml\_console (brr.ocaml\_console)](https://erratique.ch/software/brr/doc/ocaml_console)

I’m curious:

1. Did you manage to get “enough of OCaml + js\_of\_ocaml” to run in the browser ?

2. What is the slow down when compiling “ocaml → js” in the browser ?

3. How big is this js blob representing “enough of ocaml + js\_of\_ocaml” ?

---

<div class="post-metadata">

### Author: ![ancolie](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ancolie/32/6189_2.png) [@ancolie](https://discuss.ocaml.org/u/ancolie)
#### Post date: [February 4, 2023, 4:07pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/17 "2023-02-04T16:07:59Z")

</div>

We only recently started to think about the FFI related stuff. We’re going to start looking at C code and OCaml FFI inside Wasm. We’re indeed probably going to end up subverting the C stubs. If it works, writings JS stubs to use a library like zarith in the browser won’t be necessary anymore.

I have not looked into the JS/OCaml FFI inside Wasm yet, but I guess the same strategy would work.

In addition to performances, there are others benefits when using Wasm instead of js\_of\_ocaml, e.g. marshalling of float would work. 🙂

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [February 4, 2023, 4:36pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/18 "2023-02-04T16:36:06Z")

</div>

> [@zeroexcuses](#):
>
> Did you manage to get “enough of OCaml + js\_of\_ocaml” to run in the browser ?

Oh _I_ did nothing. That’s all thanks to the fine work done by the `js_of_ocaml` developers that make it easy to embed a toplevel in your page, see [this bit](https://ocsigen.org/js_of_ocaml/latest/manual/build-toplevel) in the js\_of\_ocaml manual or [this toplevel](https://ocsigen.org/js_of_ocaml/5.0.1/manual/files/toplevel/index.html) published by them.

The only twist here was to make the browser extension communicate with the toplevel embedded in your page. That occurs through [this poke object](https://erratique.ch/software/brr/doc/ocaml_console#ocaml_poke) that your page must offer; for example simply by linking against `brr.poked` (see the instructions on [this page](https://erratique.ch/software/brr/doc/web_page_howto.html)).

> [@zeroexcuses](#):
>
> What is the slow down when compiling “ocaml → js” in the browser ?

Not sure which slowdown you are mentioning but poking a page is slow to compile because there’s a lot of code to compile. You are basically compiling the OCaml parser, the type checker, the bytecode compiler and the toplevel machinery to JavaScript and `js_of_ocaml` performs whole program analysis on all that code to remove dead code in order to make your JavaScript as small as possible.

> [@zeroexcuses](#):
>
> How big is this js blob representing “enough of ocaml + js\_of\_ocaml” ?

On this [poke test](https://github.com/dbuenzli/brr/blob/master/test/poke.ml), it takes 22s to compile on a 2015 laptop and the resulting js file is 11Mo (OCaml v4.14.0, js\_of\_ocaml 5.0.1)

Note that I rather consider this console thing as a showoff rather than something practical to work with (personally I don’t use it when I make `js_of_ocaml` apps and I doubt anyone does, but it was cool to do :–).

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [February 4, 2023, 5:12pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/19 "2023-02-04T17:12:30Z")

</div>

> [@ancolie](#):
>
> In addition to performances, there are others benefits when using Wasm instead of js\_of\_ocaml, e.g. marshalling of float would work. 🙂

Sure but for me there’s no real benefit if there’s no good FFI story with JavaScript to access the browser APIs; otherwise I rather just compile to native code and more than happily scrap the browser :–)

Also what would be the compilation user experience ? `js_of_ocaml` solved that problem quite neatly by working out of bytecode. I bet we’ll need special `opam` switches which also compile libraries to wasm artefacts ?

---

<div class="post-metadata">

### Author: ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)
#### Post date: [February 4, 2023, 5:59pm UTC](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284/20 "2023-02-04T17:59:56Z")

</div>

Wasm can target not only the browser, but also other JavaScript runtimes like Node.js. In the future it will become much more important as a lightweight container runtime alternative to Docker for running service workloads.

[Next page](https://discuss.ocaml.org/t/what-is-the-current-state-of-ocaml-ish-in-the-browser/11284.md?page=2)
