Misskey & Webテクノロジー最前線

2025年のMisskey開発ハイライト

本連載は分散型マイクロブログ用オープンソースソフトウェアMisskeyの開発に関する紹介と、関連するWeb技術について解説を行っています。

今年も開発を応援いただき、また本連載をご愛読いただきありがとうございました!

今年Misskeyの開発で取り組んだことは数多くありますが、本記事ではリリースノートに載らないような「知られざる」内部的な改善のうち、特筆に値するトピックをかいつまんで紹介します。

“知られざる”今年の取り組み

フロントエンドの型エラーゼロ化

Misskeyはバックエンド・フロントエンド実装ともにTypeScriptを使用しています。

バックエンドでは、コミットごとにGitHub Actionsで型エラーが発生していないかチェックし、不具合を未然に防げるようにしています。

一方フロントエンドは、実際の動作には影響ないものの型エラーとなっている箇所が少なくなく、バックエンドのように型エラーが発生しないかどうかチェックする仕組みは作れていませんでした。

フロントエンドで型エラーをなくすことができなかったのは、元々あまりTypeScriptフレンドリーな設計ではなかったことに加え、UIを扱う性質上厳密に型付けすることが難しい箇所も多々あったためです。

しかし近年、

  • TypeScriptやVueの型推論がより賢くなってきた
  • Misskey APIの型定義が充実してきた
  • フロントエンド実装がより型フレンドリーな設計に改善されてきた

といった環境の変化に伴い、フロントエンドでもバックエンド同様に型エラーチェックを有効にできる可能性が出てきました。

フロントエンドの型エラーチェックはロードマップにもあるように最優先課題だったため、7月、実現に向けて踏み出しました。

その後改修を続け、苦労もありましたがついに今年11月、長年の目標だった型エラーゼロ化を達成しました。

あわせてコミット時の型エラーチェックも実装し、より堅牢なフロントエンド開発を行えるようなりました。

言語ごとのバンドル生成

Misskeyのフロントエンドはi18nされており、様々な言語でUIを表示できます。

今まで、フロントエンドの言語データ(UIの翻訳データ)は、アプリケーション本体のバンドルされたスクリプトデータとは別々に読み込まれていました。

これは実装の都合によるものでしたが、本来別々にブラウザにダウンロードさせる必要はないものです。

本体データと翻訳データが別々に読み込まれることにより、以下の弊害がありました。

  • データの読み込み処理が2つぶん必要になり、処理が煩雑になる
  • 「本体データはダウンロードできたが翻訳データのダウンロードに失敗した」という状態が発生し得るため、追加のエラーハンドリングが必要になる
  • バックエンドによりレンダリングされる初期HTMLに翻訳データのダウンロード処理を記述する必要が生じるため、フロントエンドの関心がバックエンドに漏れる
  • 本体データのバージョンと翻訳データのバージョンがズレることを防止するための仕組みが必要になる

本体データに最初から翻訳データもバンドルされていれば(つまり言語ごとに単一・専用のバンドルを生成すれば)このような問題は発生せず、実装がシンプルになり保守性が向上します。

さらに、本体データと翻訳データが一緒になることにより、本体データを翻訳データにあわせて最適化する余地が生まれます。

一例として、データが別になっている場合、以下のようにしてテキストをUIに表示します。

<template>
<!-- 日本語であれば「こんにちは」、英語であれば「Hello」が表示される -->
<p>{{ i18n.ts.hello }}</p>
</template>

<script>
import { i18n } from '@/i18n.js';

...
</script>

上記コードのi18nは、事前に用意された翻訳データなのでアプリケーション実行中に変化することはありませんが、都合上変数としてテンプレートに入れるしかありません。

一方、もしデータが分かれていなければ、ビルド段階で以下のように変換を行って最適化できます。

<template>
<!-- これは日本語バンドルを生成した場合の例で、英語バンドルであれば <p>Hello</p> になる -->
<p>こんにちは</p>
</template>

<script>
...
</script>

テンプレートに変数をバインドするのではなく、直接テキストが埋め込まれる形になるため[1]、minifyフレンドリーですし実行時パフォーマンスも僅かに改善します。

この「言語ごとのバンドル生成」は以前からの優先事項のひとつでした。ただし、愚直に対応している言語分バンドルを生成するようにすると、非現実的なほどにビルド時間が延びるため、実装に当たっては工夫が必要でした。

ノート 現在Misskeyは26言語に対応しているため、今までバンドル生成処理が1回で済んでいたものが26回分行わなければならなくなる、ということになります。そのまま実装すると26倍時間がかかります。

そこで、anatawa12氏によって、バンドル処理を担うviteの後処理で置換を行うことでビルド時間の増加を最小限にする方法が考えられ、今年8月に実装へと至りました。

アイコンのサブセット化

kakkokari氏によって、Misskey Webで使用しているアイコンセットをサブセット化する改修が行われました。

Misskey WebではWebフォントとしてアイコンセットを読み込むようにしています。この方法はVueのコンポーネントを使用する方法と比べてレンダリングパフォーマンスに優れます。

ただ、基本的にすべてのアイコンがフォントに含まれ、使用しないアイコンがあってもツリーシェイクできない欠点があります。

そこで、ビルド時にMisskey Webで使用されているアイコンの種類を抽出し、実際に使用されているアイコンのみ収録したフォントファイルを生成するようになりました。

結果、フォントファイルは869KB → 56KB ⁠93%削減)、付随するCSSは241KB → 11KB ⁠95%削減)と大幅に軽量化し、読み込み時のパフォーマンスが改善しました。

PugテンプレートからJSXに移行

MisskeyではサーバーサイドでレンダリングされるHTMLは、テンプレートエンジンPugを用いて生成されてきました。

Pugの構文は特殊なものの、簡潔にHTMLを表現できるメリットがあります。しかしながら、ここでしか使われない記法のため学習コストはゼロではありませんし、型システムとの相性もよくありませんでした。

そこでkakkokari氏により、素のHTMLに近いJSXでテンプレートが書き直され、メンテナンス性が向上したほか、開発者の認知負荷も低減しました。また、Pugはパッケージサイズが大きかったため、依存しなくなったことで副次的にパフォーマンス向上のメリットもありました。

パッケージマネージャのセキュリティ向上

今年はNode.jsエコシステムを標的としたサプライチェーン攻撃の話題が多かったように思います。特に、npmアカウントを乗っ取り、既存パッケージの悪意のあるコードが含まれたバージョンを公開する手法が目立ちました。

通常、そのようなパッケージは公開停止されますが、発見されるまで時間がかかることもあるため、バージョンアップ直後のパッケージをインストールすることはリスクが伴います。

このリスクを軽減するため、Misskeyで使用しているパッケージマネージャのpnpmでは、v10.16.0からminimumReleaseAgeオプションが導入されています。

当該オプションを使うと、公開されてから指定した時間経過していないパッケージのインストールを不可にできます。Misskeyでは早速活用し、公開から一週間経過していないパッケージを依存関係としてインストールできなくし、攻撃の影響を受けにくくしました。

また、⁠ライブラリを使うまでもない簡単な処理は、外部に依存しない自前の実装に書き換える」など、依存を見直しリスクを減らす取り組みも現在進行形で進めています。

その他

去年、2025年の目標として挙げた「脱CASCADE削除」も部分的に実現しています。

「Prismaへの移行」⁠VueのVaporモードへの移行」は未達成です。

Vaporモードに関しては、予想よりもVue側のリリースが遅れており、正式リリースを待っている状況です。現在alpha版までは出ているので、来年には利用可能になるでしょう。

また、バックエンドのメモリ使用量を削減する改修にも取り組みました。これについては長くなるので詳細は別の機会に紹介できればと思います。

来年取り組みたいこと

Vaporモードへの移行ももちろんですが、今年新しく生まれたトピックとして、⁠Go版TypeScriptへの移行」があります。

すでに知っている方もいると思いますが、今年3月、MicrosoftはTypeScriptコンパイラをGoに移植することを発表しました。それを受けて、MisskeyでもGo版TypeScriptへ移行する計画を進めています。

コンパイラが変わったからといってMisskeyユーザーに影響する話ではないので、リリースノートには載らない「内部的な改善」の範疇に留まるかと思いますが、開発者体験を向上させる重要なマイルストーンです。

コンパイラ実装が新しくなることに伴ってTypeScriptのメジャーバージョンも大きく上がりますが、互換性を大きく損なうような変更が多く含まれる、といったわけではないので移行作業自体は比較的楽に行えるのではと予想しています。

移行が完了次第、移行前と後でどれくらいコンパイル時のパフォーマンスが変化したか等について、詳細をレポートできればと思います。Misskeyのコードベースは小さくないので良いベンチマーク対象になるはずです。

ノート 現在MisskeyではJS版TypeScriptコンパイラ(tsc)は型チェック、型定義生成でのみ使用していて、TS→JSへのコンパイルはtscよりも高速なesbuildswcを使っています。

他にも、JWTを用いたステートレス認証の導入、Declarative Web Push対応、スケーラブルな連合プロトコル策定などの構想もあります。

数字で見る「Misskey 2025」

  • コミット数: 1,796
  • 編集されたファイル: 1,798
  • ソースコード: 154,931行の追加、77,839行の削除
  • Issue: 703がオープン 546がクローズ(うち今年作成されたものは355)
  • Pull request: 1,009回
  • リリース: 21回
  • Star数: 10,006 → 10,844

ノート GitHubのComparing changesも参考にしてください。

まとめ

今回は2025年の開発の中で、リリースノートに載らない内部的な改善をピックアップして紹介しました。

Misskeyがエンタープライズで採用されることも増えてきたため、今年も比較的堅実な開発になったのかなと思います。

とはいえ、古のMisskeyに存在したRoom機能[2]の復活、スペシャルリアクション機能[3]など、ワクワクできるような取り組みも今後考えていますので、どうぞご期待ください。

それでは2026年もMisskey Projectを応援のほどよろしくお願いします。良いお年を!

おすすめ記事

記事・ニュース一覧