概要
ブログ開設当初、astro-notion-blog(以下アスノブ)なるNotionをヘッドレスCMSに見立て、SSGで静的サイトを出力するプロジェクトを採用していた。
しばらく使ってみてデメリットが目立ち始めたため、純粋なAstroによるSSGに移行しようと前々から決めていた。
年末年始を利用して対応するつもりだったが、年明け以降まで長引いてしまった。
そもそもastro-notion-blogを採用した理由
執筆性の高さ
Notionでのページは、Markdownライクに記載できる。
リアルタイムにHTML要素としてレンダリングされ、そこに複数列のレイアウトを入れ込んだり、サイズの調整ができるため執筆しやすい。
特に設定不要で高い執筆性を享受できるのは魅力的。
ネット環境があればどこでも書ける
webサービスをCMSとして使うわけなので、アカウントでログインできればどのマシンからでも編集できる。
Notionはリアルタイムで自動保存されるので、同期を意識する必要はない。
デプロイもネット上だけでできる
CloudflareとGitHubのリポジトリを連携する前提であり、Cloudflareからデプロイを手動で指示することもできる。
Notionでレイアウトがある程度確認できているのなら、ローカルで開発サーバーを使わず、Staging環境に上げて画面を確認し、本番環境のデプロイをするという運用も可能である。
基本的にCloudflareへのデプロイ方法の説明がちゃんと用意されているので、静的サイト運用未経験者にとってはかなり助かった。
(当時はSSG、SSRの違いがあまりピンときておらず、AstroだのNotionだのの細かい仕様や単語を学習するよりも、とにかく簡単にサイトをデプロイしたかった、という事情もある)
レイアウト
サイドバーは個人的に欲しかったので、デフォルトで用意されているのを評価した。
(スマホ全盛の時代において、レスポンシブデザイン的にはマイナスかもしれないが・・・)
アスノブのデメリット
独自仕様のコンテンツ
アスノブではコンテンツをNotion APIで取得し、レスポンスのJSON(AST: 抽象構文木)を構造解析してHTMLにマッピングする。
しかしそこではNotionに特化した変換処理が多数含まれ、独自で拡張するにはコストが高くつく。
ましてやNotionの仕様がいつ変更されるかわかったものではない。
個人開発のプロジェクトをどこまでメンテナンスできるのか、NotionもAPIをずっと無料で使い続けられるのかどうか不透明でもあり、長い目で見ていくと独自仕様をメンテナンスする将来性にリスクを感じていた。
ビルド時間
実用上の課題となっていたのがこれ。
Notion APIからコンテンツを引っ張ってくるわけだが、素の状態ではそれらをキャッシュすることができない。他のサービスとの連携を追加すればできるそうだが、キャッシュのためにさらに連携依存を増やすことは個人的にしたくなかった。
シンプルにするためにフレームワークを使ってるのに、依存するサービス増やして複雑にしたら本末転倒
40記事あたりでデプロイまでに20分近くかかるようになり、ちょっとした変更を確認するために待たされる時間も馬鹿にならない。
記事の装飾性、レイアウト調整のしづらさ
独自仕様とも関連するが、Notion上でのテキスト装飾の幅は限られている。
フォントサイズ然り、縁取りやフォントファミリーの指定など
そして画像の表示サイズをNotion上で行っても、アスノブ側でレンダリングすると反映されない。これはAPIの使用上、表示サイズの情報が取ってこれないため。
(alt属性に表示サイズをテキストとして入れ込んで、レンダーの処理でパースしサイズを指定させることは可能)
表示サイズはCSSで最大サイズをimgなどに指定すればある程度バランスを取れるものの、Notion上で調整したサイズがそのまま反映できないというちぐはぐさが、書いてる身としては不便に感じる。
その辺はヘッドレスCMS+SSGの宿命的なところではあるが、Notionの強みが殺されているというのが問題。
Markdownの構文を拡張するremark directiveの存在を知り、それを使えば表現も画像サイズの指定の問題も解消できると考え、アスノブからの移行を決意した。
Astroのブログテンプレートの選出
まずアスノブから移行するにあたり、Notion APIからblogテンプレート風に改修するのは面倒な上、それをやるくらいなら既存のテーマを採用したいと考えた。
公式テンプレートと近しい構成でデザインがまとまっていて、レイアウトが大きく変わらないテーマを探したところ、fuwari系のテーマが該当した。
派生テーマがいくつかあったが、なるべくシンプルに始めたかったので元締めのテーマを使うことにした。
fuwariテーマの評価点
- レイアウトがアスノブに近く、デザイン的にも一貫性があり、レスポンシブにも対応している
- astro公式のblogテンプレートに近い構成
- ページ内検索、ライトダークモード表示の機能が組み込まれている
- 使用者の多さ
開発環境
VS Code + SSH Remote + Astro
常時稼働のラズパイにプロジェクトフォルダを作り、そこへ自宅PCや出先で使うノートPCからVPNを経由し、SSH Remoteを使って作業状況を共有するようにした。
どちらの環境から見ても編集状況は常に最新となっており、同期をとることを考える必要はない。
通信容量もファイルを開かない限りダウンロードされないため無駄に食わない。
VS CodeではMarkdown(.md)ファイルにクリップボードから画像を貼り付けることができ、.mdファイルと同じ階層に画像ファイルが自動的に格納される。
Astroの修正と記事の編集を常に同一環境でできるというのが最大の売りといえる。
NOTEGitHub Codespacesでも似たようなことができる。
自分的にはいつ無料枠を使い切るかわからない状況を考えることが面倒なので、オンプレ方式を取った。
開発サーバーについて
docker-composeでnodeのコンテナをalways restartでセットした。
これはfuwariは開発サーバーが割と不安定で、astro.config.jsを書き換えると結構な確率でプロセスが落ちてしまうため。
大抵再起動で直るので、自動起動するよう設定している。
他に検討した構成候補
Wordpress
いわずもがなサイト構築の王道アプリケーション。
本体はローカルで使い、ヘッドレス仕様にすることでホスティングサーバーだけ管理する構成を検討した。
編集性や機能は申し分ないのだが、静的サイトとして出力するためのプラグインの挙動が微妙だった。(simply static、staaticなど)
ビルドされるファイル内に出てくるドメインを単純置換するのだが、他のプラグインが管理する部分のドメインは置換されない。
javascriptなどの動的部分に対しても個別に対応が必要など、Wordpressという大きい基盤を使う割にあまり労力が変わらないこと、プラグインやWP本体のアップデートでいつ崩壊するかわからない不安感から没となった。
Strapi + Astro
ヘッドレスCMSであるStrapiをローカルサーバーで立ち上げ、Astroと連携させる方法。
Astroはひとまずblogスタートアップのテーマで試したが、問題がいくつかあった。
-
コンテンツタイプによる編集性
Strapiは動的にメディア、文書、埋め込みなどの部品を登録し、記事を作ることができる。
APIのレスポンスには部品が配列で格納され、ASTのようにAstro側でマッピングしてHTMLに変換してレンダリングする流れとなる。動的に部品を登録していくというの柔軟性があっていいのだが、全体を俯瞰して見られないので単純に編集(特に修正)がやりにくい。
加えてこの動的な部品は他のCMSではあまり見られないものなので、互換性の部分で評価が下がった。 -
Strapi側のエディタが微妙
Markdownで編集するにあたりCKEditorプラグインを入れてみたが、[]にエスケープがかかってしまう。
CKEditorは画像をクリップボードから貼り付けることができ、メディアライブラリに自動的に登録してリンクも張ってくれるというところで導入したのだが、このエスケープがかかることにより、Astro側にエスケープ文字を置換させる処理をいれることになる。
いわば独自仕様の一種になり汎用性、移植性に関わることからマイナス評価となった -
即時反映されない
結構致命的な問題。 apiから記事データを取得するにあたり、publish後即座に開発サーバーに反映することができなかった。
(設定が悪かっただけかもしれないが) -
dynamic blockで複数ペインかつキャプションをコンポーネントで作り、通常文章はリッチエディタにする
- リストで構造を返すというパース必須のデータになるが、cmsは構造を規定するものというルールにはマッチしている
- 画像のサイズがリストに応じて規定化されるが、逆に言えばスマホ表示などのレスポンスでレイアウトを大きく変える際、imgタグなどにpxでwidthを指定するような書き方よりは対応が用意になるメリットも有る
- 細かいレイアウト調整は不可能となる代わりに、統一レイアウトになるので執筆時にレイアウト調整が不要になる
- 単一画像はリッチエディタで貼り付け。大きさの調整はできないが、SSR側で最大サイズを規定する(縦横ともども)
- リッチエディタにするのは、流石にフォントサイズやら文字色などの指定はmdでは厳しいため
- リンクのブログカードはダイナミックブロックで挿入する
- SSRでカード化。ブロックはテキストで、ブロック名でカード化するかを識別する
- ペイン内にサイズ比を選択するリスト項目も入れとけば、簡易的に大きさの調整が可能
- ペインも画像だけではなくテキストも選択可能にしておけばNotionみたいな左右で画像テキストを振り分けることもできるだろう
- Contentfulではdynamic zoneのような機能はない。Strapiの優位性の一つになるが、それだけ標準的なヘッドレスの仕様とは異なるものでもある。移植するときが不安かも
Contentful + Astro
Strapiの動的部分を排除した形。
ネットがあればどこででも編集可能になる反面、1記事あたりの容量制限があること、サービス自体の方針も変更される可能性があることから見送った。
Obsidian + Astro
ObsidianエディターではNotionのようにMarkdownを書きながら描画してくれるため、編集性に優れる。
加えて画像を貼り付ければリンクを自動で張ってくれること、プラグインなどを設定すれば画像の格納先を調整できるなど、コンテンツを編集するのに結構向いている特性がある。
しかし1点課題があった。それは編集状況の共有。
ソースを共有するのであればgitにプッシュする形をとるものだが、出先で中途半端な書きかけをコミットプッシュするのは気持ちが悪い。かといって書きかけをローカルだけで保持するのも同期が面倒なのと、プッシュし忘れる可能性もあり、複数端末間での同期が難しいということに気づく。
自宅のラズパイサーバーにDropboxのようなミラーリングソフトを導入して同期を取るという案もあったが、通信容量が掛かりそうであること、システムの構成が安定するかもわからないことから、別の案を検討することとなった
移行にあたってのカスタマイズ、実装コードなど
文量が多くなってしまったので以下記事をご参照ください。
移行の効果
デプロイの時間が劇的に短縮した。
具体的には40記事のデプロイが20分(1200秒)→90秒になった。デプロイ時間は約1/13に短縮した。
remarkを扱うようになったため、定型的な独自のスタイルを執筆しながら適用できるようになり、表現の幅が広がった。
有志が公開しているさまざまなremarkやrehypeの部品も追加できるようになるので、全部自前でやらずとも拡張性があり色々遊べそうである。
また想定していなかった効果として、AIアシスタントを記事執筆に活用できるようになった点が挙げられる。
NotionにもAIアシスタントはあるが、有料サービスであり基本的にNotionでしか使えない。
その点VS CodeではGitHub CopilotやChatGPT、ローカルLLMをアシスタントとして使えるのでChatGPTのような汎用AIにお金を出して活用できたり、ローカルLLMを導入して無料でアシスタント機能が使えるといったメリットがある。
ヘッドレスCMSでも実現できるか微妙な機能なので、あながちVSCodeでコンテンツを管理するという選択肢も悪くないのかもしれない。