Bonsai: Janestreet's UI Library
Bonsai: The UI Framework by Jane Street
Bonsai is a specialized library designed for crafting high-performance, reactive web applications using Js_of_ocaml. While it draws some inspiration from the Elm architecture, it is tailored for the specific needs of Jane Street.
Within Jane Street, Bonsai is the backbone for nearly every internal web tool, ranging from the simple corporate directory to complex dashboards used to monitor and control trading infrastructure.
๐ฒ A Glimpse at the Code
To understand how Bonsai works, consider this simple interactive dice roller:
module Dice = struct
let faces = [ " โ " ; " โ " ; " โ " ; " โ " ; " โ " ; " โ
" ] ;;
let component ( graph @ local ) =
(* Components function as purely functional state machines *)
let % arr face and set_face in
{%html|
div [
"You rolled a #{face}",
button [
style = " ";
on_click =% {fun _ ->
let index = Random.nth_exn faces
set_face index
};
"Roll the dice"
]
]
| } ;;
end
๐๏ธ Architectural Philosophy
At its core, Bonsai treats UI components as purely functional state machines. The logic can be represented mathematically as:
Where is the state and is the transition function.
Incrementalization
Unlike many frameworks that re-render large swaths of the DOM, Bonsai utilizes incrementalization. This ensures that values are only recalculated when their specific dependencies change.
Bonsai vs. Traditional Frameworks
| Feature | Traditional Frameworks (e.g., React) | Bonsai |
|---|---|---|
| Abstraction | State, logic, and rendering are bundled in a "Component". | State and incrementality are a la carte primitives. |
| State Location | Often tied to the component hierarchy. | Managed externally via a dedicated API. |
| Re-computation | Often relies on virtual DOM diffing. | Uses fine-grained incrementalization. |
Pro Tip: If you are coming from React, imagine a world where every feature behaves like a hook, but the state exists entirely outside the component tree.
๐ ๏ธ Key Advantages
1. Sophisticated State Management
Because state isn't locked into a component hierarchy, Bonsai provides a robust API for handling scoping and lifecycles.
- No Manual Hoisting: You don't need to lift state to the top-level model just to share it between nested components (e.g., in a tabbed view).
- Flexible Composition: You can use the same primitives to optimize expensive business logic as you do to prevent UI re-renders.
2. The OCaml Synergy
By using OCaml for both the frontend and backend, Jane Street achieves:
- Type Safety: Pervasive use of the type system drastically reduces runtime errors.
- Code Reuse: Business logic and types are shared across the entire stack.
- Easier Migration: Many legacy terminal-based UIs were ported to the web simply by reusing existing OCaml types.
3. Integrated Tooling
Bonsai isn't just a rendering engine; it's a full ecosystem:
- Powerful templating language.
- Component-specific stylesheets.
- Comprehensive automated testing suite.
๐งช Testing the DOM
One of the standout features is the ability to write "headless" tests that simulate user interaction and verify DOM changes without a browser.
Example: Testing a User Selector
let % expect_test " shows hello to a specified user " =
let handle = Handle.show in
[ % expect { | div [ input [ oninput ]; span [ "hello" ] ] | }];
Handle.show_diff handle;
[ % expect { | div [ input [ oninput ]; - span [ "hello" ]; + span [ "hello Bob" ] ] |}];
Why this is powerful:
- Diff-based assertions: You can see exactly what added (
+) or removed (-) from the HTML. - Multi-stage scenarios: Multiple
expectblocks allow for complex setup and verification. - Full Integration: Tests can include mock server responses and state transitions.
๐ Learning Resources
If you want to dive deeper into the library, check out these resources:
- Getting Started:
- Bonsai Quick Start (Hands-on intro)
- Thinking in Bonsai (Conceptual deep dive)
- Audio Insights (Signals Threads Podcast):
"Building a UI Framework""Building Tools for Traders"
Note: It is important to realize that "Bonsai" is actually a collection of several underlying libraries rather than a single monolithic entity.