ObsidianとRust製自作静的サイトジェネレータでブログ更新自動化

2024-12-10 00:49

tags: #aws #obsidian #polysite #rust

こんにちは。 ブラックフライデーで買った3Dプリンタが面白すぎて、睡眠時間が削れています。

この記事はLabBaseテックカレンダー Advent Calendar 2024の10日目の記事になります。

今回は、私のブログ執筆環境であるObsidianとその同期、自作静的サイトジェネレータでのサイト生成、デプロイ、それらの自動化についてのお話をします。

Obsidianでのブログの記述

このブログはObsidianという情報整理アプリを用いて記述されています。

Obsidianの執筆環境

ObsidianのMarkdownエディタはWYSIWYGのエディタ環境を提供しており、Markdownを元に描画されたリッチな表現を見ながらMarkdownファイルを直接編集することができます。 Obsidianはデスクトップのみならずモバイルアプリもあり、どこでもメモを取ることができます。 そのため、ちょっとした時間に何か書くと言った用途にも便利です。

Obsidianの同期の取り方

さて、現代においてデジタルのメモ帳となれば、端末間での同期機能は必須と言えます。 Obsidianの開発元はObsidian Syncという有料サービスを展開しており、運営の用意したサーバにObsidianの内容を暗号化して保存・同期を取ることができます。 一方、Obsidianにはサードパーティのプラグインが導入できるため、Obsidianの同期を取るためのプラグインも存在しています。 その一つであり、私が利用しているのがremotely-saveです。 remotely-saveにはS3互換のAPIを用いて同期を取る方法があり、ブログ記事のMarkdownファイルの内容をS3を使って端末間で同期しています。

自作静的サイトジェネレータ

一方ブログの方は、自作の静的サイトジェネレータを使ってビルドしています。

Rust製静的サイトジェネレータライブラリ polysite

静的サイトジェネレータとしては、カスタマイズ性の高いHakyllを気に入って使っていました。 しかし私はHaskellがそんなに得意ではなかったので、Hakyllにカスタマイズを加えるためのコード記述には限界を感じていました。 そのため、Hakyllのようにカスタマイズ性が高い静的サイトジェネレータライブラリをRustで作ることにしました。 それがpolysiteです。

polysiteの特徴

polysiteは、静的サイト生成を複数の段階に分け、RuleとCompilerを繋げていくことによって、さまざまなメタデータを利用しつつサイトがビルドできるようになっています。

コンパイラを繋げる仕組みとしてpipe!マクロを用意しており、これにCompilerトレイトを実装した型の値を複数渡すと、複数のCompilerを繋げてくれます。 例えば、MarkdownをHTMLに変換して保存するCompilerは、ターゲットファイルの拡張子を変更するCompiler、ソースとなるファイルを読み込むCompiler、Markdownを描画してメタデータに保存するCompiler、メタデータの内容をターゲットファイルに書き込むCompilerなどを繋げて作られています。

Compilerでコンパイルする対象のファイルなどの指定はRule型の値で定義でき、ライブラリを利用する人はRuleの実行されるstepを分けることで、サイト生成のどの部分を並列実行してどこを逐次実行にするかを記述することができます。

polysiteを利用したサイト生成

このブログをpolysiteを利用して生成する流れは、まずMarkdownファイルをコンパイルし、次にMarkdownのfrontmatterから収集したメタデータでOGP画像やタグ一覧、アーカイブやトップページを生成します。

OGP画像はimageprocトレイトなどを利用し、ブログの内容からタイトルなどが含まれた画像ファイルを生成しています。

タグ一覧はコンパイルしたMarkdownのメタデータからタグの項目を収集して生成しています。

この辺のコードは、このブログのGitHubリポジトリで公開しているので、詳しくはそれをみてもらえればと思います。

Obsidianの更新をブログに自動デプロイ

ここまでで、Obsidianでのブログ執筆とブログのビルドについて話しました。 最後に、Obsidianで執筆したブログを自動でデプロイするところを書いていきます。

Obsidian、S3、そしてLambda

先述のように、私はObsidianの同期をS3を使って行っています。 Obsidianの更新でS3のオブジェクトが更新されるということは、Obsidianの更新でLambdaをトリガーできるということになります。 私は過去に、S3の変更をGitHubに自動pushするLambdaを実装しています。 これを応用し、Obsidian側でブログ記事の更新を行い、S3と同期を取ったタイミングでサイト内容の更新があった場合は、自動で差分をGitHubにpushしています。 これにより、GitHub Actionsでサイトの自動デプロイが走るわけです。 Lambdaからの直接デプロイは、環境の制約と課金額が増える可能性があったのでやめました。 まぁ実際はLambdaの課金額はほぼ0に等しいですが。

ブログの執筆と公開

ブログ記事の執筆は.gitignoreされたディレクトリで行い、公開する準備ができたらビルド対象のディレクトリに移動することで、各端末で下書きを共有しつつ、書き上がったタイミングでブログを公開できるようにしています。 もちろんこの記事もObsidianを使って書かれています。 スマホやタブレット、パソコンで空いた時間に少しずつ書き溜めることができているので、便利です。 また、公開したいタイミングで、端末を選ばず(モバイルであっても)ドラッグアンドドロップするだけで記事を公開できると言うのも手軽で便利です。

まとめ

今回は私が整えたObsidianを使ったブログ執筆環境とサイトの自動ビルド、そしてデプロイについて書きました。 Webサイトのビルドシステムにはずっと興味があるので色々触ってはいますが、最近作るサイトはAstroを使うことが多いです。 また、Obsidianの内容を自動で公開する手段として、Obsidian開発元の提供するObsidian Publishや、VitePressを使ったサイトデプロイを行うプラグインも存在しているようなので、そういうのも検討すると良さそうです。