makenowjust-labs/blog

MakeNowJust Laboratory Tech Blog

commlogのNuxt 3移行録

2023-09-17 (更新: 2023-12-12)

commlogはこれまでNuxt 2を利用してきました。 しかし、Nuxtは2022年11月にNuxt 3がリリースされており、Nuxt 2はVue 2と共に2023年12月末をもってサポートが終了されることが発表されていました。 commlogの大部分のコードを書いたのは5年以上前になっているということもあり、コードをメンテナンスすることが困難になっていました。

そこで今回、commlogを完全に書き直すことでNuxt 3に移行しました。 その記録を、この記事では報告します。 また、Nuxt 3の他にTailwind CSSやMock Service Worker (msw)、Bun、Netlify Buildなどの、様々なライブラリ・開発ツールを利用して開発を進めました。 これらにより、モダンな構成にできたのではないかと考えています。

commlogとは

commlogとはGitのコミットログを、Markdownとして表示する"Commit Log as a Blog"システムです。

実際に見てみるとよく分かりますが、commlogのGitリポジトリのデフォルトブランチ (commlogブランチ) には何もファイルがありません。

commlogのリポジトリのスクリーンショット

実際のソースコードはmainブランチにあり、commlogはこのデフォルトブランチのコミットの文章をMarkdownとして表示するシステムになっています。 仕組みが分かるとシンプルですが、初見では中々ぎょっとする光景だと思います。

事前の調査

これまでのcommlogは、フレームワークにNuxt 2をステート管理にVuexを利用していました。 しかしVue 3にアップデートするにあたって、Vuexは標準的なステート管理ライブラリではなく、Piniaの利用が推奨されているようでした。 一方、Nuxt 3ではuseStateによってアプリケーション全体のステート管理が実現できるようでした。 調べたところuseStateによる状態管理で十分そうだと感じたため、今回はuseStateを利用することにしました。

次に、Nuxt 2のコードを徐々に置き換えていくか、完全に書き直すかを検討しました。 どうもNuxt 3であったり、Vue 3の<script setup>を使った書き方はこれまでと大きく異なるようで、単純に書き換えるのは簡単ではないと感じました。 そのため、今回は完全に書き直すことにしました。

やったこと

ここからは、移行のために何をやったのかについて説明していきます。

nuxi init

まず初めに、既存のコードをすべて削除して、Nuxt 3プロジェクトのセットアップコマンドであるnuxi initを実行しました。

bunx nuxi@latest init commlog

今回は開発にBunを使うことにしたので、bunxを使ってコマンドを実行しています。

Bunはパッケージマネージャを内蔵したJavaScriptランタイムです。 パッケージのインストールや実行が高速なことと、Node.jsの互換性がそこそこ高く、多くのパッケージが実行できるのが特徴です。 実際、今回の開発中も互換性の点で大きな問題は起こらなかったと思います。

Tailwind CSSの導入

ひとまずNuxt 3 (Vue 3)の書き心地に慣れるため、ステート管理などは無視して元々の実装にあったコンポーネントを見た目だけ再実装していきました。 その際にTailwind CSSを導入しました。

Tailwind CSSはCSSのユーティリティ集で、細かなクラスの組み合わせでスタイルを設定します。 このブログでも利用していて、最初は微妙な感じがしますが、案外使ってみるとそんなに悪くないなぁとなるライブラリです。 デザインシステムを作れるのであれば必要ありませんが、そうでないならとりあえず乗っかるライブラリとしては悪くない選択肢だと思っています。

Nuxtで利用する場合@nuxtjs/tailwindcssがあるため、とても簡単に導入できました。

さらに、後にローディングアニメーションの実装のためにdaisyUIも利用しました。 これはTailwind CSSの上に実装されたUIライブラリです。 Tailwind CSSのおかげで細かな調整がしやすいのがいいところだと思います。

Mock Service Worker (msw)の導入

コンポーネントの見た目は実装できたので、次にデータの読み込みを実装していきます。

commlogでは、データはGitHubのAPIで取得します。 ここで問題になるのが、APIにはRate Limitがあり、あまり大量に呼び出すことはできない点です1

そこで、今回はMock Service Worker (msw)を利用することにしました。 これはService Workerを用いて通信を監視し、API呼び出しをモックすることができるライブラリです。 通信の遅延なども設定できるため、開発時にはとても便利なライブラリでした。

Nuxtに導入する場合、自分でプラグインを設定する必要がありますが、そこまで大変ではありません。 詳しくはこの辺りを参考にしてください。

Netlify Buildの設定

ここまでの流れで、以前の機能は大体実装できました。 commlogは元からNetlifyにデプロイしていたのですが、毎回手動でデプロイしていました2

そこで、今回はNetlify Buildを使ってビルドとデプロイを行うことにしました。 ここまで開発にはBunを使ってきたのですが、Netlify BuildはBunをサポートしていません。 そこで、不本意ではありますが、Netlify BuildではNode.jsでビルドをすることにしました。 Bunの互換性が良かったのか、今のところこの方針で問題は起こっていません。

追加機能の開発

せっかくライブラリを一新したので、機能を追加することにしました。 5年前にIssueにしていた、コミットにつけたコメントを表示する機能を実装しました。 Vue 3のcomposition APIがかなり使い心地が良く、そこまで苦労せずに実装できました。

今後の課題

というわけでcommlogのNuxt 3への移行が完了しました。 しかし、まだいくつかやり残していることがあります。

  • 元々あったテストを消してしまっているので、追加する
  • 依存関係のアップデートの自動化

テストに関してはBun側にもNuxt側にもサポートがあるので、実装してみたら面白いのではないかと思っています。

依存関係のアップデートは、デフォルトブランチにソースコードが置かれていない都合、やや面倒だと考えています。 別リポジトリのGitHub Actionの定期実行で依存関係を監視するとかやればいいのかな、と考えています。

あとがき

まだ課題はありますが、いつかやらなければと思っていたNuxt 3への移行を実現できました。 最近は研究で忙しくあまりコードを書けていなかったので、そういった意味でも楽しかったです。

それでは、最後まで目を通していただきありがとうございました。

脚注

  1. アクセストークンを設定すれば緩和できますが、アクセストークンは公開できないため、開発時にだけアクセストークンを有効にすることになり微妙だと考えています。

  2. 正確にはreleaseというブランチの内容をNetlifyで公開していましたが、releaseへのpushは手動だったので、実質的には手動です。