スウェーデン最大のプロパティポータルでのRemonMLのテスト


毎週Hemnet 約80万人のユニークな訪問者は、非常に多くの国で約1000万人の住民があります.
年に数回、我々は新しい技術をテストするか、新しい開発を読んで許可されている能力開発の日があります.私は私たちのメインアプリケーションでreasonmlを統合することを選んだ.
あなたが理由について聞いたことがないならば、新しいドキュメンテーションウェブサイトは大きなスタートですhttps://reasonml.org/ .

実験


アプリは現在、Ruby on Rubyの大きなコードベースと反応(JavaScript)です.したがって、いくつかのタイプの安全性を試してみるのに最適な場所です.
私は通常のユースケースの束を含むコンポーネントを変換することを選びました.例えば、他のコンポーネント/イメージをインポートして、追跡出来事を送って、反応文脈を使用して.

コード


これらは私がコードについて同僚から得たいくつかの質問に対する答えです.

インポート文なし


すべてのモジュール.re ファイルは理由でモジュールで、グローバルにアクセスできます.これは問題のように思えるかもしれませんが、それは完全に良いです.

反応する。string (" text ")


Returnは、有効な子(数字、文字列、要素、または配列)として型の束を受け入れますが、理由が静的に入力されているので、一貫した型にマップされる必要があります.したがって、私たちはReact.string この文字列がReact.element . お互いに機能があるReact.int , React.float , and React.array .

パターンマッチングとオプション型


故意にnull and undefined が存在しません.JavaScriptとの相互運用を行う場合undefined PROPの理由にマップされますoption type , どちらがSome(value) or None .
{switch (price) {
 | Some(price) =>
   <span className="mb-2">
     <PriceBox price originalPrice />
   </span>
 | None => React.null
}}
理由は、すべての可能な状態に対処するために、良い方法で私たちを強制します、そして、スイッチのケースが同じタイプを返す必要があるので、我々は帰りますReact.nullprice is None . JavaScriptでは
{price && (
  <span className="signup-toplisting-promo__price">
    <PriceBox price={price} originalPrice={originalPrice} />
  </span>
)}

小道具


次の例では、小文字の値がないように見えます.これはpunning , 変数がプロップと同じ名前を持っている場合、これは省略されます.price={price} なるprice .
let price = 50;
let originalPrice = 100;

<PriceBox price originalPrice />

JavaScriptコードへのバインディング


私たちはHeading コンポーネントライブラリから、バインドが必要です. as はJavaScriptではなく、理由で予約されたキーワードです.加えることによってunderscore in front コンパイラをコンパイルしたコードで削除します.これをname mangling .
/* Hemnet.re */

module Heading = {
  [@bs.module "@hemnet/react"] [@react.component]
  external make:
    (~_as: string, ~styleType: string, ~children: React.element) =>
    React.element =
    "Heading";
};

/* Usage */
<Hemnet.Heading _as="h2" styleType="h3">
  {React.string("Raketen")}
</Hemnet.Heading>
Google Analyticsにトラッキングイベントを送信するために、私は実際のパラメータがラベル引数を使用していることを明確にしたモジュールを作成しました.これ以上のparamsを注文することを念頭に置いておく必要はありません.
/* GoogleAnalytics.re */
/* Binds to the global variable `ga` */
[@bs.val] external ga: (string, string) => unit = "ga";

let track = (~category, ~action) => ga(category, action);

/* Usage */
GoogleAnalytics.track(
  ~category="event-category",
  ~action="event-action",
)
注意:バインディングをより安全にすることもできます.例えば、variants JavaScriptコードに特定の値を送るだけです.

テスト


テストはJESTと同じセットアップを使用してコンパイルされたコードをターゲットにすることができます.

計量


きれいな造りbsb -clean-world コンパイルされたすべてのコードを削除し、bsb -make-world , 理由コードを約200 msでコンパイルします.

コンパイラがウォッチモードで実行しているときにも、ファイルの変更を高速化をコンパイルします.

これはいくつかのモジュールについてのみですが、より大きなプロジェクトでの理由を使用したとき、きれいなビルドのために見た最も長いコンパイル時間は~ 8 - 10秒です.ファイルを変えるとき、それは通常400 ms以下でよくあります.

最終結果


唯一の視覚的な違いは、リンクの色です.それはTailwind(私も実験でテストした)と我々の世界的なスタイルの間の衝突のためです.ビジュアルは別として、コンポーネントは今では偉大なタイプの推論のおかげで使用する方がずっと安全でしょう.
理性実験
生産