はじめに
近年、Webアプリケーションの開発においては多様な技術スタックが存在しています。
筆者は最近、小さなWebアプリの個人開発ではDeno + Fresh + Honoという技術スタックを採用しています。 それぞれの概要と、良いと感じている点について簡単にご紹介します。
Deno
Denoとは、JavaScript / TypeScriptのランタイムです。
(マスコットの恐竜がかわいらしいです。公式にアートワークのページがあったりします。)
(ブラウザを除き)JSランタイムのデファクトスタンダードといえばNode.jsでしたが、
近年はNode.js以外のランタイムも開発されており、Denoはそのうちの1つです。
DenoはNode.jsの作者であるRyan Dahl氏によって作成されており、Node.jsにおける反省点を改善するように設計されています。
2024年10月にv2.0がリリースされ、以後は1カ月ごとにマイナーアップデートされる計画となっています。 2024年11月には初の長期サポート版であるv2.1がリリースされ、同時に有償サポート(Deno for Enterprise)も発表されました。
Denoの特徴を下記にいくつかピックアップします。
- TypeScriptが標準サポートされている
- ts-nodeのインストールやtsconfig.jsonの用意も必要なく実行できます。
(最近はNode.jsでも実験的サポートが導入されました)
- ts-nodeのインストールやtsconfig.jsonの用意も必要なく実行できます。
- パーミッションシステムによる高いセキュリティ
- デフォルトではファイルシステムやネットワークへのアクセスが制限され、必要に応じて許可を与えます。
- ツールチェーンの内蔵
- リンター/フォーマッターやテストランナー、Language Serverなどが提供されています。
(公式サイトでは、Batteries includedなどと表現しています。)
- リンター/フォーマッターやテストランナー、Language Serverなどが提供されています。
他にもいろいろな特徴・利点がありますが、個人的に気に入っているのが
deno lint / deno fmt(リンター/フォーマッター)とDeno KVです。
deno lint / deno fmt
リンター/フォーマッターは、今や開発における必須ツールと言っても過言ではありませんが、JavaScriptのスタンダードなリンター/フォーマッターであるESLint/Prettierは、リポジトリを作るたびに導入や設定を行うにはやや手間に感じる部分がありました。
先述した通り、Denoは開発で必要になるツールチェーンを初めから提供してくれており、リンターやフォーマッターの機能をCLIのサブコマンド(deno lint / deno fmt)で実行することができます。 セットアップの手間がなくなり、思い立ったらリポジトリを作ってコードを書き始める…ということが素早くできて便利です。
動かすだけなら設定も不要で、始めやすさという観点でとても嬉しいです。
もちろん、deno.jsonという設定ファイル(Node.jsにおけるpackage.jsonのようなもの)を作成して、各種ルールの設定を変更することもできます。
ただ、よく使われる一般的なルールに関してはデフォルトで設定されているので、Denoにおいてはデフォルトに従っておけば問題ないと思います。(設定の手間もなくなるので)
VSCodeの拡張機能も提供されており、導入すると、
Denoが提供するLanguage Server(deno lsp)を利用するコード補完などが行えるようになり、VSCode上でのフォーマットもdeno fmtで行えるようになります。(Marketplaceのページに設定例が掲載されています)
Deno KV
Deno KVは、Denoが提供するデータベース(キーバリューストア)です。
これもDenoに組み込まれているので、セットアップ不要で利用できます。
(2025年2月時点ではまだUnstable な機能なので、APIの破壊的変更などが発生する可能性があります。)
JavaScript / TypeScriptで利用することを前提に作られていることもあり、JavaScriptで扱う様々なデータを保存できます。
プリミティブな値はもちろん、ObjectやArray、Map、DateやRegExpなども扱えます。
APIも分かりやすく、公式ページのクイックスタートを見れば問題なく利用できると思います。
キーが配列になっていることが特徴的で、値にはstring / number / boolean / Uint8Array / bigintを利用できます。
RDBとは異なるので、テーブルのような概念はありませんが、キーの設計により複数のテーブルがあるかのようにデータを分割できます。
公式サイトに掲載されている例ですが、 ["users", <ユーザーID>, "profiles"] で特定ユーザーのプロフィールを保存したり、
["users", <ユーザーID>, "preferences"] で設定を保存したり…といった具合です。
キーの一部をプレフィックスとして指定して、データを取得することもできるため、
["users", <ユーザーID>] で特定ユーザーのプロフィールと設定を一括で取得したり、
["users"] で全ユーザーのデータを一括で取得したりもできます。
(楽観ロックの)トランザクションも利用できるので、小さなWebアプリのデータ永続化先としては十分な機能を備えています。
また、Denoに組み込まれているのでローカルで動作するのはもちろん、
同じくDenoが提供するDeno Deployというサーバーレスなホスティングサービスからも利用できます。
(Denoで動作するJavaScript / TypeScriptのアプリケーションをデプロイして公開することができるサービスです。)
Deno Deploy上から利用する場合は、ローカルで動作するコードのままでよく、接続先の設定変更なども必要ありません。 こういった点も含めて手軽に扱えるので、個人開発では重宝しています。
Fresh
FreshはDeno公式のWebフレームワークです。
Show caseにも掲載されていますが、
Denoの公式サイトもこのFreshで作られています。
レンダリングにはPreactが使用され、コンポーネントはJSXで実装するため、Reactの経験がある方は特に違和感なく使えると思います。 Next.jsのようなファイルシステムルーティング(ファイルベースルーティング)なども提供されます。
また、FreshはIsland Architectureを採用しています。
MPAとして動作し、デフォルトではサーバーサイドでレンダリングされますが、
インタラクティブな動作が必要な場合は『必要なコンポーネントのみ』ハイドレーションを行い、
JavaScriptの読み込みなどのオーバーヘッドを減らすような設計になっています。
Denoのnpmサポートも進んでいるので、他のフレームワークも基本的には動作しますが、 公式のフレームワークということもあり、DenoでWebアプリを開発するなら選択肢になると思います。 (v2のアルファ版がJSRに登録されており、正式リリースが待ち遠しいです。)
Hono
Honoは、日本人発のWebフレームワークです。
正規表現ベースのルーティングを採用していて動作が非常に速く、 元々Cloudflare Workersで動作するフレームワークとして開発されていたこともあり、バンドルサイズも軽量です。
どんなJavaScript / TypeScriptランタイムでも動く、を特徴としていて
Node.jsでもDenoでもBunでも動作するうえ、 Cloudflare Workersはもちろん、
Deno DeployやVercel、AWS Lambdaなど様々なエッジ環境でも動作します。
APIも直観的で分かりやすく、ミドルウェアについても(ビルトイン / サードパーティ含めて)豊富で、 カスタムミドルウェアを自作するのも簡単です。
サーバー - クライアント間でリクエスト / レスポンスの型を共有する、RPC機能がサポートされている点も魅力的です。
リクエストパラメータの型定義はもちろん、レスポンスについてもステータスコード毎に型推論でき、
フロントエンド / バックエンドどちらも型安全に実装することができます。
エディタ上で強力に補完が効くため、開発体験も非常に良いです。ぜひ使ってみていただきたいです。
(作者の方が公開したRPC機能の紹介記事もありますので、ぜひご覧ください。)
また、Web標準をベースとしている点も扱いやすさを高めています。
FreshのハンドラーもWeb標準に準拠していて、Requestオブジェクトを受け取りPromise< Response >を返すようなIFになりますが、
Honoの.fetch()も同じIFとなるため、FreshのAPIサーバー部分をHonoで置き換えたりも簡単にできます。
(筆者はこの構成を使っています)
Honoをベースとした、HonoXというメタフレームワークがあり、(まだアルファ版ではあるものの)こちらも扱いやすくて良いです。
ただし、Denoで利用する場合、Viteとの互換性の問題で、開発サーバーがやや不安定なので、
Deno + HonoXでの開発はもう少し安定するまで待ちたいと考えています。(ビルド後のコードは問題なく動作します)
おわりに
筆者が最近採用している技術スタックについての紹介でした。
あくまでも個人開発における技術選定であり、今回紹介したものはいずれも比較的新しいので、
プロダクトでの採用は難しいケースもあるかもしれませんが、興味を抱くきっかけになれば幸いです。