この記事はKogakuin Univ Advent Calendar 2019 - Adventar 16日目です。
はい遅刻ですごめんなさい
こんにちは、metarinです
このブログはGravというCMSで動いているのですが、ボクにはオーバースペックすぎると感じたのでもう少しシンプルなCMSを作ることにしました。
※まだ出来ていない
-
何故Haskell
Haskellの特徴として- 強い静的型付け故にバグが生じるリスクが低い
- Webアプリケーションフレームワークの種類が豊富
といったものがあるのでサーバーサイドに向いていると思いました
まあ本当はただの趣味なんですけど… -
HaskellのWebフレームワーク事情
適当に調べてみた感じだと- Yesod
- Servant
の2つがメジャーみたいですが、ServantはWebAPIなどの「フロントエンドなんざしらねーよ!」な方々の為な印象が強かったのでYesodにしました
-
準備
https://haskell.e-bigmoon.com/yesod/index.html を読めばだいたいどうにかなりますこの段階で
localhost:3000
にアクセスすることで動作テストできるようになります -
ハマったところ
-
Rooting
Yesodではリクエストの種類とURLで処理を行う関数を分岐させます
ここで定義されてないURLへのリンク=リンク切れとしたり、定義の重複をチェックしたりすることでコンパイル時にリンク切れチェックが行えます。便利ですね!しかし、CMSの場合利用環境によってディレクトリ構成を換えることが出来ないという制約を生み出すことになってしまうので、ルートにワイルドカードを仕込んでこの機能にはお役御免になってもらいます
これを行うためにはダイナミックマルチを使います
こんなかんじで使えますsimple-cms/config/routes
-- Static rules /static StaticR Static appStatic /favicon.ico FaviconR GET /robots.txt RobotsR GET / HomeR GET POST /comments CommentR POST -- Dynamic multi roles !/*[String] PageR GET
[リクエストされたパス] [ハンドラの名前] [受け付けるリクエストの種類]
を順に書いて定義しますここで、ルートでString型を取るダイナミックマルチを使った場合全てのURLに合致してしまうため、最後に置かないとrobots.txtなどの静的でいいもののルーティングも上書きしてぎまう為、最後に書く必要があります
また、オーバーラップチェックを切るために先頭に!を付けますルートを定義できたら、
[処理するリクエストの種類][ハンドラの名前]
で関数を定義することで処理を書けます
!/*[String] PageR GET
というルーティングの場合、関数の名前はgetPageR
になります -
テンプレートエンジン
ルーティングを作れたので、今度はgetPageR
の内容を書いていきます
YesodにはHamletというHTMLテンプレートエンジンがくっついているので、内容が変化するコンテンツでも簡単に記述することが出来ます
しかも、このHamletは埋めこむ変数の型チェックを行なってくれるため間違った型の変数を埋めこんでドカーン!させる心配がありません。便利ですね!
しかし、このチェックはコンパイル時に行われる、つまりテンプレートごとコンパイルするため、テーマ変更を出来るようにしたいCMSとはまたも噛みあいません
Haskell、及びYesodを使うという技術選定をミスった気がしないでもないですがもう後には引けません
なんとかするためにedeという別のテンプレートエンジンを使うことにしました...というところまでしか現段階で出来ていませんごめんなさい
-
まとめ
HaskellのWebフレームワークは闇が深いたぶん来週にも完成していないので予備日は期待しないで下さい
-