天然パーマです。

How I/we got 2k stars

Honoという僕が作っているWebフレームワークのGitHubスター数が2,000に迫ってきた。これまで作ってきたOSSのソフトウェアでは最高で revealgo221、次点で gh-markdown-preview134だ。それが一気に2,000である。

もちろん、スターの数がソフトウェアの良し悪しを決めるものではない。 それに2,000はとりわけ多いわけではない。 でも、以前の自分には遥か彼方に見えていた数を獲得できたのは、とても嬉しいことだ。

去年12月から作り始めて9ヶ月間、552コミット。 今や使ってくれる人も増えた。 cdnjs のAPI Serverのバックエンドにも使われているし、 HonoをきっかけにGitHubスポンサーをしてくれている企業や人も現れている。 なにより、いろんなことを勉強させてもらった。 今回はHonoというプロダクトがどうやって2,000のスターを獲得してきたかをトピックごとに振り返る。

Trie木

Honoは当初、Cloudflare Workers向けのルーターとして作られた。 当初参考にした公式ドキュメントには泥臭いコードが書いてあった。

async function handleRequest(request) {
  if (request.method === "GET") {
    if (url.pathname.startsWith("/foo")) {
      return new Response("foo");
    }
  }
  return new Response("Not Found", 404);
}

これを見て「うーん」と唸ったのがルーターを作るきっかけだ。 サードパーティのルーターはいくつかあるが 「せっかくなので自作してみよう、どうせならTrie木を使って速いルーターを作ってみよう」 そう思ったのだ。

Trie木とはアルゴリズムの一種で、URLのパスマッチングに向いている。 他のCloudflare Workers向けルーターではこれを用いたものはなく、リニアにマッチングさせるものばかりだ。 リニアとはつまり、配列にルートパターンを入れておき、アクセスが来たらその配列を頭からなめて、 対象のURLと正規表現で比べていく方法だ。ルートが増えるととたんに遅くなる。

一方Trie木では、いくらルートが増えてもオーバーヘッドが極力少なくて済む。

Trie木の実装は、以下の記事を参考にさせてもらった。

ある程度形ができると「外国の方にうけそう・Cloudflare向け」ってことで「Hono」という名前をつけて リポジトリを作成。 他のルーターと差別化を図るため、キャッチフレーズに「Ultrafast web framework」を採用した。 2021年12月15日が 記念すべき「Initial Commit」の日となった。

Web Standard

これでモダンにルーティングを書けるようになった。 以下が当時のREADMEに残っていたコードである。 最後に app.fire() と書くのがポイントだ。

// 今のAPIとは違います。
const Hono = require("./src/hono.js");
const app = new Hono();

app.get("/hello", () => {
  return new Response("Hello!", {
    status: 200,
  });
});

app.fire();

これをよりフレームワークっぽくしていく。 といっても、そんなに大変なことではない。 フレームワークに必要なRequest/Responseオブジェクトはもう既に提供されているからだ。

以前からWebフレームワークを作るが好きだった。 Perlを使っていた当時、Plackが出てきた時がアツかった。 おそらく2009年のことだ。 フレームワークとサーバとの共通フォーマット「PSGI」ができて、そのツールキットとしてPlackが登場する。 PSGIでは「ステータスコード、ヘッダ、コンテンツ」のプリミティブな配列をレスポンスして返却するというルールがある。 ただ、リクエストをハンドリングするにはENVを覗かないといけなく扱いが面倒。 そこで、Plack::Request を使う。

use Plack::Request;

my $app_or_middleware = sub {
  my $env = shift;
  my $req = Plack::Request->new($env);
  my $path_info = $req->path_info;
  my $query = $req->parameters->{query};
  # ...
};

Plack::Requestを使っていくつも「出来損ないのSinatra」を作っては投げ出し、というのを繰り返したものだ。 つまり、Plack::Requestのようなリクエストオブジェクトが提供されていればフレームワークは簡単に作れるということが分かっていた。

Cloudflare Workersの場合も同じようにRequest/ResponseがWeb StandardのAPIに準拠して提供されている。 勝手は同じだ。 唯一違ったのは途中で投げ出さなかったことだ。

「we」

ちょこちょこと機能追加と改善をしつつ年末を迎えた。 「俺の考えた最強のフレームワーク」を作ってる感覚が非常に楽しい。 Issueに「TODO」という名前で巨大なタスクリストを作って、一個一個潰していった。

そこへ現れたのが @metrue さん。 12月30日のことだ。

突然で驚いてしまった。

Honoはミドルウェア機構を備えていた。 ハンドラーが呼ばれる前、もしくはその後に実行させるよく使う処理を書けるのがミドルウェア。 ユーザーが自身で書くこともできるし、 基本的なものはビルトインとしてフレームワークが提供することを目指していた。 例えば、カスタムヘッダーを追加したければ、以下のように書けばOK。

// Add a custom header
app.use("/message/*", async (c, next) => {
  await next();
  c.header("x-message", "This is middleware!");
});

@metrue さんは「Loggerミドルウェアを書きたいんだ」とTODOのIssueにコメントをしてくれたのだ。 来る者を拒む理由はない。 まずは、Basic認証のミドルウェアを作ってもらった。 Cloudflare Workersは、Basic認証が基本で備わっていないのが面倒なのだが、 このミドルウェアで簡単に追加できるようになった。 素晴らしい。

app.use(
  "/auth/*",
  basicAuth({
    username: "hono",
    password: "acoolproject",
  })
);

その後 @metrue さんにはLoggerミドルウェアの実装や、CI、Linterの設置などをやってもらうことになる。

さて、やり取りをしていて気になったのは一人称が「I」ではなく「We」と書いてあったこと。 それからは僕も「We」をよく使うようになった。 例えば「Bearer認証ミドルウェアが欲しい」って時はこう書くだろう。

We need Bearer Auth middleware.

その時はたった二人の「We」だった。

RegExpRouter

@metrue さんの次に現れたが @usualoma さんだ。 彼はとんでもないものを投下することになる。

2月14日のバレンタインデー。ひとつのPRが作られた。@usualoma さんの登場である。

これが素晴らしくて、Namedパスパラメータに自動的にTypeを足すというもので、 DX=Developer Experienceの向上に大きく貢献している。 つまり、 /entry/:date/:id というルート定義を書くと、 c.req.param() で取得する際に補完が効く。

いきなりでかめのPRだったので若干面食らったんだけど、採用することにした。 そして次に来たのがこれ。Honoのベースとなっているのが「TrieRouter」だけど、 @usualoma さんはもう一つのルーター「RegExpRouter」を提案してきたのだ。

発想がすごい。他では配列や木構造で扱ってきたルート定義を、予め巨大な「ひとつの正規表現」にして、それを使って一発でマッチさせるというやり方。

上記のPRの文面から引用すると、つまり以下のようなルートがあるとする。

  • /help
  • /:user_id/followees
  • /:user_id/followers
  • /:user_id/posts
  • /:user_id/posts/:post_id
  • /:user_id/posts/:post_id/likes

それを以下のような一つの正規表現にしておくのだ。

^/(?:help$()|([^/]+)/(?:followe(?:es$()|rs$())|posts(?:/([^/]+)(?:/likes$()|$())|$())))

たださえTrieRouterが速いのに、より高速だ。 その速さが分かるように、ベンチマークを掲載する。 現在のスコアだ。

以下は、他のCloudflare Workersのルーターと実用的なルーティングの速度を比べたスコア。

hono - trie-router(default) x 437,354 ops/sec ±4.58% (83 runs sampled)
hono - regexp-router x 535,157 ops/sec ±3.46% (83 runs sampled)
itty-router x 203,092 ops/sec ±3.64% (89 runs sampled)
sunder x 308,252 ops/sec ±2.17% (91 runs sampled)
worktop x 190,764 ops/sec ±3.11% (86 runs sampled)
Fastest is hono - regexp-router
✨  Done in 38.26s.
// Scripts: https://github.com/honojs/hono/tree/main/benchmarks/handle-event

何よりすごいのは、Node.jsの他のルーターと比べても2番目なこと。 速いと呼ばれているFastify内部の「find-my-way」に勝っている。

find-my-way : 1,346,661 ops/sec
call : 592,211 ops/sec
express : 295,514 ops/sec
koa-router : 238,465 ops/sec
koa-tree-router : 2,068,932 ops/sec
router : 283,153 ops/sec
routr: 254,927 ops/sec
server-router : 530,983 ops/sec
trek-router : 1,343,688 ops/sec
Hono trie-router : 514,753 ops/sec
Hono reg-exp-router : 1,788,048 ops/sec <--- No.2!!
// Scripts: https://github.com/honojs/node-router-benchmark

追記すると後述するBunで動かすと、このランタイムは正規表現が得意なので、ダントツに速い。 No.1だ。

もう叫ぶしかないね。

ウルトラファスト!!!!!!

ちなみに、実はこれ、RegExpRouterがオリジナルというわけではなく、 PerlのRooter::Boomでとられていた手法である。 また、複数の文字列からひとつの正規表現の文字列をプログラムで生成する Regexp::Assemble というモジュールもある。

RegExpRouterなど、@usualoma さんによる高速化は以下のスライドにまとまっています。

v1.0.0

4月22日、記念すべき「v1.0.0」がリリースされる。

バージョニングの方針はソフトウェアによってまちまち。 それにHonoの場合、今でこそセマンティックバージョニングを意識しているが、当時は少しいい加減だ。 だから「これをもってしてv1.0.0である」と判断するのが難しかったが 「えいやっ」でリリース。一人前になった気がする。 この時点でスターは「300」程度。 同時に「APIを簡単に変えられないぞ」というプレッシャーがかかる。

宣伝

地味な宣伝活動をしていた。

例えば、Cloudflare Workers公式のドキュメントには「Templates」という形で、各言語やフレームワーク別にスターターキットのリンクを掲載している。そこに載せてもらった。これは結構簡単で、公式ドキュメントのGitHubリポジトリにPRを出せばよい。特にリジェクトされることも、放置されることもなく無事取り込まれ、掲載される運びとなった。

ユーザーに直接訴えかけられるという意味ではDiscordが有効だった。 Cloudflareには開発者向けのDiscordがある。 その中でも「#what-i-built」というチャンネルがあるので、そこでまず「私はこれを作りました」と宣伝をする。 最初は、その投稿にただスタンプが押されるだけだったが、 「Honoを使ってみたよ」という他の人のポストもあったり、質問がメンション付きで飛んでくることもあった。 Discordは右上のウィンドウから全チャンネルの投稿から検索できるので、 それで「エゴサ」しつつ、みんながどんな会話をしているのか、特に「#workers」を中心に覗くようにしている。

最近、Discordでは「workers-libraries」という掲示板のような機能ものができてて、そこに「Hono」の「板」が立ってる。 ユーザーからの質問が貼り付けられるので、見つけては適当に答えているという具合だ。

CloudflareのDiscordは雰囲気もよく、暇つぶしと優良な情報源になっている。

英語

当然ながら、GitHubでもDiscordでもやり取りは英語である。 @metrue さんはおそらく中国の方で首尾一貫して英語。 @usualoma さんは日本の方だけど、GitHub上では英語。 つまり全部英語である。

僕は英語がだいぶできない。特に書くのは難しい。 だけでも頑張って書いてる。 「英語で簡単に書くにはどういう文にすればいいのだろうか?」を考える。 なるべく受動態は使わないようにする。

サービスにも頼る。DeepLとGrammarlyを使っている。 Grammarlyはスペルミスに加え、文法ミスやクリアにするための言い換えなども指摘してくれる。

頭の中に英文が浮かんだ時には一回構成して、だいたいできたらDeepLに入れて確認。 意味がおかしくなければ、それをフォームに貼り付ける。 Grammarlyでスペルと文法がミスがないかをチェックする。 英文がひらめかなくても、なるべく主語が明確で平易な日本語をDeepLに書き込めば、分かりやすい英語ができる。

不思議なもので、英語で書いてると、普段よりも強気な発言ができる気がする。 英語は主語を明確にしなくてはいけなく、命令形も多いからという英語の性質もあるだろう。 それに「OSSプロジェクトの『メイン』メンテナとしての自分」が降りてくるからじゃないかと思っている。

The long struggle in May

@metrue さんと @usualoma さんと僕の3人はときおりIssue上で激論を交わすこととなる。 「Discussion: hono.use #189」では39コメント。 「Processed handler should be only one #262」では32コメントだ。

二人とも自分の意見を持っていて「違うものは違う」と言う。 #189 は @metrue さんの「ミドルウェアとハンドラーを同じように扱うのはどうか」という問題提起から始まった。 これまでは、パフォーマンスと実装の簡潔さを保つため、ミドルウェアとハンドラーを分けて扱っていた。 僕は突っぱねることもせず、話の妥協点を探る。 そこへ @usualoma さん登場。 @usualoma さんは挙動可能なコードを書いて、実装の解決策を考えてくれる。

#189 の議論は #262 でも再び行われることとなったが、 結果的に「ミドルウェアもハンドラーも同じように扱われるが、Responseオブジェクトを返すか返さないかでハンドラとミドルウェアかが区別される」というバランスの良い仕様と実装が決まった。 これで我々の5月の戦いが終わったのだ。

honojs organization

これまで github.com/yusukebe/hono で開発していたものを honojs というOrganizationの下に移した。 リポジトリのURLは https://github.com/honojs/hono になった。

さらに、最近では @metrue さんと @usualoma さんを Organization のメンバーに加えた。

PRのレビューやプロジェクトの管理のプロセスを分担するのは面倒なので、 これまで通りやることは変わらない。 でも、僕一人のプロジェクトより、3人いた方が外から見た時の信頼感に繋がる。 万が一、事故にあったり、病気になったり、死んだ時にはなんとかしてくれるかもしれない。

Batteries-included

Honoをやっていて一番嬉しかったことについて書く。

Cloudflare Workersの開発からデプロイまでを担うWranglerというCLIがある。 以前から、リポジトリをウォッチしていたのだが、 その中で活発に活動をしていたメンテナがthreepointoneだ。 Issueのコメントが丁寧でかつ論理的でかっこいい。 あとアイコンもかっこいい。 そう認識してから尊敬するようになった。

とある日、Twitterに見知らぬアイコンからのメンションが来たと思ったら、 そのthreepointoneだった。GitHubのアイコンとは全然違うじゃん。

This looks like a pretty neat batteries-included framework for Cloudflare Workers! Nice work @yusukebe

バッテリーインクルーディッドがどんな意味かは分からなかったがとにかく嬉しかった。

Deno

そうこうしているうちに7月。 次の「v2.0.0」の目玉機能はDeno対応だ。

Honoは当初からCloudflare WorkersとFastly Compute@Edgeに対応していた。 同じWeb StandardのAPIを使っているのでDeno対応も「ワンチャン」あると以前から思っていた。 問題は「するかしないか」だ。 サポートする範疇が増えると、その分、問題の発生率も上がる。 でもやることにした。 だって、HonoがDenoで動くところをみてみたい。

大きく2つの工程が必要だった。

  1. DenoはTypeScriptの制約がよりキツいので、それに対応させる。
  2. denoifyというコマンドで、Deno用のコードをジェネレートする。

「1」が大変だったけど、なんとか完了。 Denoはimport元がURL、拡張子をつけなくてはいけないという点で、通常のNodeモジュールとは違う。 それをdenoifyが補ってくれるというわけだ。 出力されたDeno用のディレクトリdeno_distを指定すれば、deno.land/xで公開することができる。

結果的に、importとエントリポイント以外はCloudflare Workersと全く同じコードが使えるようになった。

import { serve } from "https://deno.land/std/http/server.ts";
import { Hono } from "https://deno.land/x/hono/mod.ts";

const app = new Hono();

app.get("/", (c) => c.text("Hello! Hono!"));

serve(app.fetch);

Deno対応をして非常によかった。 Honoは次に対応するBunを含め、少なくとも4つのラインタイムで動く。

  1. Cloudflare Workers
  2. Fastly Compute@Edge
  3. Deno
  4. Bun

例えば、VercelのEdge FunctionsのバックエンドはCloudflare Workersだったり、 Supabase FunctionsはDeno Deployで動いてたりするので、プラットフォームという観点だとより多くの環境で動作する。

Deno対応はあくまで好奇心でおまけ程度になるのかな、なんて思っていた節もあったが、 あがってくるIssueを見ると「Denoで使っている」というケースをよく目にする。 先日驚いたのは、Deno本体のプロジェクトで使われていることだ。ベンチマーク向けらしい。

PRには「Honoを使ったベンチマークでは、BunよりもDenoの方が高速である」と書かれている。 そこへ、当のBunの作者Jarredが登場した。 「Honoは今のBunでは十分パフォーマンスが出せていない」と発言。 その後、Bun本体のチューニングをしてより高速化させるのだ。

あんまり書くとネタバレになってしまう。 とにかくDeno対応は成功した。

v2.0.0

7月16日、「v2.0.0」をリリースした。

特出すべきはDenoとBun対応、それにサードパーティミドルウェアを実現するための構造作りだ。 いくつかのミドルウェアの撤廃し、ContextやRequestにメソッドを追加した。 膨らんでしまったビルトインミドルウェアをスリムにして、 他は @honojs/graphql-server といった名前空間から 利用できるようにするのだ。

v1.0.0からの追加点を列挙すると以下の通りだ。

  • Content-Length自動追加の廃止
  • チェインルーティング
  • JWT Auth Middleware
  • Envに型情報を追加できるようにした
  • ルーターがマルチマッチに対応
  • ハンドラとミドルウェアを同等に扱えるようにした
  • app.routeの実装
  • Namedパラメータの名前が重複した際にエラーを出すように
  • Contextにset/getを追加
  • ミドルウェアのModule Workersモードサポート
  • StatusTextをデフォルトで設定しないように
  • 複数のクエリ値に対応
  • ルーティングの優先度を変更
  • Bearer Auth Middleware
  • 分かりやすいエラー
  • noFoundでasyncをサポート
  • JSX Middleware
  • html Middleware
  • c.executeCtxの追加
  • Serve Static Middlewareにpathオプションを追加
  • Denoサポート
  • Serve Static MiddlewareのDeno対応
  • Bunサポート
  • Serve Static MiddlewareのBun対応
  • Basic Auth MiddlewareのBun対応
  • GraphQL Middlewareの廃止
  • c.parseBody()の追加、parsedBodyプロパティの廃止
  • Body Parse Middlewareの廃止
  • Mustache Middlewareの廃止
  • c.req.cookieの追加
  • c.cookieの追加
  • Cookie Middlewareの廃止
  • サードパーティミドルウェアへの対応
  • 高速化

BREAKING CHANGEを含んでいたし、しっかりと「Migration Guide」を書いた。

そしてなによりHonoのWebサイトを立ち上げたのだ。

これを機にスター数は一気に増え、1,000を超えた。

Bun

Honoがこれほどまでスターを獲得できた大きな要因のひとつが「Bun」だ。

BunはJavaScriptCoreをベースとした新しいJavaScriptランタイムである。 Node.jsでもDenoでもない。Bunはちょうどv2.0.0がリリースされる直前に一般公開された。 公開されるとたちまち話題を呼んだ。 公式ホームページにはNodeとDenoとのベンチマーク結果が記載されており、 圧倒的に速い。それらに取って代わるJavaScriptのスタンダードになるのではないかと注目されたのだ。

BunはHTTPサーバーの実装向けに、Web Standard APIを提供している。 なので、簡単にBunに対応させることができた。 最低限ならばCloudflare Workersと全く一緒でよい。

import { Hono } from "hono";

const app = new Hono();
app.get("/", (c) => c.text("Hello! Hono!"));

export default app;

Bunjs support · Issue #344 · honojs/hono」というIssueが立つが、 それはもう済んでいた。

BunではWeb Standardが使えるが、 逆に言えば、それら以外にWebアプリを作る手段がない。 つまり、Expressが動かないのだ。 これが重要なキーになる。 BunのDiscordを覗いていると「BunでExpressは動かないのか?」という質問がたくさん上がっていた。

そこで白羽の矢が立ったのがHonoである。 HonoのAPIはExpressを参考にしていて、かなり近い。 Cloudflare Workersでの運用実績もある。 何より、どこよりも早く「Bun対応」を謳ったフレームワークだ。 「Expressは現在のところサポートしていません。その代わり、今はHonoを使うことができます」 という定型文ができたのだ。

  1. Bunが登場する
  2. BunでExpressを使いたい
  3. BunではExpressが使えない
  4. その代わりHonoを使ってください
  5. Honoが使われる

この論法が成立すると、スターはうなぎのぼりとなる。

あらよあらよと8月に入る頃には1,500を超えた。

ところで、この展開には布石があった。 先程threepointoneのツイートを紹介したが、 そのツイートに反応していたひとりが実はBunの作者、Jarredだったのだ。 「BunはCloudflare Workersと基本的に同じAPIを備えているから、同じようにHonoが動くかもしれない」と返信している。 Bunが一般公開される前の5月19日の出来事だ。

なんというか感慨深い。

さらに面白いのは、最近、こんな発言をしている。

「Bunにおける最大の失敗の一つは、Expressに対応させなかったことだ」。

HonoはCloudflare、Deno、Bunとランタイムが乱立するど真ん中にいる気がして、実にエキサイティングだ。

政治

1,000を超えたあたりから周りの動きが変わってきた。

投資家が声をかけてくれた。 この人は割とすごい人で、serverless.comなど名だたるOSSを主軸としたビジネスを展開している組織に投資をしている。 「Honoをビジネスにするつもりはない」と言うと残念がったが、 一度話をしようとZoomで30分ばかり話した。 英語が全く喋れなかったが、お互い話は通じた。 HonoはFastifyのようなOSS・コミュニティを築いていきたい。 もし、今後チャンスがあって気が向いたら「Next.jsとVercel」のバックエンド版、 つまりHonoというOSSのソフトウェアがあって、それをホスティングするサービスを展開するのもいいね、なんて話をした。

「一緒にやらないか」と言い寄ってくる人もいる。 その人もそれなりのソフトウェアを作ってる人で、面白い提案だなって思うんだけど、 必要ないので断った。

Contribution Guideも書いた。 僕の個人的な趣味から発展したもので、 いくら素晴らしい提案があっても、採用されないこともあるよ、と冒頭に明記した。

サードパーティミドルウェアを第三者が作るに当たっての制度づくりも必要だ。 命名規則だけではなく、GitHubリポジトリやnpm registryのアクセス権限の管理方法など。

「スポンサーは受け付けていないのか?」と聞かれた。 これまで「スポンサーの意向にプロダクトが左右される可能性がある」という理由でやっていなかった。 その人は「口出しはしない」と言ってくれたので考え直した。 そして、GitHub Sponsorをやることとなる。 honojs organizationでやることもできたが、配当とかを考えるとめちゃくちゃ面倒なので、個人で。 その代わり、黙ってやるのは失礼なので、@metrue さんと @usualoma にその旨は伝えた。 おかげさまで、すでに6人の方からスポンサーをしてもらっている。感謝します。

ここまで来て思うのはこうだ。

OSSは政治だ

もちろん極端な言い方だけど、プロジェクトをマネージするという観点に立てば、政治的要素を考えなくてはいけなくなる。

ただ、別に嫌いなものではなかった。 いわゆる一般的な「政治」とは違い、コードを中心に回っているからかもしれない。 僕/私達が書いてきたコードとそれを使っているユーザー。 それこれそが正しいのだ。

エコシステム

v2.0.0になって、コアのAPIはほぼ固まった。 Requestオブジェクトについて検討してもいいが、それ以外は不満がない。理想のAPIだ。 これからやろうとしているのは、サードパーティミドルウェアを作っていくエコシステムを回していくことだ。 ミドルウェアを以下3つに定義した。

  1. カスタムミドルウェア
  2. ビルトインミドルウェア
  3. サードパーティミドルウェア

カスタムミドルウェアは、ユーザー自身が自身のアプリで書くもの。 ビルトインミドルウェアは外部ライブラリに依存せず、Hono本体に組み込まれるもの。 例えば、Basic認証、CORSやETag、JSXとhtmlなどだ。 そしてサードパーティミドルウェアは、外部ライブラリに依存してOKで、第三者のデベロッパーが開発できるもの。 それをなるべく、honojs organizationのリポジトリで開発してもらって、@honojs 以下の名前空間で公開してもらう。 例えば、 hello という名前のミドルウェアならばこうなる。

  • リポジトリ => github.com/honojs/hello
  • パッケージ名 => @honojs/hello

今のところ以下の4つのミドルウェアがある。

なんでもかんでもMiddlewareにする必要はないが、 Honoというソフトウェアを中心により多くの開発者が貢献をできる仕組みができると嬉しい。

Future Plan

以上、ここまでこれまでの話。 では未来の話をしてみよう。 投資家にも「Future Planはあるのか?」と聞かれた。 取り立てて大きな理想はない。 今はより多くの人に使ってもらってフィードバックをもらうフェーズだ。 ドキュメントと上記したエコシステムを回すこと、バグフィックス。 それが直近やることになるだろう。 あとは細かいこと。

もし、手伝ってくれるのであれば大歓迎だ。

4つのランタイムの勢いはこれからもさらに増すだろう。 Cloudflare WorkersにD1が来るのが象徴的だ。 Honoがその中心にいることができたらいいなと思う。

Love

Honoを作っていて嬉しい瞬間はたくさんある。 IssueやPR、Discordのやりとりで初対面の人から、かなり高い確率で「Great Work!」とお褒めの言葉をいただく。 作者冥利に尽きる。

Just for Fun

Trie木を作っていた頃と比べてやることは増えた。 Issueであがってきた問題の再現をしたり、 PRのレビューをしたり、Discordの質問に答えたり、ドキュメントを書いたり。 夕食を食べてから寝るまでの時間を全て費やすこともある。 それでも続けていられるのはこれしかない。 楽しいからだ。 楽しかったから、僕/私たちは2,000個の星を集めることができたのだ。

全てのユーザー、コントリビューター、スポンサーに感謝。