[ANN] Brr 0.0.1, a toolkit for programming browsers

Hello,

I’d like to announce the first release of Brr.

The TL; DR is:

If you are looking for a productive way to program browsers with js_of_ocaml but without ppx and ghost OCaml objects, give Brr a try.

The details:

Brr is a toolkit for programming browsers in OCaml with the
js_of_ocaml compiler. It provides:

  • Interfaces to a selection of browser APIs.
  • Note based reactive support (optional and experimental).
  • An OCaml console developer tool for live interaction
    with programs running in web pages.
  • A JavaScript FFI for idiomatic OCaml programming.

Brr is distributed under the ISC license. It depends on Note and on the js_of_ocaml compiler and runtime – but not on its libraries or syntax extension.

Homepage: Brr / Erratique
API Docs & manuals: index (brr.index) or odig doc brr
Install: opam install brr

Brr is essentially what I need to be productive for browser programming with js_of_ocaml: an obvious FFI with JavaScript objects as abstract data types without OCaml object phantom types and binding documentation precisely linking into MDN.

The OCaml console is the hack on the cake. In the past I often found it frustrating to have OCaml programs running in my webpages and be greeted with a JavaScript prompt in the browser dev tools. Quite a bit of polishing could be done on that though. Some of which should likely directly be done upstream in the toplevel machinery (e.g. identifier completion, a better toploop API and support for easy pretty printer installation). It would also be nice if we could cut down on js_of_ocaml’s toplevel compilation times ;–)

Parts of Brr have been seriously dogfooded in the past but that new incarnation is largely untested for now and certain APIs might need adjustements. Early adopters should study actual binding coverage, expect glitches and little breakages in the future.

The Note reactive functionality was also seriously used in the past but Note itself needs a new design round and I don’t have the ressources to do it right now, expect breakage, don’t pay too much attention to it for now.

My thanks to the js_of_ocaml developers for the nice ocaml to javascript compiler and a special shootout to Hugo Heuzard for not getting mad at me when pinging him directly for questions.

Happy browser compatibility bug hunting,

Daniel

26 Likes

It’s not really released, but I’m curious about Note now: this is a new FRP library from you, the author of React (the FRP library for OCaml, not the Javascript framework of the same name).

Would you say a few words on why you went for a different library? My guess would be that React depends on runtime mechanisms (weak pointers) that are not well-supported in Javascript-land; but even if the guess is right, I’m not sure what would be the impact on the API or properties of the library.

2 Likes

Note is the result from seeing people (and myself) struggling to use React/FRP “correctly” over the years.

Some of this, I largely attribute to ergonomic problems with the API. It’s my hope for Note to address most of these points (one thing that still needs to be done is replace fix points by a simple lazy infinitesimal delay combinator).

I don’t think I could have made all these changes in React itself so I found it better to start a new library. Also I lost the trademark on the name :–)

Note also tries to provide a much simpler implementation. React’s implementation was based on the FrTime Phd thesis. It’s quite subtle and involved and, as you suggested, uses weak pointer. Note tries to avoid them since those are not available in the browser (but you have things like MutationObservers which I use as gc in Brr’s Note-based reactive dom support).

However not using weak pointers has a semantic uncleanness cost whose impact I’m unsure yet – without discipline from the programmer it may lead to subtle and hard to track bugs when the reactive graph changes dynamically, which I’m a bit wary of.

When my brain dumped Note I wrote a few more technical points in the readme you can read them here.

12 Likes

What are the differences with the default bindings provided in js_of_ocaml to the browser APIs (e.g., js.mli, dom.mli, etc.)?

I’m not sure exactly what you are asking but:

  1. If you are asking about the way API are exposed: brr does not type JavaScript’s objects as phantom types. It simply relies on OCaml’s abstract data types and plain functions. More about this can be found in brr’s FFI manual and FFI cookbook.
  2. If you are asking about binding coverage, you should be able to get a sense of what is bound in brr here.

Regarding 2. brr's coverage of more recent browser APIs is broader and more consistent than in js_of_ocaml – Promise support, Fetch, Service workers, Media capture APIs, WebGL2, Webcrypto, WebAudio, etc. Conversly older APIs supported in js_of_ocaml may not supported in brr (e.g. XMLHTTPRequest). Besides brr's coverage of some of the DOM element-specific interfaces may be shallower than in js_of_ocaml. There is however good coverage for the HTMLMediaElement, HTMLCanvasElement, HTMLFormElement and HTMLInputElement interfaces. For the rest the attribute and property API and the occasional trivial FFI method binding should be able to get you a long way.

3 Likes

In the doc at https://erratique.ch/software/brr/doc/Brr_note_kit/Ui/index.html I can see a nice application screenshot. Is there any chance the code of this app is available somewhere, as a way to learn how to code web apps using Brr_note_kit.

1 Like

Unfortunately not, I made that for a client and it is closed source.

As I said in the original announce don’t pay too much attention to the Note based stuff for now, it needs a few more design iteration.

But on due time I might do a similar drawing app project as sample code, this used Vg for rendering and Note for input and the way everything composed and decomposed was quite encouraging.

2 Likes

That would be great! I’m a FRP newbie. I used to code lablgtk+cairo desktop app, but I’m curious how similar things could be better encoded with FRP using Brr and Canvas.

One thing I forgot, is that there is a todomvc example in the repo, see todomvc.{html,ml} in this directory.

It doesn’t use the UI toolkit you mentioned, just the basic reactive DOM support provided by Brr_note and Brr_note_kit. But you can see how quickly you get reusable and composable components like bool_editor and string_editor.

The program structure in that example is quite similar to the one I had in the drawing app. You define a purely functional, non reactive data model, actions over the data model, create small UI fragments that renders parts of your data model and generate actions events for it, gradually glue them together using note combinators and finally define a fixed point signal that holds the data model as massaged by the actions events of your UI (as mentioned I’d like to replace fix points by direct let rec and a lazy infinitesimal delay combinator).

There are a few pitfalls like you should avoid retaining parts of your data model in the UI otherwise you could get outdated data come back in your model (makes for very fun and spooky bugs though). Identity in the data model is also a bit tricky, it seems in todomvc I used ==. That didn’t work in the drawing app where my surfaces had properties that could be updated but they could also be linked toghether (that window belongs to that wall etc.) so I needed stable identifiers for which I introduced a little abstraction to identify values and define relations between them.

One thing I remember fondly when doing the drawing app is that I would still get the odd interaction glitches you get when coding direct mouse manipulation interactions (surface definition/selection/move/transform) however thanks to the ability to denotationally reason and act (left leaning E.select) on the simultaneity of events, they were easy to understand and fix in an explicit way (that is via a defining expression).

Also if you get into Note the denotational semantics notation is not yet explained there, refer to the one of react it’s the same.

3 Likes

How hard would it be to build on top of Brr_note something like an Elm Architecture-style toolkit? I know there’s a TEA-Bucklescript library, but I’d rather use something relying on dune/jsoo.

I’ve read somewhere else that you were a bit skeptical about the advantage of MVU (movel-view-update) over MVC, but I personnaly find the counter UI example in ELM at


far simpler than the corresponding one in Brr at

There’s no need for those E.select. The UI is IMHO more declarative in ELM.

I don’t know. I didn’t look into MVU too much, but to me it’s largely a remix of MVC – despite what its proponents try to tell you. Since we now live in an age of software adverstising it’s a bit hard to get frank assessments.

As far as I’m concerned the compositionality story of MVU doesn’t look great. Basically it enforces state machines on you, and composing state machines is a bit meh. In FRP state machines become signals (via S.accum) which are highly composable entities with fine granularity (and bonus point, a well defined denotational semantics for equational reasoning).

If you are looking for MVU I think you can simply jump on LexiFI’s vdom. But when I see how you get to compose two models in that paradigm, I’m not convinced.

That example could be rewritten (I didn’t write the examples in this repo) to be more like the ELM one in it’s declarations.

But I think the ELM example is also more rigid. You may not like that E.select on this toy example, but you may get to enjoy it you when you start composing larger systems from smaller components.

5 Likes

You might be interested in Bonsai! At some level, you can think of it as a library for building composable state machines. It uses Incremental as its engine for incrementalizing the computation of views, with a virtual-dom implementation underneath.

It’s the primary tool we use for building UIs inside of Jane Street.

In some ways, Bonsai is like Elm, but it has its own interesting ideas. Some of the concepts are borrowed from this paper:

though I won’t pretend to understand this paper myself!

Bonsai doesn’t yet have enough public-facing documentation, and really the bleeding edge version on github is considerably better and more usable than the one released into opam. But there’s at least one public-facing UI that’s built with it, if you want a real-world example.

5 Likes

Thx for the links!

The memtrace viewer example is pretty cool, but Bonsai looks far more complicated than ELM.
If you look at the counter example (the hello world of UI), here:

and you compare it to the one in ocaml-vdom (thx @dbuenzli for the link) at https://github.com/LexiFi/ocaml-vdom/blob/master/examples/counters/counters.ml

there’s a huge difference in simplicity.

BTW, is there something similar to ocaml-vdom but for programming desktop GUI? Something like a reactive lablgtk? With a MVU paradigm?

Hi Aryx, I wrote the Bonsai example that you linked, and it certainly isn’t the most concise, but that’s because it was built for a tutorial on building small components (one counter is a single component), how to use more advanced combinators (Bonsai.assoc), and how to move data from one component to another (the add_counter_component into the associated counters component.) I think it’s a great example of the power of structuring an UI as a DAG rather than a tree, but it definitely isn’t very small!

In the example, the comments that look like “CODE_EXCERPT_BEGIN” are actually preprocessor definitions that are used in the (honestly, kinda out of date) tutorial here. A bonsai app implementing the same functionality (but that wasn’t written for such a tutorial) would look more like this.

6 Likes

Much appreciated. Too often, tutorials are thought for people who already know modern web development with JS. I seem to remember you were also interested by Android apps as PWAs. Is it possible to use Brr in this setting? In that case, would you update your tutorial with this topic?

Brr is just a JavaScript FFI and bindings to browsers API and their documentation – and that’s what it intends to remain.

As a matter of fact you have the bindings to the APIs needed to make PWAs, I didn’t try do one so far but I might in the future; at which point more documentation might be generated.

1 Like

hey, I’ve been checking these different VDom implementations,

but what is the advantage of using Brr or JaneStreet’s Bonsai over something more popular like ReactJS? In terms of development experience ReactJS has a ton of documentation, benchmarks, cross-browser glue that handles edge cases, a dedicated team that works on it and a huge ecosystem and use in the industry -> you are not likely to be the first encountering bugs;

what problems do other vdom libraries like Brr or Bonsai solve? Are they faster or easier to use or something else entirely?

thanks

1 Like

As mentioned in my previous message Brr is not a library to make user interfaces:

You could build one on top of it though.

Tried Brr recently in a miniature project and it was very pleasant to use. The most obvious win vs. standard Js_of_ocaml was that the basic types relating to JS interop were much more comprehensible (no super-long OO proxy signatures in editor hovers and compiler error messages!). The module factoring seems very thoughtfully done too.

I will look into using it more, particularly the HTML5 Canvas 2D functionality as an alternative to native code with SDL.

4 Likes