記事を書くのは Flutter 製デスクトップアプリ、ブラウザで表示するのは jaspr 製ページ、というブログシステムを作りました。
ブログとその記事作成のアプリをそれぞれjasprとFlutterで作れば一部処理を共通化できると考えて、まずアプリだけ作った。
— Kabo (@kabochapo) June 28, 2022
PoC程度のつもりだったのに、欲が出てカテゴリ階層化とか複数タブ表示とか楽しくなってきちゃってるので、jaspr側に移るのはいつになるかわからない。 pic.twitter.com/R2398PeHXM
その最初の記事として書きます。
ホスティング
このブログシステムは下記の理由で GitHub Pages 向けにしました。
キャッシュが強すぎて扱いにくいですが、あまり気にしないことにしました。
- GitHub なら追加の利用登録をせずに使える
- かつ無料
git push
するだけで投稿できる- GitHub そのものなのでサービスの連携が不要
訂正
キャッシュが強いのは勘違いでした。
push そのものがデプロイだと思っていましたが、push をトリガーとする workflow で別途デプロイが行われていました。
そこで少し時間がかかるだけのようです(といっても今のところ 1 分前後)。
新しい CSS が読み込まれない現象はあり、パラメータを付けるというよくある方法で解決しました。
動機
手軽さ
技術系の記事を書くのは Qiita か はてなブログ でしたが、ブラウザでサイトを開いて書くのはどうも億劫で、書き始めるのに気合いが必要でした。
以前に試した静的サイトジェネレータも、少し手間がかかるせいで捗りませんでした。
Zenn は、Google ログインしかサポートされていない理由で使っていません。
GitHub との連携が可能なので、今回作ったデスクトップアプリを Zenn の執筆用に作り変えると便利そうですが、わざわざ投稿先を増やす必要性を感じないので今後の気分次第です。
自由さ
Qiita 等に Stack Overflow の回答程度の小さな情報やいわゆる「ポエム」の記事を上げている人もいますが、自分専用の空間ではないので私は気が引けます。
それと違って個人ブログなら、この記事はまさにそうですが、日記風の内容でも自由に書けます。
階層式のカテゴリにしたい
多くのブログはなぜかタグ式ですが、自分のブログは階層構造にしたいと思っていました。
リレーショナルデータベースなら簡単で、Supabase の無料枠で実現できました。
jaspr との出会い
JavaScript / TypeScript は仕事などで必要なときには使っていますが、エコシステムに馴染めなくてなるべく触れたくない気持ちです。
それでも何かウェブサイトを作るなら使うしかないと思っていたところで jaspr を知り、Flutter に近い感覚で Dart で作れることと使ってみたいという欲求が後押しになりました。
jaspr とは
Dart の Web フロントエンド開発フレームワークです。
他にいくつか(Flutter 風、Svelte 風など)ありますが、内部の類似性は jaspr が一番です。
そのおかげで、状態管理に使う自作の Grab というパッケージを jaspr に対応させるのが簡単でした。
状態管理はjaspr_riverpodがあるけど、自作のGrabのほうが好みなのでjaspr_grabを仮作成した。
— Kabo (@kabochapo) June 8, 2022
Flutterに依存しまくってるパッケージだけど、Elementなどの構造がFlutterにそっくりなので一部を変えるだけで対応できた。 pic.twitter.com/ltzeWMgg3e
jaspr の感触
Flutter の内部構造まで模している点では jaspr しかないのですが、UI は HTML で書きたい気持ちになりました。
<li class="hoge">テキスト</li>
HTML ならこうやって短くかけるものが jaspr では次のようになります。
const DomComponent(
tag: 'li',
classes: ['hoge'],
child: Text('テキスト'),
)
その解決には Zap など HTML で記述するタイプのフレームワークを選ぶしかありません。
そこは置いておくとしても、jaspr はもうちょっと成熟するまでは使いにくいです。
例えば jaspr_router は機能が足りなかったので、使わずに自作するしかありませんでした。
他には、SSR 用と SPA 用が一緒になっているような構造がちょっとわかりにくいです。
jaspr serve
で動かしたときと jaspr build
で生成したサイトは挙動が異なります。
でも使おうと思えばこのブログのように一応使えるので、ちょっとしたときに使うと思います。
悩んだところ
デスクトップアプリ
fluent_ui パッケージを使いました。
Material の widget と似た部分が非常に多いですが、おかしな挙動や微妙な違いなどがあって選定を間違えたと思っています。
特に、タブを切り替えても内容を保持する機能がないのが辛いです。
それに対応しているか未調査ですが、libadwaita にすれば良かった気がしています。
余談ですが、Flutter でお近づきになった Material Design は、デスクトップでデスクトップらしい UI にしたいときには役に立たない知識だなと思いました。
SPA(問題点 1)
GitHub Pages にはウェブサーバにある rewrite の機能がありません。
SPA(シングルページアプリケーション)では URL にハッシュを付けるか、付けずに 404.html
を強引に利用して index.html
にリダイレクトする仕組みが必要です。
- 参考
試してみると当然できたのですが、リダイレクトが UX や SEO に影響しないか不安に思いました。
また、存在しないページは「ソフト 404 エラー」にするしかないのも気になりました。
jaspr には SSR の機能もありますが、GitHub Pages では使えません。
SPA(問題点 2)
SPA では Open Graph の情報を動的に設定するしかありません。
そうすると Twitter 等では解釈してくれません。
ブログでは OG は重要なので大きなネックになります。
SPA の問題の解決
記事ページはデスクトップアプリで静的ページとして生成することにしました。
一覧ページだけが SPA です。
それで一覧は動的なページになるので、記事を投稿するたびに一覧まで生成しなくて済みます。
今後
シェアのボタン類の設置など細かいところがまだできていなくて今後の作業です。
あと自分の作業ではないですが、Flutter のデスクトップでのテキスト入力は挙動がおかしいので、今後の改善を待つしかありません。
全体のコードは欲しい人がいるかわかりませんが、オープンソースにするかもしれません。