本サイトの管理用Webアプリ作成基盤として使用しているSAFE Stackがリニューアルされました。
細かい経緯等はF#でブログ管理用Webアプリ開発やブログ管理用Webアプリ(SAFE Stack)の.NET Core 3.x 移行を参照していただくとして、今回はSAFE Template v2のお話をしたいと思います。
v1 → v2で変わったところ
- テンプレートがシンプルになった。
- StandardとMinimalの2つのみ
- オプションによるカスタマイズは無くなった
- その代わり、SAFE Documentationに "How do I..."というカテゴリでカスタマイズ方法がまとまられている。
- 本記事もHow do I upgrade from SAFE v1 to v2?を参考にSAFE Stackサンプルを修正。
- .NET Core 3.1になった。
- 各プロジェクトがnetstandard2.0からnetcoreapp3.1に変更。
- SAFE Documentationはまだnetstandard2.0のままになっている。
- Sharedが独立したプロジェクトになった。ClientプロジェクトとServerプロジェクトはSharedプロジェクトを参照する形に。
- Standardはpaketの構成が単一に。前のようにgroup Clientやgroup Serverは無くなった。
- テストプロジェクトが追加されている。
- build.fsxにFarmerによるAzureへのデプロイが追加されている。
- dockerについては"How do I..."に記載されている。
結構、変わってます。
以前の記事、SAFE Stack 開発環境構築でまとめたオプション類は全て無くなり、-m
でMinimal版が作成されるのみとなりました。
カスタマイズはドキュメント見てね。という方針のようです。まぁ、これはこれでいいんじゃないでしょうか。
SAFE Stackサンプルのアップグレードも特につまるところ無く出来ました。
Felizについて
今回、久々にSAFE周辺を見ていたら、面白いものを見つけました。
FableのコントリビュータであるZaid-Ajaj氏がFelizというものを作ってます。
フェリスと読みます。ハッピーという意味だそうで。
詳しくは上記GitHubのリンクかドキュメントを見て欲しいのですが、触りだけ。
これまでFableでViewを作成する際は
div [アトリビュートのリスト] [子要素のリスト]
というような形式で記述していました。これは一見、理にかなっているように思えるのですが、"[" や "]"が沢山出てきて、今見てるのはアトリビュートのリストなのか、子要素のリストなのか非常に分かりにくかったのです。
例えば、こんな感じ。
form [] [
Field.div [] [ Label.label [ ] [ str "あなたの手" ] ]
Field.div [ Field.IsGrouped ]
[ Control.p [ ]
[ Button.a
[ Button.Color IsInfo
Button.OnClick (fun _ -> dispatch Guu) ]
[ str "グー" ] ]
Control.p [ ]
[ Button.a
[ Button.Color IsInfo
Button.OnClick (fun _ -> dispatch Choki) ]
[ str "チョキ" ] ]
Control.p [ ]
[ Button.a
[ Button.Color IsInfo
Button.OnClick (fun _ -> dispatch Paa) ]
[ str "パー" ] ] ]
Field.div []
[ Label.label [] [str "結果"]
Control.p [] [str (sprintf "%s" model.Result)]]
Field.div []
[ Label.label [] [str "勝敗"]
Control.p [] [str (sprintf "%i 勝 %i 敗" model.Win model.Lost)]]
]
コンス("[]")がところどころ入っていて、どちらのことなのかわかりにくい!
ちなみにPascalケースなキーワードはBulmaというCSSフレームワークのラッパー(Fulmaといいます)です。
これがFelizスタイルだとこうなります。
Html.form [
Bulma.field.div [
Bulma.label [prop.text "あなたの手"]
]
Bulma.field.div [
field.isGrouped
prop.children [
Bulma.control.p [
Bulma.buttons [
Bulma.button.button [
color.isPrimary
prop.onClick (fun _ -> dispatch Guu)
prop.text "グー"
]
Bulma.button.button [
color.isInfo
prop.onClick (fun _ -> dispatch Choki)
prop.text "チョキ"
]
Bulma.button.button [
color.isDanger
prop.onClick (fun _ -> dispatch Paa)
prop.text "パー"
]
]
]
]
]
Bulma.field.div [
Bulma.label [prop.text "結果"]
Bulma.control.p [prop.textf "%s" model.Result]
]
Bulma.field.div [
Bulma.label [prop.text "勝敗"]
Bulma.control.p [prop.textf "%i 勝 %i 敗" model.Win model.Lost]
]
]
ちょっと縦に伸びた感はありますが、リストの前にキーワードが付与される感じになっているので、とてもわかりやすいです。
Bulmaというキーワードから始まっているのはFeliz.Bulma、さきほどのFulmaに対応するものです。
FelizがサポートするHTML要素は最初のHtml.form
のようにHtml
というキーワードから始まります。
Felizで記述する際の注意点は、
- 属性が無い時はリストの中に
ReactElement
を直接並べることが出来る。 - 属性が有る場合は
prop.Children
の中にReactElement
を並べる
といったところでしょうか。ReactElement
とはHtml.div
などが返す要素のことです。ちなみに属性はIReactProperty
という型です。
Felizは独自の型を返すわけではなく、Fable.Reactで定義された型を返すので、その気になれば混ぜた書き方も可能です。
また、Reactの関数コンポーネントも、より自然に書けるようになっているので、ElmishはよくわからないがReactは知ってるという方にもオススメです。
まとめ
かなり駆け足で、しかもSAFE Stack v2の話よりもFelizの話の方が長いという、タイトルと合ってない記事になってしまいました。ごめんなさい。
Reactもフックが導入されて、より関数型言語との親和性が高くなりました。
Elmishはシンプルな状態管理が出来ますし、Recoilも既にFeliz.Recoilというものが作られているので、ReactをF#で書く環境は整っていると思います。
SAFE Stackサンプル(GitHub) もSAFE Template v2にアップグレードし、ついでにFelizで少し書き直してみました。よろしかったら参考にしてくださいませ。