C#による自家製静的サイトジェネレーターに移行した話

見た目はほとんど変わっていませんが(とはいえ横幅広くしたので印象は結構変わったかも)、このサイト、フルリニューアルしました。内部構造が。完全に。別物に。元々はWordPressだったのですが、今回から自作の静的サイトジェネレーターでhtmlを生成し、GitHub Pagesでホストするようにしました。元になるソース(.md)もGitHub上に置き、GitHub ActionsでビルドしてGitHub Pagesでホスティングされるという、完全GitHub完結ソリューション。また、記事を書くエディタもGitHub web-based editor(リポジトリのトップで.を打つと、VS Codeそのものが起動するやつ)を利用することで、非常に快適で、というかMarkdownエディタとしては最高品質のものが乗っかっていて、たかがブログ書くにしては面倒くさいPush/Pullもなくダイレクトコミットで反映出来てしまうというのがとても良い体験になっています。

.でエディタを起動して、articles配下にYYYY-MM-DD.mdファイルを新規作成。

image

完全にVS Codeそのものでデスクトップアプリのものと全く区別が付かないレベルで、これを超える品質のエディタを普通のサイトに乗せることは不可能でしょう。当然もちろん画像のプレビューもできますし、なんだったら拡張すら入る。

GitHub管理だと画像置き場(アップロード)が面倒くさい問題があるのですが、これはIssueを画像アップローダーとして使うことで回避しています。Issueの入力フォームは、画像をCtrl+Vでそのままアップロードが可能です。そして嬉しいことに、マークダウンに変換してくれているのでコピペするだけでOK。

image

image

上がった先のuser-images.githubusercontentは別にIssueそのものと紐付いているわけではないので、 アップローダ用に使ったIssueはSubmitすることなくポイ、です。そうしてどこにも紐付いていないuser-images.githubusercontentですが、別にだからといって削除されることもなく永続的に上がり続けているので、遠慮なく使わせてもらうことにします。まぁちゃんとGitHub上に上げてるコンテンツ用に使っているので、許されるでしょう、きっと。多分。

そうして出来上がった記事は、そのままエディタ上のgit UIからコミットすると、自身が作業している領域は直接サーバー上のmaster(main)なので、プッシュ不要で反映されます。

image

こうなると、もうWordPressで投稿をポスト、するのと変わらないわけです。ブログ記事程度でcloneしてpullしてstagingしてpushしてというのは地味に重たいので、このぐらい身軽で行きたいですね。(実際、投稿後に編集ラッシュとかよくあるので、ちょっと手数が増えるだけで猛烈に嫌気がさす)

ジェネレートはworkflows/buildy.ymlで、このリポジトリ内に配置されてるC#プロジェクトを直接ビルド/実行することで生成処理をしています。dotnet run便利。

build-blog:
runs-on: ubuntu-latest
steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 6.0.x
    - run: dotnet run --project ./src/Blog2/Blog2.csproj -c Release -- ./articles ./publish
    - uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./publish
        keep_files: true

生成されたファイルはpeaceiris/actions-gh-pagesを使ってgh-pagesブランチと同期します。その際、デフォルトでは既に上がってるファイルを全削除してしまうので、今回はstyleやassetを、同期とは別に置いてあるので削除されると困るので、keep_files: trueも指定しています。そうすると記事の削除がしづらくなるんですが、記事の削除はしない or どうしても削除しなかったら二重に(articlesとgh-pages)削除すればいいだけ、という運用で回避。

と、いうわけでシステム的には満足です。

C#でもStatiqなどといった静的サイトジェネレーターは存在するのですが、あえて自作した理由は、サイトのシステムをそっくり移行するという都合上、URLを前のものと完璧に合わせたかったというのがあります。生成結果のファイル一覧が若干変というかクドいというか、といったところがあるのですが、これは前のWordPressでやっていたルーティングをそのまんま再現するためということで。WordPressからのエクスポートも、DB直接見てC#でそのままテーブルダンプから作ったので、まぁ別に大したコードが必要なわけでもないので一気に作っちゃえという気になったというのもあります。

外部ライブラリとしてはMarkdownのHTML化にMarkdigを採用しました。色々高機能ではあるのですが、今回は Markdown.ToHtml(input) しか使っていませんけれど、感触的にはとても良かったです。

シンタックスハイライトにはPrism.jsを用いました。Markdigの出力する```csharpの変換を、特に何も意識せずとも対象にしてくれるのが良かったですね。プラグインはautoloaderとnormalize-whitespaceを合わせて投下しています。

<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/components/prism-core.min.js""></script>
<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/plugins/autoloader/prism-autoloader.min.js""></script>
<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js""></script>

まとめ

最近ブログ投稿がだいぶ減ってしまっていたのですが、システムも一新したことでやる気が出てきたのでいいことです。まぁ見た目は本当にあんま全然変わってないんですが……!

なお、反映に必要な所要時間は30秒弱。

image

遅いっちゃあ遅いですが、許容できるといえば許容できますね。サイトジェネレートプログラムの実行時間自体は1秒以下で、別に全然時間かかってないんで、CIセットアップとか、それ以外の時間が何かとかかっちゃってます。GitHub Actionsの仕組み的にしょうがないといえばしょうがないんですが、もう少しなんとかなってほしいかなあ。あとGitHub Pages自体が反映が若干遅い。遅い上に進捗が分からないのが地味にストレスフル。とはいえとはいえ、良いんじゃあないでしょうか。良さの殆どはGitHub web-based editorから来てますね、これは本当に革命的に良い。というわけで、このweb-based editorを活かすシステムを作っていくという手段と目的を逆転させた思考が最終的に実際良いんじゃないかと思ってます!

Profile

Yoshifumi Kawai

Cysharp, Inc
CEO/CTO

Microsoft MVP for Developer Technologies(C#)
April 2011
|
July 2022

Twitter:@neuecc GitHub:neuecc

Archive