プログラミング
Bonsai: Jane StreetのUIライブラリ
Bonsai: Janestreet's UI Library (github.com)
要約
Bonsaiは、OCamlでパフォーマンスが高くリアクティブなWebアプリケーションを構築するためのUIライブラリで、Elmに触発されています。Jane Streetのほぼ全てのWebアプリケーション(企業ディレクトリからトレーディングシステムを監視・操作するツールまで)で使用されています。Bonsaiコンポーネントは純粋関数的なステートマシンとして実装され、状態が変更されたときのみ増分的にレンダリングされるため、効率的です。
全文翻訳
Bonsai Bonsai Bonsaiは、OCamlでパフォーマンスが高くリアクティブなWebアプリケーションを構築するためのUIライブラリで、Elmに触発されています。
これは、企業ディレクトリからトレーディングシステムを監視・操作するツールまで、Jane Street内のほぼ全てのWebアプリケーションの構築に使用されています。
少しインタラクティブ性のあるシンプルなBonsaiコンポーネントは以下のようになります。
module Dice = struct
let faces = [ "⚀"; "⚁"; "⚂"; "⚃"; "⚄"; "⚅" ]
;;
let component (graph @ local) =
(* コンポーネントは純粋関数的なステートマシンとして実装されます。 *)
let face, set_face = Bonsai.state (List.hd_exn faces) graph
in
(* コンポーネントは、関連する状態部分が変更されたときのみ、増分的にレンダリングされます。 *)
let%arr face and set_face in
{%html|
<div>
You rolled a #{face}
<button
style=""
on_click=%{
fun _ ->
let index = Random.int (List.length faces)
in
set_face (List.nth_exn faces index)
}
>
Roll the dice
</button>
</div>
|}
;;
end
ほとんどのJane Streetの内部WebアプリケーションはBonsaiで構築されています。
コンポーネントは純粋関数的なステートマシンとして実装され、容易に合成可能です。
フレームワーク内の増分化は、値が必要になるまで再計算されないことを意味します。
これはビューだけでなく、あらゆる値に適用されます。
なぜBonsaiなのか?
他のWebフレームワークは、状態、増分化、レンダリングをUIコンポーネントという単一の抽象化にまとめがちです。
対照的に、Bonsaiでは状態と増分化のプリミティブを個別に合成できます。
ユーザーインタラクション中にページ全体を再レンダリングしないようにするのと同じプリミティブを、ライブ更新データセット上の高コストなビジネスロジック計算を増分化するためにも使用できます。
(Reactに慣れているなら、すべてがHooksに非常に似たものを使用し、状態がコンポーネント階層の外で管理されていると想像してみてください。)
状態が明示的なコンポーネントに関連付けられていないため、ユーザーがページとインタラクトする際のライフサイクルと状態のスコーピングを管理するための広範なAPIがあります。
例えば、タブインターフェースなどで、状態を持つUIコンポーネントのコレクションを別のUIコンポーネント内に埋め込みたい場合、Bonsaiはアプリのトップレベルモデルに内部コンポーネントの状態を手動でホイストする必要なく、状態管理を処理します。
状態がどのように合成されるかのさらなる例については、Bonsaiの作成者によって書かれたこの合成比較を参照してください。
そして、BonsaiはOCamlで書かれているため、バックエンドとフロントエンドの両方で同じ言語と型を使用することが可能になります。
これが可読性に与える影響、特にOCamlの型システムを広範に使用してエラーを減らす場合に、大規模なWebアプリのコードベースを管理可能に保つことへの影響は、どれだけ強調してもしすぎることはありません。
Jane Streetでは、以前はターミナルUIしか持たなかった多くの内部システムがあり、このフレームワークは既存の型とビジネスロジックをWebに移植することを容易にしました。
Bonsaiには強力なテンプレート言語、コンポーネント固有のスタイルシートのサポート、およびアプリ全体の自動テストシステムも付属しています。
Expressive tests that save you from manually clicking through your app
Bonsaiの最も強力な機能の1つは、UI要素をプログラムで操作し、DOMの進化を観察する現実的なテストを簡単に記述できることです。
以下の例では、ユーザーセレクターの動作をテストしています。
テキストボックスに入力した内容は、「hello」メッセージに追加されます。
let%expect_test "shows hello to a specified user" =
let handle = Handle.create (Result_spec.vdom Fn.id) hello_textbox in
Handle.show handle;
[%expect
{| <div> <input oninput> </input> <span> hello </span> </div> |}
];
Handle.input_text handle ~get_vdom:Fn.id ~selector:"input" ~text:"Bob";
Handle.show_diff handle;
[%expect
{| <div> <input oninput> </input> - <span> hello </span> + <span> hello Bob </span> </div> |}
];
2つのexpectブロックがあることに注意してください。
(これにより、特定のシナリオ内で複数のアサーションを行い、セットアップ/ヘルパーコードをそのシナリオに限定できます。)
最初のブロックはUIを表示し、2番目のブロック(差分を含む)は、プログラムでテキストを入力した後の動作を示します。
Bonsaiは、ユーザー入力に応答してHTML属性やクラス名がどのように変化するかさえ表示します。
テストにはモックサーバー呼び出しを含めることができ、UIだけでなくそれを駆動する状態への変更も伴う場合があります。
このようなテストにより、ブラウザを開かずにコンポーネント全体を記述できます。
Documentation
Bonsai Quick StartとThinking in Bonsaiは、Bonsaiへの実践的な入門を提供しており、学習を開始するのに最適な場所です。
また、以下もあります。
一連のハウツー記事。
Bonsaiの歴史に関する短い連載。
「Building a UI Framework」に関するSignals & Threadsポッドキャストのエピソード。
「Building Tools for Traders」の別のエピソードでは、Bonsaiを使用する利点について議論しました。
Bonsaiで構築されたサンプルWebサイトのライブラリ。
APIドキュメントはcont.mliファイルにあります。
Bonsaiは実際にはライブラリのコレクションです
ええと、1つのしわ:Bonsai自体 — このライブラリ — は、上記が示唆するよりも実際にはより汎用的です。
これは、汎用の増分可能で合成可能なステートマシンを構築することを可能にします。
Bonsai_webは、そのコアライブラリの上に構築され、インタラクティブなブラウザベースのUIに特化していますが、インタラクティブなターミナルベースのUIを構築するためのBonsai_termもあります。
リアクティブな仮想現実UIのためのBonsai_vrのプロトタイプさえありました。
Bonsaiライブラリのフルスイート:
汎用ライブラリ
Bonsaiは、増分可能で合成可能なステートマシンを構築するためのライブラリです。
テスト
ブラウザベースのUIライブラリ
Bonsai_webは、bonsaiを使用してインタラクティブなブラウザベースのUIを構築するためのライブラリです。
例
コンポーネント
テスト
ベンチマーク
ターミナルベースのUIライブラリ
Bonsai_termは、bonsaiを使用してインタラクティブなターミナルベースのUIを構築するためのライブラリです。
例
コンポーネント
テスト
プリプロセッサ
Bonsai Webアプリケーションでは、次のプリプロセッサがよく使用されます。
ppx_htmlは、JSXに似たHTMLを記述するためのプリプロセッサです。
ppx_cssは、CSSを記述するためのプリプロセッサです。