- Rustで小さなWebアプリを作る場合でも、Djangoのような統合型の体験が不足しており、ルーティング・ログイン・DB・管理機能を自分でつなぎ合わせる負担が大きい
- 必要なフレームワークは、ルーティング/ハンドラ、テンプレート、静的ファイル配信、ログイン、認可、DBインターフェース、管理ツール、WebSockets、ホットリロードを標準で束ねるべき
- actix-web・axumのようなミニマルフレームワークや、Dioxus・Leptos・YewのようなSPAフレームワークはあるが、Webアプリ全体の構成を代わりに組み立ててはくれない
- スターターテンプレートは初期設定を減らせても、プロジェクトが分岐した後は変更のマージやライブラリ更新が保守負担として残る
newtは既存コンポーネントを意見のある形で束ねるWebツールキットを目指しており、小さなWebアプリを数日ではなく数分で始められるようにするのが目標
Rust Web開発に欠けている統合型の出発点
- 小規模なWebプロジェクトをRustで作る場合でも、Djangoや類似フレームワークよりはるかに多くの初期の接続作業が必要
- Rustコミュニティの一般的なアプローチは、必要な部品を自分でつなぎ合わせる方式に近い
- Are We Web Yet?でも、RustのWeb開発では通常は自分で接続する必要があり、始める際に追加の設定作業を見込むよう案内している
- この追加作業は単に「少し多い」程度ではなく、実際にプロジェクトを始める前に処理すべき項目がかなり多い
- 統合型Webフレームワークがあれば、RustをWebアプリに使うよう説得しやすくなる
- Rustの利点としては、型システム、性能、コンパイル中に取れるコーヒーブレイクが挙げられている
ほぼすべてのWebアプリに必要な基本構成
-
ルーティング/ハンドラ
- 入ってきたリクエストを適切なハンドラに送る必要がある
- パスパラメータを処理する必要があり、型情報があればなおよい
- クエリパラメータやフォーム処理もあるとよい
-
テンプレート
- HTMLを生成する必要があり、場合によってはJSONやXMLも生成する
- 条件分岐、match/switch、ループのような基本ロジックが必要
-
静的ファイル配信
- CSSのようなアセットを配信する必要がある
- 別サーバーで処理することもできるが、ローカル開発や小規模デプロイでは同じWebサーバーに含まれていると便利
-
ログイン
- アプリはたいてい複数ユーザー向けか公開ネットワークにデプロイされるため、ログイン機能はほぼ常に必要
- 毎回自分で配線するのは面倒なので、最初から簡単に使えるべき
- カスタマイズやオプトアウトは可能であるべき
-
認可
- 複数ユーザーがいるシステムでは、アクセスできるデータや役割が異なる
check(user, object, action) パターンだけでもかなりのことができる
-
DBインターフェース
- アプリデータを保存する方法が必要
- ORMに近い方式が有用かもしれないが、もっと軽量な方式でもよい
- ログイン、認可、管理ツールで使われるため、基本コンポーネントになる
-
管理ツール
- ローカル環境や本番環境でアプリケーションを設定する際、最低でも1人のユーザーや一部データをブートストラップする必要がある
- 一般的な管理作業の一部は組み込みであるほうが、体験が滑らかになる
-
WebSockets
- 接続中のユーザーに対し、よりリアルタイムに近い形でデータをプッシュする機能を作れる
-
ホットリロード
- コードやテンプレートの変更ができるだけ素早く反映されるべきで、開発者体験において非常に重要
長く維持されるプロジェクトに必要な補強機能
-
バックグラウンドジョブ
- スケジュールに従って実行される機能が生まれるので、一貫した方法があると開発しやすい
-
モニタリング/可観測性
- 最小かつ重要度の低いシステムでない限り必要
- 本当に切実に必要になった瞬間に大きく役立つ
-
キャッシュ
- 実装方法は多く、どれも複雑さを増やし、速くなるかどうかも状況次第
- フレームワークレベルの話があるとよいが、ユーザーが自分で処理してもよい
-
メールと通知
- ログイン機能があるなら、パスワードリセットのためにメール機能が事実上必要になるかもしれない
- それ以外の通知機能は、必要になったときに追加しても大きな問題はない
-
デプロイツール
- 特定の場所へデプロイする一貫した方法があるとよい
- 選んだホストで使える自動生成Dockerfileだけでも有用
-
CSS/JSバンドル
- WebツールがCSSとJSを認識して自然に含められるとよい
- 必ず統合されるべきかははっきりしない
既存のRust Webエコシステムが残している空白
- RustにはWeb開発ツールがすでに多いが、望まれている統合型体験を目標にしているツールはない
-
ミニマルWebフレームワーク
- actix-webとaxumは、FlaskやSinatraのような小さなフレームワークに近い
- Rustの型システムを活用して良いWeb開発体験を提供するが、ハンドラ以外の追加機能はほとんど提供しない
- ほとんどのプロジェクトはこうしたミニマルフレームワークで作れるとしても、必要な機能を毎回自分でつなぐ必要があり面倒
-
SPAフレームワーク
- Dioxus、Leptos、Yewは、Rustをバックエンドとフロントエンドの両方で使い、フロントエンド描画にWebAssemblyを使う領域を埋めている
- Yewでdigital vigilを作った経験は楽しかったが、実際の本番環境で使いたいかは確信がない
- これらのフレームワークもそれぞれの目的には優れているが、依然として多くの接続作業が必要
-
個別ライブラリの寄せ集め
- テンプレート、ログイン、認可、WebSocketライブラリは数多くある
- 一部のプロジェクトやサンプルは複数コンポーネントを統合しているが、使うすべての断片を統合しているものは見つけにくい
- 動きの速いエコシステムなので、一部のサンプルは古くなっている可能性がある
- 「ただつなぐだけ」は結局、各ライブラリの動作を調べ、十分に理解する作業になる
スターターテンプレートでは解決できない保守
- 既存の方法は通常、actix-webやaxumのような基本フレームワークを選び、必要な断片を見つけて載せ、自分で接続していく流れ
- スターターテンプレートは初期の苦痛を減らせるが、保守負担は残る
- ライブラリを最新状態に保つ必要がある
- 互換性を壊す変更(breaking change)にも対応しなければならない
- プロジェクトがテンプレートから外れると、テンプレート変更を再マージするのが難しい
- 複数のプロジェクトを運営していると、1つのフレームワークを更新する代わりに、
n個のカスタムフレームワークをそれぞれ更新することになる
- 全体を担うWebフレームワークが、バージョン間のアップグレード案内を提供するほうが望ましい
- 互換性を壊す変更は起こり得るが、文書化できる
- 互いに統合されることを知らない2つのコンポーネントの相互作用の変化によって問題が起きる状況を減らせる
newtが目指すWebツールキット
- 理想的なRust Webフレームワークは、前述の機能に加え、優れたドキュメント、変更ログ、慎重なバージョン管理、互換性を壊す変更への対応、コミュニティを備えるべき
- 現時点でそのようなツールは存在せず、他の誰かが作っているかどうかもはっきりしない
- 進行中のツールはフレームワークというより、既存のビルディングブロックを意見のある形でつないだWebツールキットに近い
- このツールキットの名前はnicole's web toolkit、略して
newt
- public repository で公開されている
- まだ使える状態ではなく、最新の変更もまだpushされていない
- コントリビューションを受け入れる準備もまだできていない
newtの目標は、新しい小さなWebアプリを作るときに、何日も接続作業をする代わりに、数分で実際のプロジェクト作業を始められるようにすること
- 一部コンポーネントは必要に応じて最初から作る計画もある
- そのほうが簡単だったり、より一貫性のある形にできたりするかもしれない
- Rustエコシステムには、この種のツールキットが複数ある健全な状態が必要であり、他のツールも一緒に登場することを期待している
1件のコメント
Hacker Newsのコメント
Rocket(https://rocket.rs/) が著者の挙げたフレームワークに入っていないのは意外だった
自分で使ったことはなく、より規約の少ない axum/actix-web のほうが好きだが、理解している限りでは Rocket の目標は著者が求める バッテリー同梱フレームワークにはるかに近く、すでにかなり長く続いているプロジェクトでもある
非常に長い間、ビルドに nightly Rust が必要で、本番環境でフレームワークを使おうとする人にとってはこれが大きな欠点だった
また約2年間 0.5.0 リリース候補の状態に閉じ込められており、最新の安定版リリースは他の Rust Web フレームワークより大きく遅れていた。nightly が必要で、非同期サポートもまだなかった
0.5 の山を越えた今は改善しているかもしれないが、Rocket の開発履歴は Axum のような代替と比べると使うのをためらわせる
一つあるにはある: Poem[1]
著者は Flask に言及しているが、「必要なもの」セクションを見ると Flask もその要求を満たしているとは言いにくい。Django は本当に嫌いだが、そうした要件なら著者が描写しているものに最も近いのは Django だと思う
その意味では Poem も良い候補ではない。全体として Poem は FastAPI にかなり似ていて、これはほめ言葉に近い。Rust の Web フレームワークを5、6個使ったことがあるが、大半は初期設定でボイラープレートをかなりいじることになる。素早く結果を出したいならこれは問題だが、その点で Poem はよく合っている
actix は性能がかなり良いが、30ms 未満の応答を目標にしているのでなければ、そもそも actix を検討する理由は少ない。Pydantic のようなものが必要なら、ある程度やってくれるクレートもある: https://crates.io/crates/poem-openapi
[1] https://github.com/poem-web/poem
核心は「フレームワーク」であるという点だ
F# も一度試してみる価値がある
望む型システムの遊びはほぼ全部あり、必要なツールや便利機能も備わっている。大きな欠点があるとすれば、非同期処理やメモリ管理が Rust ほど時間を吸い取らないので、実際にビジネス要件を解決してしまう危険があることだ
それでも Microsoft と付き合う過程のどこかが、その空白を埋めてくれるかもしれない
OCaml や Haskell と比べるとどうなのか?
人気のない考えかもしれないが、Rust はシステム言語であり、Rust で Web 作業 をするのは労力の無駄だ
その用途には、はるかに優れた言語とエコシステムがある
Java と同じように、Rust でも接続プール共有のために依存性注入ができ、スレッドベースのバックグラウンドジョブもとても簡単に書ける
Google は最近の発表で、Rust 開発者が Go 開発者より効率や生産性で劣るわけではないと測定したと述べている [1]
Rust は素晴らしい言語であり、システムプログラミングだけに限定する必要はまったくない。はるかに多くのことができる
[1] https://www.ardanlabs.com/news/2024/rust-at-google/
軽量で、C/C++ や低レベルコードを簡単かつ高速に呼び出せ、ネットワーキングでも多くの制御権を与えてくれる。PHP のようなアプリケーション専用言語や nginx/apache の設定ファイルを学ぶ必要なしに、ほぼ何でも汎用的で直感的なやり方でできる
libmicrohttpd のようなものの Rust 代替 があればうれしいし、あれば使うと思う
組み込みプログラミングと Web プログラミングの交差部分も同じだ
それでも Django、.Net、Go のような選択肢が可能なら、Rust はたいてい悪い選択である可能性が高い
静的にコンパイルされた Web フレームワークは、Rails、Django、Flask のようなものよりメモリ/CPUを簡単に 1/10 から 1/100 しか使わずに済む
Python には Django、C# には ASP .NET Core、Ruby には Rails がある
Rust を Web 開発で本当に大きく伸ばしたいなら、フル機能ソリューション を作る必要がある
Rocket がたぶん最も近いかもしれないが、上で挙げたフレームワークほどバッテリー同梱ではない
著者が探しているのは ASP.NET Core の Rust 版 であり、それ自体に問題はない
選択肢と組み立てを好む人もいるが、多くの環境では選択を代わりにキュレーションしてくれるほうがはるかに生産的だ
「別の X が欲しかったらどうする? Y% もっと良いかもしれないのに!」という反応はよくあるが、統合そのものが非常に大きな価値を持つ点を見落としている。個々のライブラリは単体で見れば最高でも、互いに滑らかにかみ合わなければゴミの山になり得る
ASP.NET 8 でプログラミングするのが好きな理由も、テンプレートシステムが認証、注入、ルーティングなどとうまく合うかをまったく心配する必要がないからだ
loco-rs、poem、rocket への言及はないのか? すでに バッテリー同梱の体験 を目指すプロジェクトはかなり多い
こうしたプロジェクトが leptos のようなフレームワークと違う点は、案内してくれる CLI があることだ。Symfony で好きな点もそれで、自分が考える「怠惰」な部分もそこにある
https://shuttle.rs がある
フレームワークであるだけでなく、周辺の Web ボイラープレートを生成してくれるツールでもあるので、私の基準では十分に怠惰なやり方だと思う
この記事はいくつもの別の論点を一度に扱っているので、理想的にはそれぞれ別々に取り上げるべき
パターンマッチングがあれば、ルーターが必ずしも必要というわけではない。URL を分割して、静的/動的な変数を必要に応じてマッチさせればよい
認証はどの言語でも普通は自前で作るか、Firebase/Auth0 のような SaaS を使う形なので、必ずしも言語やフレームワークの問題ではない
CSS/JS ツールは、Dominator のような多くの Rust フロントエンドフレームワークにはあまり合わない。Dominator は JS ではなく Rust でできており、シグナルにスタイルを紐づけてリアルタイムに変わるようにするなど、独自のスタイリングアプローチがある
著者の言いたいことは理解できる。実際に記事のいくつもの項目を解決しようとして何度も探し回ったし、つらい思いもした。たとえば https://github.com/dakom/dominator-workers-fluent-auth は Cloudflare Workers フレームワーク上でここに出ている多くの作業を処理し、追加の要望である Fluent ベースのローカライズも加えている
すべてをやってくれるバッテリー同梱のフルフレームワークがあればよいが、多くの実際のプロジェクトは、そうした規範的な決定を変えて自分たちで実装する道を望むはずだ。Rust はフロントエンド Web でも十分に成熟しており、どこを見ればよいかさえ分かれば wasm-bindgen などですべて扱える
Web フレームワークは URL リダイレクト、末尾スラッシュの処理、大文字小文字を区別する URL の管理、複雑な正規表現マッチングなど、はるかに多くのものを提供する
「認証はどの言語でも普通は自前で作るか SaaS を使う」というのは間違い。Django、Laravel、Rails やバッテリー同梱の言語では、認証管理が非常に優れている。個人的には、組織の 90% では認証を外部業者に任せるのはとんでもない失敗だと思う
熟練した Web 開発者が不要な複雑さに対処せず、1 日で基本的な CRUD を 10 個すぐに立ち上げられるというのは、小規模事業者にとって本当に大きな利点だ
この記事が Rust ではなく C++ に焦点を当てていたとしても、だいたい同じことが成り立っただろうか?
参入障壁の高いシステム言語であり、コンパイル時間もあり、広く使われるようになってから 10 年も経っていない言語が Rails のようなものとアクセシビリティで競うことを期待するのは無理がある