elm-pages・ヘッドレスCMS事始め
TL;DR
- このサイトの作成にelm-pagesとmicroCMSを使ってみた。
- 記事公開・更新時にSEO/SMO関連metaタグを静的生成(SG)、下書きの動的プレビュー(CSR)、両方に対応。
- 現代のCMS-friendlyなSSGに求められる基本的な機能は揃っており、それらをすべてElmで快適に記述できる!
- あとはNext.jsのISRに相当する機能まで進化するかどうかというところ。
背景
- もともと業務の文脈でヘッドレスCMSを調査していた
- ヘッドレスCMSは存在を認識してはいたが、ちゃんと使ったことはなく、Jamstackの構成要素というくらいの薄い理解
- ただ、自分の考えるJamstackだとAPI部分(=マネージドバックエンド)はFaunaとかFirestoreが使われるイメージが強かった
- そんな状態から改めて調査すると、ヘッドレスCMSは「ブログやニュースサイトの記事管理」に主眼をおいたマネージドバックエンドという理解でまあ概ね間違ってはなさそう
- Firestore/Google Cloudが内包しているFaaSやバッチ機構を持たないので、複雑なWebサービスの実装には限界がある
- よってできることは「カスタムスキーマを定義できるBaaS」なのだが(経験上それだけでも大変だが……)、加えて下書き機能・レビュー機能・予約公開機能といったテキストコンテンツ作成業務に欠かせない要素をベースで提供しているあたりが特徴か
- 今回使ってみたのは国産のmicroCMS
- で、それを踏まえたときおぼろげながら浮かび上がってきたんです、elm-pagesという存在が
elm-pages
https://github.com/dillonkearns/elm-pages
- こいつはelm-graphqlやelm-markdownを開発しているDillonさんが最近集中的に開発しているElm版Jamstackフレームワーク
- ElmといえばPure SPA(もしくは既存のwebアプリに部分的に埋め込み)なので、SSR(特にOGP/Twitter CardなどのSEO/SMOに関連する
<head>
コンテンツの事前生成)機能が一切提供されていない- そしてElmのVDOMはkernel module実装なので、ユーザランドではhydration(サーバでprerenderしたHTMLをユーザに届けつつ、ページロード後にそこからVDOMを復元して以降はSPAとしての動作になるやつ)を自前実現もできない
- いくらElmがGoogle Botも解釈できるような枯れたJavaScriptを吐くとはいえ、静的事前生成に欠けるのは(具体的にどの程度劣ってるかは自分のElmアプリで計測しないことにはわからんとはいえ)弱点には違いない
- そこでelm-pagesは、
- たしかにhydrationはできないが、とりあえずSEO/SMOのためのpreprenderはやろうと思えばできるのだからやろう
- そして、そこまでをElmでできるようにしよう。つまり、
<head>
タグ内を含むwebsite/articleのメタ情報を記述するためのElmライブラリを提供しよう - そのようにして記述されたコードから、preprenderされたHTMLや、ページロード後にそれをElm SPAでtake overするためのグルーコード、あともちろん肝心のElm SPAをビルドするためのCLIを提供しよう
- ここではhydrateでなくtake overないしreplaceと呼ぶのがふさわしい。prerenderされたHTMLが一瞬ユーザに提示されたあと、Elm SPAがprerender時と全く同様にアプリをrenderし、Elmのroot nodeとして指定してあるHTML要素をまるっと置き換えるからだ
- プレーンなブログサイトのような単純なDOM構造であれば、take overしたアプリとprerenderされていたHTMLは構造が完全一致するので、基本的にはflash of no contentも発生せず、まるでhydrateできたかのような挙動になる
- というのが基本コンセプト
実際に触れてみて
ひとまずの成果物はこのサイトそのもの。
https://ymtszw.github.io
Elmはよく「フレームワークを同梱したwebアプリ(SPA)専用の言語」という説明をされることが多く、自分もそう説明することは結構多い。
が、そうはいってもbare Elmだけだとアプリケーションが大規模化するにつれて表面化する課題はあり、特にボイラープレートコードの多さはよく議論に上がると思う。健全な型システムで守られてはいるので一過性の作業としてやり過ごしてしまうことはできるが、楽できるのにしないのもプログラマの姿勢としては物足りない。ということで、
- 自前ツールによりコード生成を図る
- tree-sitter-elmなどはそのための部品として便利
- ymtszw/setemもそのような成果物の一つ
- elm-review ruleによりコード生成を図る
- Siiiboでも最近よく使っている
- elm-spaを導入してSPAのボイラープレートを自動生成させる
- elm-pagesを導入してJamstack構成を志向しつつSPAのボイラープレートも自動生成させる
といった「フレームワーク on フレームワーク」ないし「フレームワーク over フレームワーク」構成は続々と提案されてきている。その中でelm-pagesの体験の良さはかなり優れていると言っていいと思う。
- 従来のElmの弱点とみなされていたSSRできないという点に部分的(実現したい要求によっては十分)な解決をもたらす
- 普通に開発体験が良い(devサーバを同梱しているCLIの動作が軽快)
- Viewの記述部分に好きな(Elmエコシステムの)技術を使える
- elm-css
- elm-tailwind-modules
- elm-ui
- 生のelm/html + external CSS(classless CSS)
- 特に最近オススメなのがelm-cssで、styled-components風の思想を取り入れているため、view関数内部で何も考えずにCSSを書けば自然とscoped CSSとなり、心配事が大変少ない
- elm-cssから型付CSS要素を省いてAPIを整理したmiyamoen/elm-origamiもアツい
- 実は個人的にブログサイトなどに使うSSGとしては昔からJekyllを使っていて、流石にもうJekyllサイトのメンテはかったるくなり始めていたところ
- Jekyll及びそのフォロワーSSGは、テンプレートエンジンを素朴に使ったレイアウトシステムは提供しているが、そこでスタイル調整するためのCSS開発技術について明確な意見を持ってるものが少なかったように思う
- 例えばJekyllはせいぜいSassプラグインを入れられるくらいで、各種CSS in JS系技術との連携は(そもそもRubyツールってこともあり)困難、というかやりたくない
- この点はHugoや11tyなどでも基本的には変わっていなくて、世界観変えたければNext.jsなどに足を踏み入れたほうが早い、と概観していた
- ちなみにAstroにはその意味で期待していた
- という状況においてelm-pagesはすっぽりとハマったのである
- ヘッドレスCMSを始めとするデータソースAPIとのビルド時の統合をそのものズバリな
DataSource
型で抽象化しており、これが使いやすい- 例えば
DataSource.Http
はHTTPクライアントをSPAからでなくサイトビルド時に使用するための専用moduleなのだが、Elmを書いていれば自然と慣れるおなじみのAPI群でビルド時のAPIからのデータ取得を自由自在に組み合わせることが可能だ - 他にも
DataSource.File
でローカルファイル(Markdownなど)を読み出したり、globパターンでディレクトリ内のファイル一覧をとってきたりなど、CLI同梱フレームワークならではの、普通のElmではできないことができるようになっている
- 例えば
- v3でさらなる改善が見込まれている
- ユーザ向けAPI・データ型が更に整理され、ユーザランドの記述がさらにわかりやすくなりそう
<head>
内のコンテンツ制御の自由度が更に上がるらしい?
elm-pagesはStatic GenerateできてキャッシュフレンドリーなJamstackフレームワーク、ということでNext.jsは結構意識しているように受け止めている。何ならside-by-side機能比較も十分作れるレベルだと思う。
https://jamstack.org/
https://nextjs.org/
流石にDillonさんの個人開発なので正面から戦わせるのは厳しいところではあるし、基本的には(少なくとも今は)プロダクションビルドは静的ページ事前生成+ページロード後にSPA内で動的処理、という構成にとどまっていて、Incremental Static RegenerationというNext.jsの最新の目玉機能には追いついていないし、そもそも追いつこうとしているか(聞いてみないと)わからない。が、それでなくても今後の機能展開に期待は十分持てる。
あと、現在v3向け作業の真っ最中でドキュメントが追いついておらず、したがって私の理解も追いついてないところも結構あるので見逃してるだけで、「実はもっとこんな事もできる」といった可能性もあり得るので、これを読んだ人は是非触ってみて欲しい(特にAPI Route周りまだ触っていないので。)
Elmでなにか書いてみたいが、丁度いいネタがないという人にも、とりあえずelm-pagesからElmに入り、自分のブログサイトでも作りつつ、記事も書きつつ色々試せる、楽しい遊び場になること請け合いだ。
久々にElm関連で業務外に時間を忘れて深堀りしてしまった気がする。いろんなリポジトリに散らばってる昔の記事とか発表資料とかを集約する機運も高まったし、色々楽しみだぞ~~
https://www.youtube.com/watch?v=5GEhrq2dH0k
無限に時間が欲しい