Honoのコミット記録
4.3.7以降の変更
内部的な型のリファクタリング
型関係のリファクタリングのようです。特に表立ってのインターフェースが変更されたわけではありません。
Set Cookieが正常生成されない不具合修正
import { setCookie } from "hono/cookie";
const app = new Hono();
app.get("/does-not-work", (c) => {
setCookie(c, "hello", "world");
setCookie(c, "hello", "world2");
const res = new Response("does not work");
return c.body(res.body, res); // <-- this
});
上記のサンプルコード c.body(res.body, res) のようにレスポンスオブジェクトの初期値を渡してレスポンスを生成する場合にレスポンスヘッダーの Set-Cookie が正常に返却されないという不具合の修正です。
hono/jsxの forwardRef を使用したコンポーネントで ref を必ず渡す必要がある不具合修正
import { forwardRef } from 'hono/jsx'
const DivComponent = forwardRef((props, ref) => {
return <div {...props} ref={ref} />
})
function Render() {
return <DivComponent /> // <-- type error(ref not specified)
}
上記のサンプルコードのように forwardRef を使用すると ref のpropsを渡す必要があるという型になっているが、optionalでも問題ないように型の修正が行われています。
上記の変更で 4.3.8 がリリースされています
4.3.8以降の変更
CreateHandlersInterface の型定義をexportするように変更
import type { CreateHandlersInterface } from 'hono/factory'
上記のコードで factory.createHandlers の生成する型を使えるようになったようです。
ALBのマルチバリューヘッダー設定に対応
同キーのクエリパラメータ(http://www.example.com?&myKey=val1&myKey=val2 など)がある場合に multiValueQueryStringParameters としてAWS Lambdaに送信します。それの対応が行われました。
上記の変更で 4.3.9 がリリースされています
4.3.9以降の変更
Secure Headers Middleware の Node.js依存の解消
Secure Headers Middlewareは nonce 属性に設定する際のbase64値をNode.jsのAPIに依存していましたが、Node.jsに依存しない変更が行われました。この変更でCloudflare WorkersでSecure Headers Middlewareを使用する場合は nodejs_compat の compatibility_flags の設定が必要でしたが、不要になります。
4.3.9以降の変更 その2
Status Codeが指定のコードで返らない場合がある不具合の修正
ちょっと特殊ですが HTTPException を使用した例外をスローした際のStatus Codeが返らず、例外となった元のResponseオブジェクトのStatus Codeで返ってしまうという不具合の修正です。具体的には以下のコード例で400が返らず、200が返ってしまうということの修正が行われました。
app.get("/example-a", (c) => {
throw new HTTPException(400, {
res: new Response("An exception", { status: 200 }),
});
});
304を返す場合のヘッダー設定をHonoから提供
304を返す場合に設定するヘッダー設定(ETag)をHonoからPublicな設定として提供されるようになりました。これにより304のヘッダーを設定するのが用意になります。
import { etag, RETAINED_304_HEADERS } from 'hono/etag'
app.use(
'/etag/*',
etag({
retainedHeaders: ['x-message-retain', ...RETAINED_304_HEADERS],
})
)
上記の変更で 4.3.10 がリリースされています
4.3.10以降の変更
JWT Auth Middlewareの secret に設定漏れがあった場合に正しいエラーメッセージを表示するように修正
JWT Auth Middlewareを使用する場合に secret を設定が必要ですが、secret が undefined など定義されていない場合はJWTの検証エラーとなりエラー理由がわかりにくいため、secret が設定されていない場合にはその旨のエラーを表示するように修正されました。
上記の変更で 4.3.11 がリリースされています
4.3.11以降の変更
JWT Auth Middlewareの secret に設定漏れがあった場合に正しいエラーメッセージを正しいメッセージに修正
メッセージに "secret ではなく "secret" とダブルクォーテーションが抜けていたメッセージの修正です。
4.3.11以降の変更 その2
4.4.0の内容がマージされてるので昨日の内容とコミット順が前後します。
JSDoc によるドキュメントの追加
JSDoc によるドキュメントが大量に追加されています。コミットを1つ1つ書くと多くなってしまうので纏めます。
JSRのサポート
4.4.0からJSRがサポートされました。JSRからHonoがインストールできるようになっています。
req.paramsの型を見やすい型に変更
今までRequest Handlerの引数から取得する req.params で複数のURLパラメータがある場合は
type params {
version: string
} & {
id: string
}
となっていましたが、これが1つに纏まって
type params {
version: string
id: string
}
と表示されるようになるリファクタリングです。
内部関数である convertFormDataToBodyData のリファクタリング
この convertFormDataToBodyData の役割を詳しく追ってないのでなんのための関数かわかりませんが、内部的なこの関数の FormData 生成のために2重で生成されていたが FormData を1つの変数で生成できるようにリファクタリングが行われています。
上記の変更で 4.4.0-rc.1 がリリースされています
この4.4.0の正式版へのコミットがされていますが、多いのでまた後日。
4.4.0-rc.1以降の修正
4.4.0まで別ブランチで開発してたものが多く数が多いので特に重要ではないものは軽くしか触れません。
READMEへJSRバッジの修正
DenoからJSRにバッジの表示を変更しています。
JSRへPublishするためのCIのトリガーの修正
tagがPushされたら実行するように変更
Deno環境でのベンチマークプログラムの import パスの変更
Denoで実行しているベンチマークプログラムはsloppy importsという機能を使ってimportを解釈されるパスに変更されました。
HonoのESLintルール変更
@hono/eslint-config が 0.0.6 にUpdateされ、そのルールに沿ったコードに修正されています。
JWT Auth Middlewareの型定義のexportを追加
JWT Auth Middlewareの JwtVariables SecureHeadersVariables TimingVariables の型がexportされて使用できるようになりました。
JSDocの追加
module系のドキュメントの追加です。
Honoで使用されるReactのバージョンの取得が可能になるように修正
Honoに依存したReactのライブラリを作成する場合にReactのバージョンにより処理を分岐できるようにHonoが使用するReactのバージョンを取得できるようにする修正がされました。
READMEに CODE_OF_CONDUCT.md などのリンク追加
各種ドキュメントのリンクがREADMEに追加されました。
上記の変更で 4.4.0 がリリースされています
この4.4.0のリリース以降もコミットがされていますが、多いのでまた後日。
4.4.0以降の修正
Pretty JSON Middlewareの クエリパラメータに pretty が存在するかどうかの条件式から不要な条件式を削除
全体のコードとは若干異なりますが、上記のような三項演算子の条件までは不要なため削除されました。
- c.req.query('pretty') === '' ? true : false
+ c.req.query('pretty') === ''
ALBのマルチバリューヘッダー設定の対応で multiValueQueryStringParameters より queryStringParameters が優先されてしまう不具合の修正
ALBのマルチヘッダー設定の対応がされましたが、 multiValueQueryStringParameters と queryStringParameters の両方が送信される時に queryStringParameters を優先してパラメータを取得してしまい、パラメータが送信されてくるパラメータが欠損してしまうという不具合が修正されました。
if (event.multiValueQueryStringParameters) {
...
} else {
...
}
となっているので multiValueQueryStringParameters がある場合はそちらを優先して取得するという変更です。
Objectに指定したプロパティが存在するかどうかの判定に Object.hasOwn() を使用するリファクタリング
HonoのAWS LambdaアダプターでALBのProxy判定に Object.hasOwnProperty() が使用されていましが、 Object.hasOwn() を使用するようにリファクタリングが行われました。
Object.hasOwn() はドキュメントにある通り Object.hasOwnProperty() の代わりに使用できるように設計されおり、 Object.hasOwn() の使用を推奨されています。また、HonoはNode.js環境ではversion 16以上が動作保証環境になっており、Node.jsでも Object.hasOwn() が使用できるので問題ないそうです。
hono/client で FormDataに配列を設定できるように修正
HonoでRPC機能 を使って hono/client からサーバに送信するする際のFormDataに同一キーのデータつまり配列を送信できるように修正されました。
const res = await client.posts.$post({
form: {
title: 'Hello',
body: 'Hono is a cool project',
list: ['listA', 'listB'] // <-- It has never been sent correctly
},
})
これが可能になっています。
SSGを行う際のパス生成で2階層以上の親のパス(../../)が正常に生成されない不具合修正
SSGを行う際は内部的に joinPaths という関数を呼びますが、この関数を以下のように呼び出すと正常にファイルパスが生成されない不具合が修正されました。
ただし、これは saveContentToFile という experimentalなAPI に影響する不具合の修正です。
import { saveContentToFile } from 'hono/ssg'
await saveContentToFile({
data: new Promise((resolve) => resolve({ routePath: '..', content: 'test', mimeType: 'text/plain'})),
fsModule: fs,
outDir: '..',
})
一旦28日分までを纏めて記載。29日分は後で追記する予定。
4.4.0以降の修正 その2
ちょっと量が多いのはmainブランチの最新に追いつくためです。
Pull Request templateにドキュメント追加確認のチェックボックスを追加
4.4.0でJSDocによるドキュメントの追加がされましたが、以降はドキュメントをメンテナンスしていく上で修正や追加、削除などがある場合にドキュメントを合わせて修正する必要があるということになりそうです。
Honoに定義しているRoutingに request する場合に duplex が設定されずにエラーになる場合がある不具合の修正
Body Limit Middlewareを使用していてかつ、@hono/node-server を使用していない場合に以下のようなコードで内部ルーティングを呼び出すとエラーになります。
import {Hono} from 'hono'
import {bodyLimit} from 'hono/body-limit'
const app = new Hono()
app.use(bodyLimit({maxSize: 100 * 1024})) // 100kb
app.post('/hello', async (context) => {
return context.json({message: 'Hello, World!'})
})
const response = await app.request('/hello', { // <-- This is where the error occurs
method: 'POST',
body: JSON.stringify({foo: 'bar'}),
})
これは内部ルーティングではReadable StreamをBodyに設定して送信しますが、Readable Streamを送信する場合は duplex を設定する必要がありますが、設定されていないことでエラーになるそうです。
@hono/node-server を使用する場合にエラーにならないのは @hono/node-server の内部にてReadable Streamを送信する場合に duplex を付与するロジックが含まれているためです。
WebSocketのEvent型から onOpen など呼び出す際にオプショナルチェーンを使って呼び出すようにするリファクタリング
今までは events.onOpen && events.onOpen(evt, wsContext)) のようにEvent型の変数に onOpen の存在確認を行ってから呼び出していたが、それをオプショナルチェーンを使うようにリファクタリングされました。
- events.onOpen && events.onOpen(evt, wsContext))
+ events.onOpen?.(evt, wsContext))
BunのWebSocket Helperを使用する場合に Context に server を渡せるように修正
BunでWebSocketを使用する場合は、下記のコードでいう req からServerオブジェクトを取り出していたが、Context に server を渡せるようになり、指定できるようになる変更がされました。
(ちょっとこれは説明があってるか自信がないです)
import { createBunWebSocket } from 'hono/bun'
const { websocket } = createBunWebSocket()
Bun.serve({
fetch(req, server) {
return app.fetch(req, { ip: server.requestIP(req), server }) <-- `server` can be passed
},
websocket,
})
ドキュメント系のファイルが変更されてもCIでテストが動かないように修正
paths-ignore を設定して特定ファイルの変更はCIが動作しないように修正されています。
CIのテスト環境にNode.jsの22が対象に追加
Node.jsの22は10月からLTSに入るので先んじてテスト環境に追加されました。
src/* のTSDocの追加
src/compose.ts や src/context.ts の src/ 直下のファイルにTSDocが追加されました。
hono/testing の testClient で型エラーを起こす不具合の修正
hono/testing の testClient で basePath を使用した以下ようなテストを書くと型エラーが発生する型修正が行われました。
import { Hono } from 'hono';
import { testClient } from 'hono/testing';
const app = new Hono().basePath('/mybasepath');
const route = app.get('/items', async c => c.json({ id: 2 }));
type AppType = typeof route;
const api = testClient<AppType>(app); // <-- If app is specified as an argument here, a type error will occur.
v4向けのブランチをCIの対象外とする修正
v4はすでにリリースされているため不要なため削除されました。
一部のランタイム判定に navigator.userAgent を使用するように修正
Deno, Bun, Cloudflare Workers, Nodeは navigator.userAgent から取得した値でどの環境下なのかを判定するように修正されました。
これらの4環境は navigator.userAgent をWinterCGで策定された要件通りに実装しているようです。
JSXのスタイルに数値を渡すと正しく反映されない不具合修正
以下ような数値のスタイルを渡すとスタイルに px が付与されてしまい正しくスタイルとして認識されない不具合が修正されました。
<div style={{ "--hue": 10, "--text": '#000' }}>test</div>
{/* output: <div style="--hue: 10px; --text: #000"> */}
以前ALB対応で追加された setHeadersToResult が未使用なので削除される
ALBの対応で追加されたものが未使用のコードがあったため削除されました。
JSON APIの Content-Type をサポート
JSON APIの仕様で Content-Type に application/vnd.api+json のようなドットを含んだ文字列が入ることがありますが、今までドットを受け入れてなかったので HTTPException が発生していましたが、それを発生しないようにする修正がされました。
hono/testing の testClient の型を修正
testClient 内で any が使用されていますが、その一部を使用しないで済むようにリファクタリングが行われました。
以上が29日までにmainブランチに行われたコミットです。
4.4.0以降の修正 その3
CONTRIBUTING.md のコードブロックのシンタックスハイライトの形式を変更
マークダウンのコードブロックのシンタックスハイライトの言語指定が txt になっていましたが、コマンドなので bash に変更されました。
重複する型定義の修正
手前味噌ですいません。先日の src/ 直下にTSDocが追加されたコミットのdiffを見たら気づいたのですが、同一の型定義が作成されてしまっていたので1つ削除されました。
以上が30日までにmainブランチに行われたコミットです。
後日 上記の変更で 4.4.1 がリリースされています
4.4.1以降の修正
戻り値の型指定を行うようにリファクタリングを実施
どうやら4.4.1のリリースを行ったが、JSRのリリースが正常に行えていなかったようです。その原因がこの戻り値の型指定がなかったためとあります。JSRのリリースに戻り値の型指定が必要ということでしょうか?私もJSRにはまだリリースしてないのでなんとも言えないのですが、そういう風なコミットのようです。
- function test() { console.log('test') }
+ function test(): void { console.log('test') }
上記の変更で 4.4.1 改め 4.4.2 がリリースされています
4.4.2以降の修正
リリースするためのワークフロー名を release に変更
GitHub Actionsでリリースを行っていますが、リリースするためのワークフロー名が ci だったので release という名称に変更されました。
letによる変数宣言を無くすリファクタリング
意図があってるか不明ですが、 let で宣言されていた変数を const で定義するためのリファクタリングが実施されました。
ただ、コードを見るに try {} catch {} の try 内の最後に return つまり返り値はあるのですが、 catch で例外を潰しつつ、返り値がないのはどういうことを意味するのかちょっとわからなかったです。
4.4.2以降の修正 その2
リリースCIのJSRへのpublishジョブ名の変更
JSRに対応したため、ジョブ名もdenoからJSRに変更されました。
いくつかモジュールについてJSDocの追加
JSDocでのドキュメント管理にするために更にいくつかのモジュールについてドキュメントが追加されました。
CodeCovによるカバレッジレポートの追加
CIで各ランタイムのテストなどが実行された後にテストのカバレッジが計測されるようになりました。
JSRに移行した旨の記載がREADMEに追加
4.4.0以降はJSRにHonoがリリースされるので以前の deno.land/x にはリリースされない旨と deno.land/x から JSR への移行方法が追記されました。
また、4.3.11から4.4.0へは特にbraking changeが発生していない旨も合わせて追記されています。(このスクラップを読んでる人にはくどい説明かもしれません)
4.4.2以降の修正 その3
カバレッジバッジをREADMEに追加
先日カバレッジレポートの対応が行われましたが、カバレッジのパーセンテージがREADMEに表示される対応がされました。
DenoのWebSocketのonOpenイベントがトリガーされない不具合を修正
DenoでWebSocketへの接続を行う upgradeWebSocket 内で遅延処理つまりPromise処理があると onOpen のイベントがトリガーされないという不具合が修正されました。
const app = new Hono()
app.get(
'/ws',
upgradeWebSocket(async (c) => {
await new Promise(resolve => setTimeout(resolve, 5e2)) // Simulate time-consuming operation
return {
onOpen: () => console.log('opened') // can't be trigger
}
})
)
Pull Requestにあったサンプルのままですが、上記のようにPromiseがあると動作しないという不具合が修正されています。原因としてはEventの生成処理前に upgradeWebSocket を呼んでること原因のようです。
Cloudflare WorkersでWebSocketの接続を行う場合にhttp statusに101が返らない不具合の修正
Cloudflare WorkersでWebSocketを接続する場合にはhttp statusが101が返っていないため接続できない不具合が修正されました。
CIでの wrangler というランタイム名称を workerd という名称に変更
細かい話ですが wranlger はあくまでCLIであり、Cloudflare Workersのランタイムは workerd ということでランタイム名が正しい名称に変更されました。
ランタイム名の変更に伴いテストなどのファイル名の配置ディレクトリ名やテストの describe なども同じく修正されています。
workerd 環境下でのWebSocketのテスト追加
その名の通りCloudflare Workers環境下でのWebSocketのテストが追加されました。
今まではWebSocketの接続ルーティングをもったHonoアプリケーションに対して、WebSocketではないルーティングへのアクセスのみがテストとして定義されていましたが、WebSocketの接続ルーティングへ接続を行い open message close と一通りのイベントが動作するかのテストが追加されました。
またこのコミットにもコメントにもありますが、 workerd 環境下の unstable_dev を使ってWebSocketの接続を行うには ws のパッケージが必要になるようです。
AWS Lambda adapterの型定義ファイルを1つに纏めるリファクタリング
AWS Lambdaのadapterには2つのカスタムの型ファイルが存在していました。2つ存在するとそれぞれの使用用途が明確でなく、型ファイルの追加を行う場合にどちらに追加するか迷うことが発生するため1つに纏められました。
カバレッジから型定義のみのファイルは除外するように修正
カバレッジを計測しますが、型定義のみのファイルはカバレッジの対象に含める必要はないので、その修正が行われました。
4.4.2以降の修正 その4
hono/quick と hono/tiny のテスト追加
hono/quick もしくは hono/tiny のテストかどうかというのは表現的に怪しいですが、Honoはv4で getRouterName というヘルパーが追加されましたが、hono/quick か hono/tiny で作成されたHono インスタンスに対して getRouterName で名称が取得できるかどうかというテストが追加されています。
非公式のhttp statusの型名のタイプミスを修正
http statusには200や404といった公式なステータスと218や520といった非公式なステータスが存在します。
Honoでhttp statusを指定する場合に非公式なステータスを使用する場合は今まで UnOfficalStatusCode と型名がつけられていましたが、正しくは UnofficialStatusCode (3文字目のオーが小文字) という名称に変更されました。ただ、今すぐ以前の UnOfficalStatusCode の型名が使用できるのではなく deprecated ですが使用することは可能です。
app.mount 時にアクセスのあったルーティングパスのRequestオブジェクトを指定できるように修正
Honoには mount という機能が存在します。 mount はHonoやHono以外のルーティングをHonoのルーティングで上書きするというような機能です。
import { Router as IttyRouter } from 'itty-router'
import { Hono } from 'hono'
// Create itty-router application
const ittyRouter = IttyRouter()
// GET /itty-router/hello
ittyRouter.get('/hello', (request) => new Response(request.url))
const app = new Hono()
app.mount('/itty-router', ittyRouter.handle)
この例では IttyRouter では /hello を定義していますが、それをHonoがマウントして /itty-router/hello で元の IttyRouter のルーティングにアクセスできるようにするというものです。
しかし、この例で書いてるように IttyRouter 側では本来 /hello で受けているので本来であればレスポンスの中の request.url は /hello のはずですが、HonoがマウントしているためHono側で受けたRequestつまり /itty-router/hello となります。もちろんこれはそもそも受けているRequestがそうなので間違いではないですが、 IttyRouter 側からすればマウントする親がどうなっているかというのは考える必要はない場合もあります(リクエストパスで何か処理をしたいのであれば自分が定義したパスだけで考えたい場合など)。
そこで、本来の /hello のルーティングアクセスのRequestオブジェクトを渡せるように mount の受け入れれる引数に新たな指定方法が増えました。
import { Router as IttyRouter } from 'itty-router'
import { Hono } from 'hono'
// Create itty-router application
const ittyRouter = IttyRouter()
// GET /itty-router/hello
ittyRouter.get('/hello', (request) => new Response(request.url))
const app = new Hono()
app.mount(
'/itty-router',
ittyRouter.fetch,
{
replaceRequest: (req) => req
}
)
replaceRequest オプションを渡すことでHonoで受けたRequestではなく、IttyRouter 側 /helloのRequestをそのまま渡せるようになりました。 replaceRequest だけでなく optionHandler というものも渡せて、これは従来の ittyRouter.handle と同等のハンドラーも指定できるようになっています。
上記の変更で 4.4.3 がリリースされています
4.4.3以降の修正
src/request.test.ts 内のテスト内容のTypoを修正
テスト内容のTypoが修正されました。
Honoのエラーハンドリングで受け取る引数で HTTPException クラスを使用しないように修正
HTTPException というものが、Honoのエラーハンドリングに渡された場合は HTTPException からエラーのResponseを取得してクライアントに返す処理というものがあります。
しかし、この HTTPException の独自クラスかどうかという判定のためにimportされており、HTTPException をimportすることで常に HTTPException 分のファイルサイズ (260B) がバンドルサイズに含まれることを懸念して、importせずに同等のことができるようにという修正がされました。(涙ぐましいがこういう努力が嬉しいですね)
requestハンドラー内でResponseオブジェクトを返さず終了した場合のエラーメッセージをわかりやすメッセージに修正
ニュアンスとしては「たぶんResponseオブジェクトのreturnを忘れてるよ」から「Responseオブジェクトのreturnを忘れない?」って感じのエラーメッセージに修正されています。
Honoの開発環境をGitpodで使用できるように .gitpod.yml を追加
GitpodというCodespacesみたいなもの?で開発環境が即座に作成できるように .gitpod.yml が追加されました。
4.4.3以降の修正 その2
getConnInfo がexportされていない不具合修正
Honoには ConnInfo Helper というリクエスト元の情報を取得できるヘルパーがあります。ドキュメントの記載どおりに hono/cloudflare-workers からimportするとエラーになるという不具合が修正されました。
4.4.3以降の修正 その3
ミドルウェアを使用しないハンドラーで Response を返さない場合は404 Responseを返すように修正
ミドルウェアを使用しないしないルーティングで非同期のハンドラーでResponseを返さないと404なるという動きがあるようですが、同期のハンドラーの場合はレスポンスが返されずエラーになっていました。
そこで同期のハンドラーでもResponseを返さないと404 Responseを返すという修正がされました。
const app = new Hono()
app.get('/async', async () => {
return // <-- 404 Response
})
app.get('/sync', () => {
return // <-- error
})
同一型定義の削除
Hono内部のユーティリティの型に Prettify と Simplify という同じ型定義ありましたが、同一なので Prettify が削除されました。
配列を返すJSONをRPCのインターフェースとして使用すると型が never になる不具合修正
JSONはオブジェクト( { "foo": "bar" } )から始まる形式と配列( [{ "foo": "bar" }])から始まる形式の両方が可能ですが、配列から始まる形式をJSONとして返すハンドラーをRPCの型として読み込むとハンドラーの返り値の型が配列の型ではなく never になる不具合が修正されました。
import { Hono } from "hono";
// server
const app = new Hono()
.get(
'/test',
async c => {
return c.json([{ foo: 'bar' }])
}
)
export type APP = typeof app
// client
import { hc } from "hono/client";
const client = hc<APP>('http://localhost')
const resp = await client.test.$get()
const result = await resp.json() <-- type of result becomes `never`
HonoのRPCにリダイレクトによる型のサポートを追加
HonoのRPCに使用するハンドラーの中でリダイレクトを行う分岐などがあると型情報が正常に取得できない問題がありました。この修正でハンドラー内でリダイレクトを行った場合でも型情報が取得されるようになりました。リダイレクトがされる場合を考慮してクライアント側は記述する必要があるということです。
const routes = app.get('/profile', (c) => {
if (!flag) {
return c.redirect('/')
}
return c.json({ name: 'abc' }, 200)
})
const client = hc<typeof routes>('/')
const res = await client.profile.$get()
if (res.status === 302) {
console.log(res.headers.get('Location'))
} else {
const data = await res.json()
// ^ { name: string }
}
hono/jsxで for 属性のサポートが追加
label タグなどでよく用いられる for 属性が新たに使用できるようになりました。ただし、for をそのまま指定するのではなく、Reactと同様に htmlFor として属性を指定すると for として出力されるようです。
アンダーバーやハイフンを含む拡張子のファイルを静的ファイルとして配信できない不具合の修正
そのままなのですが、ファイル拡張子にアンダーバーやハイフンを含むファイルが404になってしまう不具合が修正されました。
RPC内部で型のために内部で使用するプロパティ名と同名のプロパティを持つオブジェクトが返却できるように修正
HonoのRPCでは型情報のためのプロパティ(data, status, format)が存在しますが、それと同名のプロパティを持つオブジェクトをハンドラーで返してしまうとRPCの型情報が正しくなるということがありました。そこでHonoのためのプロパティについてはアンダーバーから始まる名称に変更されました。
配列を返すJSONをRPCのインターフェースとして使用すると型が never になる不具合修正(の追加修正)
先ほど配列を返すハンドラーをRPCとして使用すると型が never になる不具合の修正を記載しましたが、それの追加修正です。
発生条件を詳しく見ていないですが、配列にネストした配列を入れると never になる不具合が追加で修正されました。
静的ファイル配信で404の場合にファイル検索が2回動かなくていいように修正
静的ファイル配信を行う処理で404の場合に配信ファイルの検索が2回動いていた処理ロジックが1回で済むようにリファクタリングされました。
カバレッジのレポート出力にテキストファイルとHTMLファイルの出力を追加
カバレッジレポートの出力は今まではJSONだけでしたが、ローカルなどでの確認が行いやすいようにテキストとHTMLファイルの出力も追加されました。
ConnInfo Helper の型定義ファイルの配置場所を変更
今までは src/helper/conninfo/index.ts に直接定義されていましたが、型定義は src/helper/conninfo/types.ts に移して export する形にリファクタリングされました。
上記の変更で 4.4.4 がリリースされています
4.4.4以降の修正
カスタムのVery Headerを設定できるように修正
今まではVery Headerは無条件で Origin が設定されていましたが、カスタムの値を設定できるようになりました。PRでも書かれていますが、CloudflareのPolishを使用する際にこの変更が必要な場合あるための修正です。
HonoでhtmxとTypeScriptを使用する際のライブラリの typed-htmx による型定義が行えない不具合の修正
Honoとhtmxを組み合わせて使用する際に typed-htmx というライブラリを使用することでJSXの属性に型定義を行えるようになるらしいです。
これが4.4.0のリリースから動作しない不具合が修正されました。原因としてはJSRの対応でGlobalを使用しての定義を削除したことで動作しなくなったらしいです。JSRの対応でGlobalは使用できないので、新しくJSXという名前空間で定義してそれを使用することになったようです。
app.route の第二引数を必須化
4.0以前は任意の引数だったのですが、4.0以降は指定しないことは非推奨とされていました。そこで今回、その非推奨だった第二引数を必須化する変更です。
(ただ、v4のリリースノートやマイグレーションのドキュメント見ても非推奨になりますという記述が見つけられなかった)
app.on の第一引数の必須チェックを削除するリファクタリング
これだけ見るとなぜこの行がそもそも存在していたのか不明ですが、元々第一引数は文字もしくは文字の配列が型として定義されていますが、それが無い( if (!method) )場合は自身を返すという無駄なチェックは必要ないということでチェック処理が削除されました。
4.4.4以降の修正 その2
Context 内のプライベート変数の不要な初期化を削除
Context 内に持つプライベートな変数( _var )が {} で初期化されていましたが、そもそも初期化が不要なので undefined を許容するという変更がされました。 _var は Variables を保持する内部変数ですが、値の格納や取得時に _var 自体が存在しているかのチェックがあるために不要という判断をしたようです。
また、このコミットで Context のカバレッジをあげるためにテストも追加されています。
Honoのベース処理保持ファイルのカバレッジを100%にするためにテストを追加
Honoの基本機能( ErrorHandler や MiddlewareHandler など )を保持している src/hono.ts とそれに付随する src/hono-base.ts のカバレッジを100%にするためにテストが追加されました。
ResponseのJSONまたはテキストの型をジェネリックで指定する場合にステータスコードの型は省略できるように型を修正
HonoではJSONもしくはテキストを返す場合に c.json や c.text といったRequestHeaderの Context の引数からレスポンスを生成できますが、これをジェネリックで指定することも可能です。しかし、ジェネリックで指定する場合は返すJSONやテキストの型とステータスコードを指定する必要がありました。c.json などはそもそもステータスコードを指定せずともデフォルトのステータスコードでResponseが生成されるのでこれをジェネリックでも可能とする型修正が行われました。
app.get('/', (c) => {
return c.json<Array<{sample: string}>>([{ sample: 'test1' }, { sample: 'test2' }]) // <-- You do not need to specify the second StatusCode in the json generic type specification.
})
リクエストのBodyをparseする内部処理の中で条件にマッチしないチェック処理を削除するリファクタリングを実施
Hono内部でRequestのBodyをparseする parseBody という処理の中に存在する特定の if 文は必ずマッチしないため不要な条件チェック処理ということで削除するリファクタリングが実施されました。
リファクタリングを行っただけなので、特に振る舞いなどが変わることはありません。
4.4.4以降の修正 その3
JSXに指定された属性をHTMLタグの属性に変換する処理をリファクタリングし、コードサイズを小さくする修正を実施
HonoのJSXはReactと同様に className や htmlFor といった通常の属性とは異なる属性を指定することで通常の class や for 属性に変換する処理があります。このリファクタリングではJSXの属性をまずはHTMLタグの属性としてすべて扱ってから、JSX独自の属性をHTMLタグ属性に変換したものを足した後にJSXで指定された独自の属性を消すという処理になっていましたが、そもそもJSXの属性からHTMLタグ属性に変換する際にJSXの属性をそのまま追加するか、変換してから追加するかという単に属性を追加していくロジックにリファクタリングされました。
このリファクタリングによりバンドルサイズ(minifyあり)ベースで77bほどサイズが小さくなるようです。
上記の変更で 4.4.5 がリリースされています
4.4.5以降の修正
AWS Lambdaの環境でStream Responseを返す際にSet Cookieが正常に行えない場合がある不具合の修正
AWS LambdaのランタイムでStream Responseを返す際にResponseの headers に set-cookie を複数設定したとしても1つしか設定されないという不具合が修正されました。
上記の変更で 4.4.6 がリリースされています
4.4.6以降の修正
c.html の返り値の型は引数に応じて Reponse もしくは Promise<Response> となるように修正
今までは c.html の返り値の型が常に Response もしくは Promise<Response> となっていました。しかし、c.html の第一引数が非Promise(例えば文字列)の場合は Promise<Response> の返り値とならないように型修正が行われました。
4.4.6以降の修正 その2
hono/client 内で使用されているObjectのマージに関するテストをケース通り行うようにテストを修正
HonoにはRPC機能がありますが、その中で使用する hc に関するリクエストの処理でクライアント側からオプションを追加で渡すことができます。その渡したオプションをデフォルトのオプションにマージしてリクエストを行うという deepMerge という関数が内部に存在しますが、そのテストに関する修正です。
振る舞いとしては Object ではないオプションが渡された場合はそのオプションをそのまま投げるという処理になっていますが、テストケースが正常に実行されるようにテストが修正されました。
同一のテストケースの削除
Honoが独自に定義する Request(HonoRequest) で .text() や .json() などRequestのBodyから指定の形式でデータを取得する処理のテストが重複して定義されていたのが削除されました。
4.4.6以降の修正 その3
ContextVariableMap と Env(Variables) と同名のキー定義がある場合に Env の型を ContextVariableMap の型で上書きしてしまう不具合修正
HonoのContextには ContextVariableMap という型定義があります。これはmiddlewareなどで Context に値を設定する場合に定義するものですが、これが middleware に定義した Variables の型定義を壊してしまうというものの修正です。文字を読んだだけではわからないので、PRにあったコードを拝借して説明します。
declare module 'hono' {
interface ContextVariableMap {
test: 'root'
}
}
const middleware = createMiddleware<{
Variables: {
test: 'override'
}
}>(async (c, next) => {
c.set('test', 'override')
await next()
})
まず ContextVariableMap で test というキーに root という文字列が入るという型定義をしています。次に createMiddleware は Variables つまり Env の型定義に同名の test というキーで override という文字列を設定しているという型定義の2つを作成します。
const router = new Hono()
.get(
'/test',
middleware,
async c => {
const testValue = c.get('test') // test type is 'root'
return c.text(testValue) // However, the testValue variable contains `override`.
},
)
c.get で test というキーでデータを testValue の変数に格納しています。この時 testValue の型は root という文字列の型になるが、実際には override という文字列が入っているというのが今回の不具合の内容です。
上記の変更で 4.4.7 がリリースされています
4.4.7以降の修正
変数に明示的に型を設定
hono/jsx 内部で使用する変数に明示的に型を設定する修正がされました。これはJSRがslow typesになっている警告を修正するものです。要は型を推論に任せるよりも明示的に設定した方が型の決定が早くなるために行ってほしいというものらしいです。
Codecovを動作させるためのトークンの環境変数の設定方法を変更
HonoにPull Requestを作成した場合に Codecov によるカバレッジの計測が行われていましたが、トークンが正常に設定されていないというエラーが発生していました。正しくトークンを設定するように修正されました。
JSDocのタイポ修正
ドキュメントのタイポが修正されました。
DenoのWebSocket接続時のOptionを設定できるように修正
DenoでWebSocket接続時にオプションを指定することができますが、DenoでHonoを使用する場合にWebSocket Helperではそれが対応されていませんでしたが、このコミットにより使用できるようになりました。
使用するには upgradeWebSocket の第二引数に指定することで使用できるようになります。
app.get(
'/ws',
upgradeWebSocket((c) => {
return {
onMessage(event, ws) {
console.log(`Message from client: ${event.data}`)
ws.send('Hello from server!')
},
onClose: () => {
console.log('Connection closed')
},
}
}, { idleTimeout: 60 })
)
4.4.7以降の修正 その2
Accepts Helper内で行うリクエストヘッダーのパース処理速度を更に向上させる修正を実施
HonoにはAcceptsヘッダーを処理するためのヘルパーが存在します。内部の処理ではRequest Headerに設定されているAcceptsの内容を読み取る時に、スプレッド構文を用いて、以下のようにAcceptをパースしています。(実際のコードとは少し異なるが似たようなサンプルです)
const acceptHeader = c.req.header('Accept') // Accept: text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8
const accepts = acceptHeader.split(',') // ['text/html', 'application/xhtml+xml', 'application/xml;q=0.9', 'image/webp', '*/*;q=0.8']
return accepts.map((accept) => {
- const [type, ...params] = accept.trim().split(';') // ['application/xml', 'q=0.9']
+ const parts = accept.trim().split(';') // ['application/xml', 'q=0.9']
+ const type = parts[0]
...
}
この処理の中で重み値である ; の除いた実際の値を取得するための処理をスプレッド構文を使うより1つの配列に一旦格納してから実際の値を取得するといったコードの方がパフォーマンスが向上するということで変更が行われました。
4.4.7以降の修正 その3
utils/buffer.ts のテストカバレッジをあげるためにテストを追加
utils/buffer.ts の中に equal という関数がありますが、これはHonoの中では使用されていません。しかし、ユーザが使用するかもしれないということで残す決定をしましたが、それならば振る舞いを保証する必要があるためテストコードが追加されました。
Bunのテストでは標準機能を用いてLCOV形式のカバレッジレポートを生成するように修正
Bunは1.1.16からテスト実行におけるカバレッジのレポートをLCOV形式で出力できるようになったようです。そこでBunの環境では1.1.16にバージョンをあげて、テストによるカバレッジレポートをBun標準の機能を用いて出力するように変更されました。
テストコードにおけるVitestの不要なimportを削除
HonoのテストではVitestが使用されていますが、Vitestの describe や it といったAPIはglobalsの設定がされているので、 import は特に必要ありません。そこで import してしまっているテストから不要なVitest import を削除する修正されました。
4.4.7以降の修正 その4
指定された2つの値をそれぞれハッシュ化する関数を並行処理するようにしてパフォーマンスを改善
Basic Auth MiddlewareやBearer Auth Middlewareでは渡されたユーザ名やパスワード、トークンといったものが設定値と同等かどうかを調べるために timingSafeEqual というHono内部で使用する検証関数が存在します。その timingSafeEqual の関数では渡された値とハッシュ化する関数を通して値が2つの値が同値になるかという処理がありますが、それぞれ直列処理していたコードを並行処理に変えてパフォーマンスをあげるという変更が行われました。コミット内容そのままですが以下の変更です。
- const sa = await hashFunction(a)
- const sb = await hashFunction(b)
+ const [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)])
上記の変更で 4.4.8 がリリースされています
4.4.8以降の修正
Context生成時にHonoRequestオブジェクトを事前に生成して保持するのではなく、必要時に生成するように修正
Request毎にHandlerで使用するContextを生成しますが、生成時にオリジナルのRequestオブジェクトからHono独自のRequestオブジェクトつまり、 HonoRequestというオブジェクトを生成してそれをContextに設定していました。しかし、これは使用しなれば無駄な生成コストであるため、処理の開始速度を早めるためにContextの初期では HonoRequest を生成せず、 HonoRequest を取り出す時に生成するようにしました。これにより HonoRequest を使用しないリクエスト処理時間が早くなります。
よくある手法ですが、以下のようにプライベートな変数に生成した結果を保持しておき、2回目以降は変数にすでに生成済みの結果を返すようになっています。
get req(): HonoRequest<P, I['out']> {
this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult)
return this.#req
}
ミドルウェアを使用してルートをChainしていくとContextの型が正しくなくなる不具合を修正
Issueにあったコードを拝借して説明します。
import { Hono, MiddlewareHandler } from 'hono'
const mw1: MiddlewareHandler<{ Variables: { foo1: string } }> = async (c, next) => {
c.set('foo1', 'foo1')
await next()
}
const mw2: MiddlewareHandler<{ Variables: { foo2: string } }> = async (c, next) => {
c.set('foo2', 'foo2')
await next()
}
const app = new Hono()
.get('/1', mw1, async (c) => {
// this is correctly typed.
return c.json({ foo1: c.var.foo1 })
})
.get('/1-then-2', mw1, mw2, async (c) => {
// this is also correctly typed.
return c.json({ foo1: c.var.foo1, foo2: c.var.foo2 })
})
.get('/nothing', async (c) => {
// In this scope, c.var should be empty because no middlewares are applied.
// However, c.var is typed as { foo1: string; foo2: string; }.
// In runtime, v is {}.
const v: { foo1: string, foo2: string } = c.var;
return c.json(v);
});
コメントそのままですが、上記のコードでいう /nothing にアクセスすると返ってくる値は {} というカラのJSONが返ってきます。しかし、コード上の c.var はカラではなく、しっかり型が入っているというバグが以前ありました。
このバグはバージョン4のリリースと同時に修正されましたが、別に型の修正がされたことで再度同じバグが引き起こされたようです。その修正が行われました。
Web Standardsで動作する説明文に変更
ここ最近「Edge」というのは私も使用しなくなってきたのですが、Honoも「Edge」で動作するという説明ではなく、Web StandardsのAPIで動作するフレームワークですよという説明文にREADMEなどが修正されました。
Server-Timing Middlewareが重複して動作するとエラーとなってしまう不具合の修正
HonoにはServer-Timingのヘッダーを設定してくれるServer-Timing Middlewareが存在します。
しかし、このミドルウェアを app.route などの機能を用いて、2つのルーティングで重複して使用するとエラーになるという不具合が修正されました。
import { timing } from 'hono/timing'
import { Hono } from 'hono'
const app = new Hono()
app.use(timing())
const a = new Hono()
a.use(timing())
a.get('/', (c) => c.text('a'))
app.route('/a', a)
export default app
上記の変更で 4.4.9 がリリースされています
4.4.9以降の修正
JSRでのJWTにあるユーティリティの型が読み込めない不具合修正
HonoのJWTには JWTPayload や SignatureAlgorithm といった型が存在しますが、JSRを使ったHonoではその型が正常に取得できないという不具合が修正されました。
4.4.9以降の修正 その2
Bunで ReadableStream の接続が切断された場合に明示的に abort を呼び出すように修正
Bunでは SSE などの ReadableStream で接続している場合にクライアントで画面を閉じるなどといった切断処理起こった場合に ReadableStream のキャンセル関数が呼び出されないようです。そのため、キャンセル関数でユーザ側で定義した abort 処理が動作しないということが発生するようです。
そこで AbortSignal の abort イベントでもユーザが定義した abort を呼び出すように修正されました。
先頭にスラッシュから始まらないルーティングを定義した場合にHono RPCクライアントが正しい型を返さない不具合の修正
HonoにはRPCのようにレスポンスのルーティングとレスポンスの型を明示的に行える機能があります。その機能を用いる際に、ルーティングに設定するパスをスラッシュから始めないと型が正常に動作しないという不具合が修正されました。
const route = app.get('posts', (c) => {
return c.json({
test: 'test'
})
})
export type AppType = typeof route
import { hc } from 'hono/client'
const client = hc<AppType>('/')
client.posts.$get // <-- Incorrect type
上記の変更で 4.4.10 がリリースされています
4.4.10以降の修正
routerのテスト関数が非同期である必要のないものは通常の関数定義に修正
テストの it に渡すテスト関数が非同期関数として定義されているものの中で非同期である必要の無いものから async を消すという修正がされました。
1つのルーティングに2つ以上のハンドラーを定義すると 2つ目以降はFormDataをRecord型として値を受け取れない不具合の修正
hono/validator を使用すると form として指定するとFormDataをRecord側で受け取ることができます。しかし、2つ以上定義すると2つ目以降はFormDataがそのままFormDataとして渡されてRecord型として値が受け取れない不具合が修正されました。
原因はリクエストから受け取ったFormDataをRecord型に変換して返す処理の中で2回目以降のリクエストからFormDataを取り出す処理を高速化するためにFormDataをキャッシュしているようですが、そのキャッシュの設定に設定したFormDataをそのまま返してしまうロジックが存在したため発生するようです。
import assert from 'assert'
import { Hono } from 'hono'
import { validator } from 'hono/validator'
const app = new Hono().post(
'/',
async (c, next) => {
await c.req.parseBody()
await next()
},
validator('form', (value) => {
console.log('validator - value:', value)
assert(!(value instanceof FormData), 'Value has to be a Record, not FormData')
return value
}),
(c) => {
return c.text('Hello Hono!')
}
)
const form = new FormData()
form.append('foo', 'bar')
await app.request('/', {
method: 'POST',
body: form
})
hono/client を使用してWebSocketを接続する際にQuery Parametersをサポートするように修正
hono/client を使用してエンドポイントに対してWebSocketのリクエストを投げる際にQuery Parametersを渡して接続できるように変更が加えられました。これによりサーバ側はエンドポイントだけでなく、渡されたパラメータにより処理を振り分けることが可能となりました。
const client = hc<AppType>('http://localhost')
client.index.$ws({
query: {
id: '123',
type: 'test',
},
})
// => ws://localhost/index?id=123&type=test
ルーティングに定義するパスとハンドラーの組み合わせの全パターン型指定の修正
ちょっと正直これだけ見ると正直難解な型定義の修正なのですが、つまるところHonoには app.get の引数にパスと複数のハンドラーを渡すことができますが、その渡せるハンドラーの個数9個分の型定義を直すリファクタリングが行われたようです。
テスト対象の名称のタイポを修正
getRouterName を対象としたテストの description が誤っていたため修正されました。
4.4.10以降の修正 その2
denoで ReadableStream が正常終了した場合に onAbort が呼び出されてしまう不具合修正
この記事の「4.4.9以降の修正 その2」でも触れたBunで ReadableStream が切断された場合に onAbort が呼び出す修正を触れたと思いますが、その修正でBunは確かに問題なくなったのですが、denoの環境下では正常終了した場合も onAbort が呼ばれてしまうという不具合が発生したようです。
そこで明示的に close() を呼んでいない場合は onAbort を呼び出すという修正がされました。
上記の変更で 4.4.11 がリリースされています
4.4.11以降の修正
AWS-LambdaのAdapterで Set-Cookie にカンマが入るような設定を行った場合に正しく Set-Cookie が返らない不具合の修正
PRにかかれていますが、例えば Set-Cookie の値に Expires を設定すると以下のような内容になります。
Set-Cookie: key=value; path=/; expires=Wed, 10-Oct-12 07:12:20 GMT
AWS-LambdaのAdapterではHonoで設定した Set-Cookie をAWS LambdaのResponseとして返す処理でCookieの値を再設定しています。そこでHonoで設定した Set-Cookie にカンマが入るような設定をすると正常に Set-Cookie の値が返らないという不具合が修正されました。
またこの修正でHeaderから Set-Cookie の値を取得するために、 getSetCookie というAPIを使用できる場合は使用するという風にも変更されています。
use 指定後のHttp Method定義にパスを指定しない場合にURL Parameterの型が正しく取得できない型定義の修正
同一のパスに対して、POST と GET の両方のHttp Methodを受け取るルーティングを定義する場合はチェインして記述することが可能です。更にチェインした側はパスを省略することでチェインされた側のパスを自動的に引き継ぎます。
new Hono()
.post("/:id", async (c) => {
const id = c.req.param("id");
return c.text(id);
})
.get((c) => { // path is "/:id"
const id = c.req.param("id");
return c.text(id);
});
しかし、use を使用するとpathは引き継ぐのは引き継ぐのですが、型が正しく認識できないという型の不具合が修正されました。
new Hono()
.use("/:id", async (c, next) => {
await next();
})
.get((c) => { // path is "/:id"
const id = c.req.param("id");
return c.text(id); // TypeScript complains that `id` might be `undefined`.
});
4.4.11以降の修正 その2
JSDocの hono.dev へのドキュメントページリンクを修正
JSDocには hono.dev へのドキュメントページのリンクが記載されています。各機能のドキュメントページのURLが /docs 変更されたため、JSDoc内のリンクも /docs へのリンクへと変更されました。
4.4.11以降の修正 その3
アンカータグの download 属性にbooleanの値を設定した場合に属性自体の出力有無となるように修正
アンカータグには download という属性値があり、この属性値はリンク先を download 属性値で指定した名前で保存するというものです。 hono/jsx で download 属性値にbooleanの値を設定するとそれがそのまま文字列として出力されていましが、この変更により true の場合はただ download 属性値を出力し、 false の場合は download 属性値を出力しないという風に変更されました。
HonoへのIssue作成の際にBug Reportを作成された場合は triage ラベルとするように変更
今まではBug ReportのIssueを作成された場合は即座に bug のラベルが付与されていましが、まずは triage ラベルが付与されるように運用が変更されるようです。その後に調査した結果でバグだった場合は bug ラベルを付与する運用に変更されます。
c.json で返る型を JSON.stringify() で返る型に限りなく近くする変更
Honoでは c.json をハンドラーで返すことでJSONのデータをクライアントに返すことができます。またHonoではRPCで処理するための hono/client が存在します。 hono/client で使用する hc はハンドラーが返す c.json の返り値から型を決めますが、JSON.stringfy にはObjectではなく、Functionを渡したり Symbol を渡したりと無茶なことをすると undefined や カラのオブジェクト( {} )を返しますが、その動作に近くなるように型変更が行われました。
JSRリリースのための slow types となる変数に明示的に型を指定するように修正
JSRリリースするために slow types となる変数に明示的に型を指定するように修正がされました。
JSRのスコアを向上させるために utils/jwt にJSDocを追加
JSRにはパッケージのスコアリングに「ドキュメント」「ベストプラクティス」「発見可能性」「互換性」の4つの項目がありますが、HonoのJSRのスコアを上げるために utils/jwt にJSDocが追加されました。
上記の変更で 4.4.12 がリリースされています
ベンチマーク計測を行うため、他Routerライブラリバージョンを更新
Honoと他のRouterライブラリとの速度比較を行うために最新版で速度を測るように express や koa-router などなどのライブラリを最新バージョンで速度を測るように変更されています。
4.4.12以降の修正
HonoのビルドをBunで行うように修正
Honoのビルドは一部Bunを使用してビルドされていました。しかし、一部はNode.jsでTypeScriptを実行するために tsx も併用されていました。Bunでのビルドが統一されるならば tsx の使用や2つのRuntimeは必要ないので、Bunに寄せるように修正されたようです。
4.4.12以降の修正 その2
deprecatedな UnOfficalStatusCode の型を使用しないようにするリファクタリング
「4.4.2以降の修正 その4」でも触れていますが、 UnOfficalStatusCode は deprecatedです。(予定ではv5で削除されるようです)内部で UnOfficalStatusCode の型が使用されていますが、結局のところ型としては UnofficalStatusCode と同様なので、 UnOfficalStatusCode は UnofficalStatusCode と定義するように修正されました。書いてて伝わりにくいのでコードで書くとこうです。
- export type UnOfficalStatusCode = -1 // same UnofficialStatusCode
+ export type UnOfficalStatusCode = UnofficialStatusCode
4.4.12以降の修正 その3
th タグの scope 属性の指定できる正確な属性値をUnion型の定義を追加
hono/jsx で作成する th タグの scope の属性値は String が指定可能でした。ただ、scope に指定する属性値は row や col といった決まった値を指定します。そこで指定する属性値の型に row や col といった指定できる4つの属性値のUnion型が追加されました。
ただし、この4つの属性値以外にも String での指定は可能です。これは下位互換もあるかもしれませんが、4つの属性値以外も一応ブラウザでの動作があるので今まで通りの値も指定が可能になっています。
RPCのFormの属性値に配列を指定するとエラーになる型情報の修正
hono/client を使用してRPCによるFormを送信する際に、本来Formは属性値に配列データを指定することが出来ますが、HonoのRPCでは配列を使用すると型エラーが発生する型情報の修正が行われました。
Issueにあったコードを拝借すると以下のような場合にエラーになるようです。
import { Hono } from "hono";
import { hc } from "hono/client";
import { validator } from "hono/validator";
const route = new Hono().post(
"/",
validator("form", (value: { body?: string[] }, c) => {
const body = value["body"];
if (!body || !Array.isArray(body)) {
return c.text("Invalid!", 400);
}
return { body };
}),
(ctx) => {
return ctx.text(`Body is [${ctx.req.valid("form").body}]`)
}
);
const client = hc<typeof route>("");
client.index.$post({
form: {
body: ["1", "2", "3"], // this is type error
},
});
4.4.12以降の修正 その4
RPCのFromに Blob を指定できるように型を変更
昨日の 4.4.12以降の修正 その3 で行われた「RPCのFormの属性値に配列を指定するとエラーになる型情報の修正」に付随して、Formに指定できるのは File 型ではなく Blob 型が良いということで Blob 型を指定できるように変更されました。
ちなみに File と Blob の違いは Blob の型に対して name と lastModified のプロパティを持つことで File 型になります。(他に2つのプロパティがありますが、非推奨だったりします)
余談ですが、この File から Blob への変更の方がいいのではないかという議論は作者はもとより中学生たちで議論されてて関心するばかりです。
use のパスにワイルドカードのパスを指定したミドルウェアを設定するとRPCの型が正常に生成されない型の不具合を修正
Honoには use というミドルウェアを設定するものがありますが、この use にワイルドカード、つまり * を指定するとRPCの型が正常に生成されないという型の不具合がありましたが、それが修正されました。
const app = new Hono();
app.use('*', middleware).route('/users', usersRouter);
const client = hc<typeof app>('');
console.log(client.users.$get()); // type error (Property '$get' does not exist on type 'never'.)
上記の変更で 4.4.13 がリリースされています
4.4.13以降の修正
Honoのv4.5がリリースされたので、その修正およびコミットが以下のPRに纏まっています。
数日はここからコミットの内容を書きつつ、mainブランチに追いついていく記載とします。
@hono/react-compat パッケージのために createRoot と hydrateRoot をデフォルトエクスポートに変更
HonoもPreactのように @hono/react-compat というライブラリを使用すると import xx from 'React' がReactを使用するのではなく、 hono/jsx を使用するということが出来るようになるための修正が行われました。
@hono/react-compat パッケージのために React互換のrenderToString と renderToReadableStream を追加
上記の修正と同じように @hono/react-compat を指定するということはReact互換のAPIが必要になってきます。そこで hono/jsx にもReactと同じ振る舞いを行う renderToString と renderToReadableStream が実装されました。
useCallback の引数の関数に引数を取る関数を指定すると型エラーとなるため型を修正
これもReactとの互換性向上の1つだと思いますが、 useCallback の第一引数に関数を渡しますが、その関数が引数を取るような関数を渡すと型エラーとなっていたようです。そこで型エラーが発生しないように修正されました。
また、Reactの StrictMode が動作するようにJSXの記述ができるように修正も同時に行われています。
JWT Auth Middleware で署名付き Cookieを使用できるように修正
HonoのJWT Auth Middlewareでは署名付き Cookieを扱うことができず、ミドルウェアが401で応答を返していました。この変更によりJWT Auth Middlewareでも署名付き Cookieを使用できるように修正がされました。
余談ですが、この修正自体は元は別の方が行っていたようですが、PRが停滞していたため別の方が引き取って続きを作成したようです。停滞しているPRをこのように引き取る形もありですね。
hono/jsx バージョン番号を更新
v4.5で hono/jsx のバージョン判定文字列が 19.0.0-hono-jsx に変更されました。
createContext をReact同様にProviderとするように修正
これも @hono/react-compat を実現するための変更です。Reactのエイリアスとして動作するようにReact同様の動作をする必要があるので、作成したContextはProviderとして動作するように修正されました。
React 19の新機能と互換性を持つための大幅な変更
これはかなり大作なコミットです。
React 19では色々と新機能が入っています。中でもこのコミットで対応されたのは数多くあります。
- headタグ内の
titleやmetaなどのタグの巻き上げレンダリングをサポートの追加 - refsのクリーンアップ関数対応のサポートの追加
- 非同期スクリプトのサポートの追加
-
useActionStateなどのFormに関するHooks関数のサポートの追加 -
use関数のサポートの追加
書いてる私もお腹いっぱいになってきます。これも最終的には @hono/react-compat を実現するためのものにもなると思います。まだ私自身も試したわけではありませんが、 use がサポートされているということは非同期コンポーネントも hono/jsx で使用できるということになるのでしょうか。
続きは別途記載していきます。
4.4.13以降の修正 その2
ConnInfo HelperのIPアドレスタイプの判定が行えない場合は undefined を返すように修正
今まではIPアドレスのタイプが IPv4 もしくは IPv6 のどちらか、もしくは判断できない場合は unknown という文字列を返していました。(IPアドレスの取得ができないというわけではなく、IPアドレスのタイプということ)
しかし、Cloudflare Workersで動作させると常に unknown という文字列を返すようです。そこで、IPアドレスのタイプが不明な場合は取得できたIPアドレスからタイプを逆引きするという提案もありましたが、IPアドレスのタイプが取得できないのあれば無理に作成せず undefined を返すという方向で修正がされました。
ちなみにIPアドレスのタイプはどのように取得しているかというとBunだけは送られてきたRequestオブジェクトからIPアドレスやIPアドレスタイプが取得できるようです。逆にBun以外はIPアドレスのタイプは取得できないので、IPアドレスから逆引きするしか無いと思います。
4.4.9で修正された影響により4.5のブランチでテストが失敗してるテストコードの修正
ちょっとコミットの解釈は自信が無いですが、たぶん合ってると思います。(PRなど何も説明がないので自信の記憶だけが頼り)
4.4.9のリリースに入ってる「Context生成時にHonoRequestオブジェクトを事前に生成して保持するのではなく、必要時に生成するように修正」というのがあります。この記事の上の方に解説しているので見て頂ければわかると思います。
これの影響で4.5リリースのブランチにあるテストが失敗してしまっていたので、4.4.9リリースと同様の修正がテストコードにて行われました。
React Compilerによる再レンダリングの抑制するための修正
なんかタイトルが雑ですが、雰囲気で感じとってください。
hono/jsx は(特にHono v4.5)ではReact 19互換に力が入っています。そこでReact互換であるならばReact Compilerで実行することより同一のPropsであれば子の再計算処理が行われない(つまり、自動的にmemo化された状態)になるはずが、 hono/jsx では再計算されてしまうという事象がありました。そこでその事象を修正したのがこのコミットです。
修正としては、元からのJSXのProps数やPropsの値を現在のPropsの設定を見比べて、同一の場合は比較処理をスキップするという処理が入ったようです。
Cloudflare Pages用のmiddlewareの追加
HonoにはCloudflare PagesのAdapterはありますが、middlewareはありませんでした。Issueで提案された面白い例ではmiddlewareではCloudflareのHTMLRewriterでのHTML書き換え処理をmiddlewareで共通的に定義するというような使用用途が提案され承諾されて追加されました。
// functions/_middleware.ts
import { getCookie } from 'hono/cookie'
import { handleMiddleware } from 'hono/cloudflare-pages'
export const onRequest = handleMiddleware(async (c, next) => {
const myCookie = getCookie(c, 'my_cookie')
const response = await next()
// Alternative API similar to Pages middleware
const response = await c.next()
return new HTMLRewriter()
.on('head', new InjectScriptHandler(myCookie))
.transform(response)
})
Cloudflare Pagesのhandlerの型を追加したCloudflare Pages用のmiddlewareのhandlerと同様に修正
追加されたCloudflare Pages用のmiddlewareではCloudflare Pages用のhandlerの型が定義されていましたが、元からあったCloudflare PagesのAdpaterではhandlerの型定義が少し異なっていました。そこで追加されたmiddlewareのhandlerの型定義をAdpater側でも使用するように修正されました。
続きは別途記載していきます。
4.4.13以降の修正 その3
ConnInfo Helperが返すIPアドレスタイプの型に undefined を追加
前回の「4.4.13以降の修正 その2」でも説明したConnInfo HelperのIPアドレスタイプですが、型自体に undefined が追加されました。これは値が undefined ということではなく、そもそもオブジェクトに addressType というものがオプショナルで返ってくるものなので undefined という型が追加された形になります。
IP Restriction Middlewareを追加
そのままですが、要はIP制限を行ってくれるIP Restriction Middlewareというミドルウェアが追加されました。
ドキュメントの通りですが、このミドルウェアでは拒否するリストを denyList に、許可するリストを allowList に登録することで指定のエンドポイントをIP制限をかけることができるようになります。まだまだこういったIP制限を行うアクセス制限はまだまだあると思うので十分需要はあると思います。(昔自分もFastifyのプラグインとして作った記憶があります)
import { Hono } from 'hono'
import { getConnInfo } from 'hono/bun'
import { ipRestriction } from 'hono/ip-restriction'
const app = new Hono()
app.use(
'*',
ipRestriction(getConnInfo, {
denyList: [],
allowList: ['127.0.0.1', '::1'],
})
)
app.get('/', (c) => c.text('Hello Hono!'))
察しのいい方は気づいていると思いますが、HonoでIPアドレスを扱うにはConnInfo Helperが必要になりますが、このIP制限を行うミドルウェアももちろんIPアドレスを扱うのでConnInfo Helperに依存しています。
IP Restriction Middlewareが返す無名関数に関数名を追加
IP Restriction Middlewareが返す関数が無名関数だったため、関数名を定義して返すように修正されました。これでミドルウェアからの返り値を名称をもって取得できるようになります。
ConnInfo HelperがVercel上で動作するように修正
ConnInfo Helperは様々な実行環境でのIPアドレスの取得を吸収するものですが、VercelはVercelでまたIPアドレスの取得方法が異なります。このコミットではVercel AdapterでのIPアドレスの取得が行えるに修正がされました。
VercelはこのHeaderからIPアドレスが取得できますが、これを見ると確かにそこからですよねって感じのわかる人はわかるヘッダーの値です。
Vercel Adapterで返すIPアドレスタイプを undefined に修正
追加されたVercel AdapterでのConnInfo HelperでIPアドレスタイプが旧の unkwon の文字列を返すようになっていたので、直近変更された undefined で返すように修正されました。
ConnInfo HelperがLambda Edge上で動作するように修正
これもConnInfo Helperシリーズの修正ですが、Lambda EdgeのAdapterでIPアドレスが取得できるように修正されました。
Service Worker Adapterの追加
いわずもがなHonoはバックエンドサーバとして使用されることが多いですが、HonoをService Workerとして動作させることを可能とするAdapterが追加されました。これは一種のHonoがWeb Standards APIで作成されているのでこういうことが可能ということです。
このService Worker Adapterを使用するとオフラインで動作するWebアプリケーションの構築が行えるということでこれはこれで面白いものが追加されたと思います。
リクエストごとに一意のIDを採番するRequest ID Middlewareの追加
追加したものを見ていてRuby on Railsにもあったなと懐かしい気持ちになってきました。
Honoでリクエストごとに一意にIDを採番してくれるミドルウェアが追加されました。パッと聞いただけでは使用用途がわからないかもしれませんが、よくある使用例でいうとログに仕込むことで、そのリクエストがどのような処理を通ってリクエストが処理されたかというのがわかるようになります。それがこのミドルウェアを使用すると簡単に採番されたIDが取得できるようになります。
ちなみにドキュメントにも書いていますが、IDの採番はデフォルトで crypto.randomUUID() を使用します。そのため、環境によっては動作しない可能性もありますが、変更することも可能になっています。
複数のミドルウェアの実行結果を制御するCombine Middlewareの追加
ミドルウェアは色々と存在しますが、複数使用することも想定されます。そこで使用するミドルウェアの全部を実行する必要がない場合などにはこの新しく追加されたCombine Middlewareが大いに役立ちそうです。
このミドルウェアは some, every, except の3つの機能を持つようで、ドキュメントにも書いていますが、some でIP制限のミドルウェアとベーシック認証にミドルウェアでどちらかが正常に通ればアクセスできるエンドポイントをこのCombine Middlewareを使用することで構築できるようになります。現実世界では例えば社内や特定のプライベートネックワーク内からであれば無条件でアクセスを許可しつつ、パブリックネットワークからはベーシック認証がかかるということができるということです。
import { Hono } from 'hono'
import { bearerAuth } from 'hono/bearer-auth'
import { getConnInfo } from 'hono/cloudflare-workers'
import { some } from 'hono/combine'
import { ipRestriction } from 'hono/ip-restriction'
const app = new Hono()
app.use(
'*',
some(
ipRestriction(getConnInfo, { allowList: ['192.168.0.2'] }),
bearerAuth({ token })
)
)
app.get('/', (c) => c.text('Hello Hono!'))
Honoのジェネリックである Bindings に interface を指定できるように型を修正
HonoにはBindingというContextつまりDIを設定するジェネリックを指定できる型に Bindings というものがあります。これは今まではTypeScriptの type しか指定できませんでしたが、 interface も指定できるようにするというのがこの変更です。
PRでも触れられていますが、この変更の起点となったのはCloudflare Workersでは Env の型を取得するcliコマンドがありますが、このコマンドを使用して生成した型は interface で定義されているためそのまま使用することができるようになるというのが利点として書かれています。Cloudflareユーザには嬉しい変更だと思います。
追加されたIP制限やミドルウェアの組み合わせミドルウェアの使用例などに関するコメントを正しいコメントに修正
exampleなどに書かれているコメントに from 先が正しくないものがあったりJSDoc自体の追加だったりとコード内のコメントに関する修正がされました。
ContextVariableMapに配列型のものを指定すると型が正しく取得できない場合がある不具合の修正
発生条件まで詳しく見ていないですが、ContextVariableMap の値に配列の型を指定すると c.get して取り出したものの値の型が any になってしまうという不具合が修正されました。
hono/jsx でHTMLのグローバル属性の型のサポートを追加
HTMLにはグローバル属性というすべてのHTML要素で共通の属性があります。その属性を指定する場合の型のサポートが追加されました。
JSRリリースのための slow types となる変数に明示的に型を指定するように修正
毎度お馴染みのJSRのslow typesとなる警告の修正です。
上記の変更で 4.5.0 がリリースされています
これでv4.5のリリースの変更がすべて大体mainブランチの変更に追い付いたと思います。(今日1つだけマージされていますが、コードの変更ではないので明日の解説に回します)
4.5.0以降の修正
ビルド時のファイル削除をライブラリを使用しないように修正
ビルド時に前回のビルドをクリーンアップするために rimraf を使用して rm -rf と同等の処理を実施していました。ビルドはBunで行っていますので、Bun Shellにそれと同等のことができるcliが存在するのでそれを使用して依存関係を減らすように修正されました。
テスト用のコンフィグファイルを src/ 配下から移動する修正
テスト用コンフィグファイルは src/ 配下に配置しない方がよいということで、vitestの設定ファイルである setup-vitest.ts ファイルが移動されました。
4.5.0以降の修正 その2
JWT Auth Middlewareの引数の secret プロパティに JsonWebKey や CryptoKey の型の値も指定できるように型を修正
jwt の引数に secret というプロパティには今まで文字列のものしか指定できませんでしたが、その先の内部でJWTを verify するメソッドは文字列だけでなく、 JsonWebKey や CryptoKey も渡すことができるので、ミドルウェアのそもそもの jwt の secret も JsonWebKey や CryptoKey を渡すようにしてもよいという修正です。何か動作自体が変わることはありません。
Bearer Authの値のprefixが無い状態も動作するようにする
Bearer Authの値は特に指定しなれば Bearer {token} という風に Bearer というprefixがある前提で動作します。このprefixを変更することはできますが、prefix自体を無しにするということを可能にするというのがこの修正です。
この変更により以下のような動作が可能です。
app.use('/apiKey/*', bearerAuth({ token, prefix: '', headerName: 'X-Api-Key' }))
app.get('/apiKey/*', (c) => {
handlerExecuted = true
return c.text('auth apiKey')
})
const req = new Request('http://localhost/apiKey/a')
req.headers.set('X-Api-Key', 'hoge')
const res = await app.request(req)
console.log(await res.text()) // output auth apiKey
factory.createApp() をStableに変更
factory.createApp() は今まで experimental でしたが、stableに変更されました。
WebSocketのクエリパラメータの配列をサポートするに修正
「4.4.10以降の修正」であったWebSocketのクエリパラメータをサポートしましたが、配列のパラメータがサポートされていなかったため、この修正で配列もサポートされるように修正されました。
Requestの Content-Type と validator のタイプが一致しなくてもエラーをスローしないように修正
今までの validator の振る舞いとして第一引数に json という文字列を指定した場合はRequestの Content-Type が application/json でない場合はエラーとしていました。しかしRequestの Content-Type が ultipart/form-data やそもそも Content-Type が指定されていない場合もエラーになるのは使い勝手としてあまり良くないためvalidatorは Content-Type が一致しない場合は何も行わないという変更がされました。
上記の変更で 4.5.1 がリリースされています
4.5.1以降の修正
Cloudflare Pagesで getRuntimeKey() が other になってしまわないように修正
どうやらCloudflare Pages(のProduction?)では getRuntimeKey() の値取得のロジックに使用している navigator.userAgent もっというと navigator が使用出来ないために、ランタイムキーの判定が正しくないということが発生するようです。そこでエラーにならないように修正されました。
ただしこの修正の元となっているのはCloudflare Pagesで c.env が正しく取得出来ない場合があるというIssueが元になっているようで、この修正でなぜ直るかまでは理解出来ていません。また c.env が正しく取得出来ないのは Cloudflare Workersのバージョンである compatibility_date を更新することで直るということも報告されているので、ちょっと問題としてはややこしそうです。
4.5.1以降の修正 その2
c.json で readonly が設定されたプロパティの型が正常に返らない不具合の修正
4.4.11以降の修正 その3に記載した「c.json で返る型を JSON.stringify() で返る型に限りなく近くする変更」の修正を行いましたが、readonly の型が正しく返らない不具合が修正されました。
昨日の「Cloudflare Pagesで getRuntimeKey() が other になってしまわないように修正」をリバート
やはり修正の起因は c.env の値が正常に取得出来ないということらしいですが、内容を読む限りCloudflare Workers上の問題であるように感じ取れます。昨日も書きましたが compatibility_date で正常に動作するCloudflare Workersのバージョンを指定すると良いということです。
TypedResponse を使用した回帰するジェネリックの型指定を行うと c.set の型が正しく行えないための修正
このスクラップを書いていて今まで1,2位を争うくらい意味がわからない修正です。そもそもこの修正を行う起因となったIssueで TypedResponse というResponseの型をジェネリックで指定する型があるのですが、これを contextVariables の型に使用して回帰するというかなりトリッキーな型指定をすることで c.set の型がおかしくなるという報告の元に修正されています。
が、そもそもなんでこの修正で直るかというのすら理解できてないです。どちらかというと元の使用方法が使用想定にない型指定なのかなと思います。
4.5.1以降の修正 その3
CSRF Protectionのmiddlewareの返り値として返す関数名のTypoを修正
CSRF Protection というmiddlewareがHonoにはありますが、この import { csrf } from 'hono/csrf' の csrf が返す関数名が誤っているので修正されました。
4.5.1以降の修正 その3
Secure Headers MiddlewareでResponse Headersの X-Powered-By を削除しないオプションを追加
フレームワークでよく付与されるResponse Headersに X-Powered-By というどのフレームワークで動作しているかを返す値がありますが、Secure Headers Middlewareを使用するとその値が自動的に削除されていました。そこで残すために removePoweredBy というオプションに false を渡すとReponse Headersの値を削除しないというオプションが追加されました。
上記の変更で 4.5.2 がリリースされています
4.5.2以降の修正
Content-Typeの文字列チェックにダブルクォーテーションも許すように修正
Bunなどでは boundary の部分にダブルクォーテーションが入ることがあるようです。現状はContent-Typeの文字列チェックにダブルクォーテーションを入ることを許していないためエラーとなるそうです。そこでContent-Typeにダブルクォーテーションを許すように修正されました。
Content-Typeに application/json を指定しつつ、 charset を指定するとvalidationされない不具合を修正
Content-Typeには application/json という値の後ろに charaset を指定できるそうです。(もちろん application/json だけではありません。)
Content-Type: application/json; charset=UTF-8
hono/validator でJSONのチェックを行う場合はContent-Typeの値が application/json という値である必要があるのですが、 charaset の値が入ってくる想定がされておらず、 application/json という値で終わることつまり、後には文字列が入らない想定となっており、validationがスキップされる動作となっていたことが原因のようです。
そこで、application/json の後ろに値が入ってきても問題ないように正規表現のチェック処理が修正されました。
4.5.2以降の修正 その2
hono/jsx でSVGに関する不具合の修正
このコミットには2つの内容が含まれています。
- SVGの中の
titleタグを使用するとheadタグのtitleが追加される不具合の修正 - SVGの属性の中で、ケバブケースで出力されない不具合の修正
まず、1つ目はReact 19と同様の動作をするために4.5系で処理が追加されましたが、SVGの中に使用する title タグを使用してしまうと同様の動作をする不具合が修正されています。またSVGの中にはキャメルケースとケバブケースの属性がありますが、 hono/jsx やReactはそうですが、属性は基本的にキャメルケースで指定します。その指定した属性がケバブケースで出力されないという不具合が修正されています。
hono/jsx のDOMのレンダリング速度の改善
hono/jsx で1コンポーネント内でそれなりのDOMの数(Issueで報告があったのは <div><span></span></div> が、ただ28個あるコンポーネント)をレンダリングする速度が遅くなるようです。どうやらDOMが増える度に指数関数的に速度が遅くなる。
原因としてはDOMを生成する処理にどこにDOMを差し込むかを判定する処理が再帰的かつループ処理があり、それにより計算コストが増大していくようです。無駄なループ処理が実行されないように修正されています。
Service Worker Adapterを使用してルーティングが存在しないURLにアクセスするとエラーが発生する不具合の修正
基本的にはルーティングに存在しないURLへのアクセスは404だったり、何かしらのエラーのレンダリング処理が行われますが、Service Workers Adapterでは存在しないルーティングにアクセスするとHonoでエラーが起きるようです。
Failed to execute 'fetch' on 'WorkerGlobalScope': Illegal invocation`
というようなエラーが発生して、Service Workerでの fetch が動作しないというエラーが起きるようです。それについて暫定ではありますが、 globalThis.self から fetch が取得できるならその fetch を使用するという処理で修正されています。
上記の変更で 4.5.3 がリリースされています
4.5.3以降の修正
hono/jsx で draggable 属性値に string(true) を設定すると型エラーとならないように修正
hono/jsx では draggable は boolean または undefined で受け入れる型定義になっています。そのため "true" という文字列の設定が出来ないため、受け入れる型が変更されました。
ただ、変更された型が以下です。
- draggable?: boolean | undefined
+ draggable?: 'true' | 'false' | undefined
ちなみにReactの場合は boolean でも受け入れます。
<div draggable={true}>react dragable</div>
// => output dom: <div draggable="true">react dragable</div>
このようにReactの場合は draggable 属性は Booleanish という型つまり、 boolean でも string でも受け入れて文字列で出力するという処理がされています。なのでちょっと修正方法が微妙なようは気もします。
4.5.3以降の修正 その2
CSSProperties という style 属性に指定できる型をオーバーライドできるように修正
hono/jsx では属性の型をオーバーライドして独自の型を加えることが出来ます。 style 属性には CSSProperties という型があるので、それをオーバーライドしても型が反映されないという不具合が修正されました。
合わせて、 style 属性には {} のような構造化のデータを渡す型となっていましたが、文字列を渡すことができるようにも型が修正されています。
WebSocket再接続時の初期化処理を独自に定義できるように修正
今まではWebSocketの再接続時はHonoの内部で new WebSocket という風に新しいWebSocketクラスを生成します。また、生成するWebSocketの接続URLはオプションで渡すクエリパラメータも含める必要があるので、元のWebSocketと異なる事ができ、型の安全性が失われることがあるということです。
そこで、この修正ではWebSocketの再接続するための関数を渡すことが出来るようになり、オプションも合わせて定義できることから上記の問題を解消するという変更がされました。
const client = hc<AppType>(url, {
webSocket(url, options) {
return new ReconnectingWebSocket(url, options)
},
})
validator の 'param' を指定しつつ、必須のパラメータが1つの定義と指定しているにも関わらず、オプションとなってしまう型不具合の修正
ちょっとタイトルからわかりにくいですが、元となったIssueから参考のコードを拝借します。
const schema = z.object({ id: z.string() })
const paramValidator = zValidator("param", schema)
// in: {
// param: {
// id: string | undefined; < -- The type undefined is wrong
// }
}
このように必ず入ってくる値にも関わらずMiddlewareでは undefined という誤った型が入ってきてしまい、わざわざ undefined の処理が必要になるということです。
上記の変更で 4.5.4 がリリースされています
4.5.4以降の修正
hono/jsx で Fragment だけや null を返した場合にカラ文字列のHTMLを生成するように修正
よくあるレンダリングしたくない場合にFragmentだけ( <></> )や null を返してカラのHTML文字列を生成することがありますが、hono/jsx ではそれを行うとエラーになってしまっていたようです。そこでそれがエラーにならずカラのHTML文字列を生成するように修正されました。
c.header に設定できる値を型でサポートするように修正
以下のようにHonoではResponseのHeadersに値を設定できます。
app.get('/', c => {
c.header('Content-Type', 'text/plain')
c.text('ok')
})
このResponseのHeadersのキーは標準でいくつかあり、例えばCORSを設定するならば Access-Control-Allow-Headers などがあります。この設定できるキーの入力をある程度型でサポートするというのがこの修正です。確かにHeadersは色々あるので、こういう地味なのは嬉しいですね。
4.5.4以降の修正 その2
hono/jsx の draggable 属性について boolean 型も指定できるように修正
これは以前で「4.5.3以降の修正」で私が書いたReactでは draggable 属性には boolean が指定できるのでちょっと互換性が異なるなというものが修正されたようです。
要は 'true' 'false' の文字列に加えて boolean 型も指定できるようになったようです。
4.5.4以降の修正 その3
c.header に Content-Type を指定した場合の値を型でサポートするように修正
「4.5.4以降の修正」の修正の c.header の修正に更に追加されたものと思って大丈夫です。前回の修正はReponse Headersのキーに関する型のサポートでしたが、今回はそのキーに Content-Type を指定した場合の値の型がサポートされました。ですので、Content-Type に application/json というのをフル入力せず「json」と入力するだけで、 application/json が候補として表示されるようになります。
serveStatic を使用する際にディレクトリ名にドットを含ディレクトリ名を指定した場合に静的ファイルが返せない場合がある動作の修正
app.get('/favicon.ico', serveStatic({ path: './satic/hello.world' }))
上記のようの例の場合、 hello.world はファイルなのか、ディレクトリなのかフレームワーク側では現在ファイルとして扱うぽいのですが、実際はディレクトリの場合に hello.world/index.html を返してほしいが動作しないという振る舞いに対する動作に対応する修正されました。
フレームワーク側ではそれが判断できない場合にディレクトリとして、認識するために isDir というオプションを渡してディレクトリとして認識させるということが可能になりました。
app.get('/favicon.ico', serveStatic({
path: './satic/hello.world',
isDir: (path) => {
return path === 'static/hello.world'
}
}))
これでディレクトリとして認識されて static/hello.world/index.html を返してくれるというものになります。
上記の変更で 4.5.5 がリリースされています
4.5.5以降の修正
非同期コンポーネントでエラー(Uncaught (in promise))が発生するとクラッシュする可能性の不具合を修正
PRに書いていますが、クラッシュする条件としては
- 非同期コンポーネントが複数ある
- 最初のPromiseが解決される前に後続のPromiseでエラーが発生する
テストコードをほぼそのまま転載しますが、こんな感じのコードで発生するようです。
const AsyncComponent = async () => {
await new Promise((resolve) => setTimeout(resolve, 10))
return <h1>Hello from async component</h1>
}
const AsyncErrorComponent = async () => {
await new Promise((resolve) => setTimeout(resolve, 0))
throw componentError
}
app.get('/', (c) => {
return c.html(
<>
<AsyncComponent />
<AsyncErrorComponent />
</>
)
})
というものです。非同期コンポーネント自体はReact 19と同様にHonoでも使えるようになったのですが、エラーとなった場合は onError でハンドリングされないという不具合が修正されました。
4.5.5以降の修正 その2
multipart/form-data のデータを送信した際にFormDataのvalidationが必ず失敗してしまう不具合の修正
const route = app.post(
'/posts',
zValidator(
'form',
z.object({
body: z.string(),
})
),
(c) => {
const validated = c.req.valid('form')
// ... use your validated data
}
)
HonoではこのようにFormDataのvalidationを行う際に引数に 'form' という指定をしてvalidationを行うことが出来ますが、 Content-Type に multipart/form-data を指定した場合に必ずvalidationが失敗する不具合が修正されました。どうやら原因は Content-Type のmultipartから始まる正規表現のチェックで空白の指定が誤っているため、Content-Type が正常でないとみなされて、必ず失敗するといったことが発生したようです。
FormDataの同一キーにappendした際のvalidationを行う値は配列として保持するように修正
要は const form = new FormData() を行った後に form.append('key', ...) として同一キーに値を append していくとそれは配列として扱うのですが、 validation時にFormデータからObjectとして値を復元する際に配列としてみなすように修正されました。(余談ですが、HonoはこのFormDataの配列として扱う修正が多いような気が…)
hono/jsx metaタグの name 属性に補完が効くように型を追加
これは以前あった c.header のキーおよび値をある程度、型で補完することができる機能のmetaタグ版です。これによりmetaタグの代表的なものは name を指定時に補完が効くようになります。
上記の変更で 4.5.6 がリリースされています
4.5.6以降の修正
hono/jsx にて script タグが style タグとして出力される不具合を修正
タイトルのままなんですが、 script タグを指定しても style タグとして出力されてしまう不具合が修正されました。
hono/jsx のレンダリング速度を改善
hono/jsx と他のライブラリとクライアントでのレンダリング速度を調べてくれた方の報告では、速度の早い順に Solid.js > Preact > React > Hono という順になったようです。それで一番遅いのであれば問題ないのですが、コンポーネント数が多いとブラウザでレンダリングが出来ずハングするようです。
そこで usualoma さんによる速度の改善が行われました。
大きい変更としては「再帰のロジックをやめ、ループで処理するように変更」「Object.definePropertiesの速度が遅いため使用しないよう変更」ということでReact並へのレンダリング速度に修正されました。

a タグの target 属性に補完が効くように型を追加
以前に書いた c.header や meta タグと同様のシリーズの修正です。
a の target 属性には _blank などを指定することが出来ますが、これも入力補完が効くように修正されました。
Content-Type に application/x-www-form-urlencoded に追加して charset=UTF-8 を指定した場合にvalidationが正しく動作しない不具合修正
「4.5.2以降の修正」で application/json で同じことがありましたが、 application/x-www-form-urlencoded でも同様の不具合があり、修正されました。原因は以前と同じ正規表現的に文字コードが入ることがない条件指定となっていたことが原因です。
4.5.6以降の修正 その2
area タグの target 属性や button タグの formtarget に補完が効くように型を追加
「4.5.6以降の修正」で書いた a タグの target 属性と同じように他のタグでも target および formtarget 属性の入力に補完が効くように型が修正されました。修正されたタグおよび属性は以下です。
-
areaタグのtarget属性 -
baseタグのtarget属性 -
buttonタグのformtarget属性 -
formタグのformtarget属性 -
inputタグのformtarget属性
このシリーズまだまだありそうなのでコントリビュートチャンスではないでしょうか。
HonoのXアカウントのURLを x.com に変更
READMEにHonoの公式であるXのアカウントがありますが、そのURLが旧ドメインである twitter.com であったため、 x.com に変更されました。
4.5.6以降の修正 その3
オプショナルのURLパラメータを定義したルーティングが hono/client を使用すると正常なパスで呼び出されない不具合を修正
HonoではオプショナルのURLパラメータを持ったルーティングを定義することができます。
const app = new Hono()
app.get('/something/:firstId/:secondId/:version?', (c) => c.json({ ok: true }))
上記の例では firstId および secondId 部分は必須ですが、 version 部分は無くてもこのルーティングに該当するという定義です。つまり /something/1/2 も /something/1/2/3 もこのルーティングで処理されます。
しかし、 hono/client を使用したRPCを使用して、オプショナルな部分を渡さず呼び出すと呼び出されたURLは /something/1/2/undefined という風に正常なURLとして渡って来ないという不具合が修正されました。
input タグの type および autocomplete 属性について補完が効くように型を修正
最近恒例のシリーズです。今度は input タグについて type と autocomplete 属性について入力が補完されるように修正されました。ただ、そこまで詳しく見ていないのですが、 autocomplete に関してはまだまだ種類は多いようですが、これはあくまでReactと同等の補完ということで承認されています。
上記の変更で 4.5.7 がリリースされています
4.5.7以降の修正
CSRF Protection middlewareでチェックする Content-Type の大文字小文字を考慮しないように修正
CSRF対策を行うミドルウェアがありますが、チェック時に Content-Type の大文字小文字を区別してチェックしていたため、CSRF対策として機能しない不具合が修正されました。
上記の変更で 4.5.8 がリリースされています
4.5.8以降の修正
TypeScript 5.6にした場合にテストが正常に動作しなくなるテストコードの修正
端的に表題の通りなんですが、じゃあなんで次期バージョンの5.6ではこれが通らなくなくなるの?っていうのはちょっと難しい内容です。
そもそもこのテストは型が指定の通りに型となっているかテストを書いています。で、5.6では5.5で発生しているジェネリックによる型評価に不具合があり、それが修正されてリリースされるようです。で、その不具合を対応したTypeScriptのバージョンを使用すると、元々はTypeScriptのバグのせいでテストが通っていたコードが失敗するようになったという経緯です。
4.5.8以降の修正 その2
denoの場合に 標準出力のカラーコード出力の確認ロジックが動作すると NO_COLOR という環境変数へのアクセス権を求められる動作の修正
Honoは内部的で標準出力する際に NO_COLOR の環境変数を見て、標準出力にカラーコードを付与するかどうかの判定を行っているようです。ただ、コードを見るとすべての標準出力がそうではなく、現状は showRoutes というすべてのルーティングを出力できる開発用の関数があるのですが、その関数で出力する標準出力に NO_COLOR の環境変数でのカラーコードを出力するかどうかを判定していました。
しかし、Denoの場合は環境変数にアクセスするためには --allow-env というパーミッションが必要になります。そこでDenoの場合は NO_COLOR の環境変数を見るのではなく、 Deno.noColor という --allow-env パーミッションがなくても NO_COLOR の環境変数を参照する値を見るように修正されました。
embed タグや link の type 属性について補完が効くように型を修正
今度は以下のタグの type 属性について入力が補完されるように修正されました。
- embed
- link
- object
- source
- script
- style
Pretty JSON Middlewareに整形を行うクエリパラメータを指定できるよう修正
Pretty JSON Middlewareを使えば、JSONのレスポンスが整形されたJSON(JSON.stringify({ sample }, null, 2))で表示することが出来ましたが、今まではスペースの数値しかオプションで指定できませんでした。なので、Pretty JSON Middlewareを使用すると使用するルーティングは prettye というクエリパラメータを付与すると整形されるようになっていました。
今回は整形するための特定のクエリパラメータ(デフォルトでは pretty というパラメータ)を指定することが出来るように変更がされました。オプションなので、以下のように space と同様に指定することで使用することが出来ます。
app.use(
'*',
prettyJSON({
query: 'format',
})
)
上記の変更で 4.5.9 がリリースされています
4.5.9以降の修正
Compress Middleware の圧縮を行わないようにする処理の追加
レスポンスBodyを圧縮して返すミドルウェアがありますが、いくつかの条件で圧縮を行わない条件が追加されました。
- エンコード済みの場合
- リクエストメソッドが
HEADの場合 -
Content-Lengthが1024もしくは指定のサイズ以下の場合 - 圧縮を行わない
Content-Type(application/jsonやx-www-form-urlencodedなど)の場合 - レスポンスHeadersの
Cache-Controlにno-transformが付与されている場合
上記の条件のどれかに当てはまるとミドルウェアは圧縮を行わないようにするという処理に修正されました。
Popover APIの popover 属性や popovertargetaction 属性について補完が効くように型を修正
新しめのAPIに Popover API というものがあるのですが(ざっくり書くとHTMLだけでポップオーバーを表示できるもので、JSでも書ける)、そのAPIを使用するための属性に popover や popovertargetaction という属性がありますが、これもある程度決まりのある値を指定します。
それが恒例のシリーズと化していますが、入力を補完するように型が修正されました。
4.5.9以降の修正 その2
button タグと input タグの formenctype 属性や formmethod 属性について補完が効くように型を修正
これをほぼ毎日書いてるとコントリビュータの方の名前を見るだけで、次はなんのシリーズと思えるくらいの安心感です。
今回は表題の通り input タグなどに使用される formenctype 属性や formmethod 属性とその大本の form タグの enctype 属性と method に補完が効くように型が修正されました。
また、 form タグの autocomplete も一部補完が効くように修正されています。
Vitest をv2へバージョンアップ
Honoで使用されているテストフレームワークのVitestがv2へバージョンアップされました。v2のバージョンアップに伴い一部だけテストが書き換えられていますが、難なく変更されているようです。
4.5.9以降の修正 その3
Vitest v2へのアップデートに伴い deprecated な型の修正
Suite という型が deprecated になっており、移行先の型である RunnerTestSuite に修正されました。
logger middlewareで出力されるログの先頭からスペースを削除
logger middlewareを使用する <-- や --> の先頭にスペース3つが先頭について状態で出力されていました。ただし、ここだけがスペースが挿入されているので他のログを合わせると位置がズレているということなので削除されました。
上記の変更で 4.5.10 がリリースされています
非同期コンポーネントを複数レンダリングする際に ErrorBoundary によるエラーをキャッチした場合にクラッシュしてしまう不具合の修正
表題を見てもわからないと思うので、Issueのコードをそのまま記載します。
const app = new Hono();
export const SlowComponent: FC = async () => {
await new Promise((resolve) => setTimeout(resolve, 100));
return <div></div>;
};
const BrokenComponent: FC = async () => {
await new Promise((resolve) => setTimeout(resolve, 10));
throw new Error("Out of service");
};
app.get("/", (ctx) => {
return ctx.html(
<>
<SlowComponent />
<ErrorBoundary fallback="An error occurred">
<BrokenComponent />
</ErrorBoundary>
</>,
);
});
上記の例では BrokenComponent というコンポーネントはエラーを起こします。しかし ErrorBoundary が存在するので一見問題なさそうに見えますが、その横にそれよりもレンダリングが遅い SlowComponent というものが存在します。この場合エラーが起こった後よりもレンダリングを行おうとして処理が正常に行えないということが発生するようです。
この場合でも正常にレンダリング処理が行われるように修正がされました。修正は至ってシンプルで全レンダリングで1つでもエラーがあった場合にエラーを認識するように修正されています。
4.5.10以降の修正
head タグ内のタグ要素の巻き上げ処理を改善しレンダリング速度を改善
hono/jsx もReact19同様に title や meta タグなどの head タグに配置するタグをどこに記述しても head タグに巻き上げる仕様が入っています。しかし、その仕様の動作によりレンダリング速度が遅くなっていたということで、 title や meta タグなどが head タグ内にある場合は処理しないようにして速度が改善されています。
Content-Typeの判定処理にオプショナルチェーンを使用するようにリファクタリング
HonoでBodyをパースする際にContent-Typeが multipart/form-data か application/x-www-form-urlencoded の場合にパースするという判定がありますが、その判定にContent-Typeが習得できない場合の判定条件があったので、それをオプショナルチェーンで書くようにリファクタリングされました。
README.md 内に Twitter という文言を X という文言に修正
Twitterのサービス名が変わりましたが、HonoのREADME.mdに一部Twitterというサービス名が残っていたのでXに変更されました。
4.5.10以降の修正 その2
JSX RendererのJSDocへのドキュメントへのURLの指定方法を修正
JSDocにJSX RendererのドキュメントURLが記載されていますが、そのURLの指定方法を正しい記述に修正されました。
Basic認証の認証ロジックを切り出すリファクタリングを実施
Basic認証の認証部分に関する関数が独立して切り出されました。この切り出しには別で提案されているCasbinを使用した認可のミドルウェアを取り込むためのようです。
Casbinはあくまで認可を制御するのであって、認証は別で賄う必要があります。また、認可なので「誰が」というのを把握する必要があり、このリファクタリングでは認証部分で「誰が」というのを習得しやすくするためにリファクタリングが行われたという背景がありそうです。
上記の変更で 4.5.11 がリリースされています
4.5.11以降の修正
JSX Renderer MiddlewareのJSDoc内の名称を正しい名称に変更
"JSX" Renderer Middlewareですが、"JSR"と記載されているJSDocがあり、"JSX"という正しいJSDocドキュメントに修正されました。
Denoのテストに使用する @std/assert をJSRから取得して使用するように修正
Denoのランタイムで行うテストコードでassetを行うライブラリがJSRから取得して使用するように修正されました。
これにはどうやら背景があるようで、Denoにて先日リリースされたCache APIをサポートするための機能を開発のようですが、キャッシュの有効期限をHono側で制御するための処理が組み込まれる(Denoのキャッシュにはexpireを設定できないぽい?)ようで、その過程でテストライブラリを更新する必要があるようです。
4.5.11以降の修正 その2
ここからはリリースされた 4.6.0 および 4.6.1 の内容のコミットの説明になっていきます。
Secure Headers Middlewareに Permissions-Policy ヘッダーを設定できるように修正
HTTPのヘッダーに Permissions-Policy ヘッダーというものを設定することでブラウザからWebページにアクセスできる機能を絞ることが出来ます。例えば camera geolocation microphone といったアクセスを制御することでXSS攻撃などのリスクを低減することが出来ます。
この変更によりSecure Headers Middlewareでは Permissions-Policy が設定出来るようになりました。
const app = new Hono()
app.use(
'*',
secureHeaders({
permissionsPolicy: {
fullscreen: ['self'], // fullscreen=(self)
bluetooth: ['none'], // bluetooth=(none)
payment: ['self', 'https://example.com'], // payment=(self "https://example.com")
syncXhr: [], // sync-xhr=()
camera: false, // camera=none
microphone: true, // microphone=*
geolocation: ['*'], // geolocation=*
usb: ['self', 'https://a.example.com', 'https://b.example.com'], // usb=(self "https://a.example.com" "https://b.example.com")
accelerometer: ['https://*.example.com'], // accelerometer=("https://*.example.com")
gyroscope: ['src'], // gyroscope=(src)
magnetometer: [
'https://a.example.com',
'https://b.example.com',
], // magnetometer=("https://a.example.com" "https://b.example.com")
},
})
)
Honoのドキュメントのまんまですが、詳しくはこちらを参照ください。
Cloudflare Pages Functionsの _middleware.ts でHonoを使用した際にContextが正常に動作するように修正
ちょっとマニアックなのですが、Cloudflare Pages Functionsにはmiddleware用のファイルを置いてmiddlewareを定義することが出来ます。
そのmiddlewareのファイル( _middleware.ts )で hono/cloudflare-pages を使用してContextに設定しても本体側でContextを取得するコードを書いても undefined になります。(それはそうなんですが)
// functions/_middleware.ts
import { handleMiddleware } from "hono/cloudflare-pages";
export const onRequest = [
handleMiddleware(async (c, next) => {
console.log("middleware setting user");
c.set('user', 'joe')
await next();
})
]
// functions/api/[[route]].ts
import { Hono } from "hono";
import { handle } from "hono/cloudflare-pages";
interface HonoContext {
Variables: {
user: string
};
}
const app = new Hono<HonoContext>().basePath('/api');
const routes = app.get('/hello', (c) => {
return c.json({
message: `Hello, ${c.get('user')}!`
});
});
export const onRequest = handle(routes);
で、この修正はまさにCloudflareの中の人って感じの修正なのですが、 functions/_middleware.ts から 本体のプログラム( functions/[[route]].ts )に渡すためのInterfaceがあるようです。(ドキュメントには明確に触れられていないですが)
そこで、そのInterfaceを使って渡せるようになったというのがこの修正です。(これはかなりマニアックな修正です)
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'
export const onRequest = [
handleMiddleware(async (c, next) => {
c.env.eventContext.data.user = 'Joe'
await next()
}),
]
// functions/api/[[route]].ts
import { Hono } from 'hono'
import type { EventContext } from 'hono/cloudflare-pages'
import { handle } from 'hono/cloudflare-pages'
type Env = {
Bindings: {
eventContext: EventContext
}
}
const app = new Hono<Env>().basePath('/api')
const routes = app.get('/hello', (c) => {
return c.json({
message: `Hello, ${c.env.eventContext.data.user}!`, // 'Joe'
})
})
export const onRequest = handle(routes)
WebSocket Helperで raw の型をジェネリックで生成するように修正
WebSocket Helperで raw を使用する際は以下のようなコードになりますが、そもそも raw が unkown の型になっていますので、基本的には自分でキャストするか型エラーを無視するしかありませでした。
app.get(
'/ws',
upgradeWebSocket((c) => {
return {
onMessage(event, ws) {
// @ts-expect-error
ws.raw.subscribe('chat-test')
},
}
})
)
それがこの修正でジェネリックとなったため raw にも自動的に型が入り、例えばBunならば ServerWebSocket とという型が入って使用することが出来ます。
JSXのレンダリングにて steam の場合は Content-Encoding ヘッダーに Identity が設定されるように修正
内容からすべてを把握出来るわけではないですが、どうやら Suspense の処理でエンコードされていないことを明示的に渡しておく必要のあるための修正のようです。
Context Storage Middlewareの追加
今までHonoはContextにアクセスするにはハンドラーから受け取ったContextを各処理に伝搬していく必要がありましたが、このContext Storage Middlewareを使用するとハンドラー外からの処理でもContextにアクセス( getContext )することが可能になります。
これは AsyncLocalStorage というグローバルに値を格納できるAPIを用いて実装されており、そこに格納されたコンテキストを取得するという処理になっています。
静的ファイルを返却する際に事前に圧縮済みファイルがある場合はそれを返却するできるように修正
例えばJavaScriptにhttpでリクエストした際にJavaScriptファイルを返すのではなく、事前に対応されたgzipファイルを返すということがこの修正で可能になりました。これはNginxなどにも機能として存在しますが、Honoでこれをサポートするということになりました。使用するには precompressed というオプションに true を渡すと使用することが出来ます。
import { serveStatic } from '@hono/node-server/serve-static'
app.use('/static/*', serveStatic({ root: './', precompressed: true }))
streamSSE で 非同期コンポーネントの返却できるように修正
Server Send EventではStreamを出力できるように修正されました。以前に似たようなPRが作成されたようですが、今回はSSEで renderToReadbleStream が使えないということで修正されたようです。
fetch で取得したResposeをそのまま返すとエラーになる場合がある不具合の修正
どうやら fetch で取得したResponseをそのまま返すとエラーになる場合があるようです。原因はどうやら取得したResponseをmiddlewareなどでHeadersを変更しようする処理でうまく変更できずにエラーとなるようなので、それが修正されました。
Secure Headers Middlewareに Permissions-Policy ヘッダーに設定できるディレクティブを追加
Permissions-Policy ヘッダーに設定できるディレクティブに usb や accelerometer gyroscope magnetometer を設定できるように修正されました。
serve-static にファイルが見つかった際のコールバックハンドラーの処理を追加
静的ファイルを配信する際に特定のファイルの配信する際にResponseヘッダーを書き換えたいなどの要望に応えるために onFound というコールバックハンドラーを指定することで処理ができるようにオプションが追加されました。
app.use('/static/*', serveStatic({
root: './',
onFound: (path, c) => {
if (path.endsWith('hoge.jpeg')) {
c.header('Cache-Control', `public, immutable, max-age=31536000`)
}
},
}
Basic認証にて認証に失敗した際のBodyメッセージをカスタマイズできるオプションを追加
今まではBasic認証で認証エラーとなった場合は 「Unauthorized」 というメッセージ(Body)が固定が返っていましたが、それを指定できるようにするオプションが追加されました。
const app = new Hono()
app.use(
'/auth/*',
basicAuth({
username: 'hono',
password: 'acoolproject',
invalidUserMessage: () => 'Custom unauthorized message as function string'
})
)
invalidUserMessage オプションには文字列や関数および message プロパティを持ったオブジェクトを指定することが出来ます。
Bearer認証にもBasic認証同様に認証に失敗した際のBodyメッセージをカスタマイズできるオプションを追加
上記で説明した認証エラー時のメッセージをBearer認証を行うBearer Auth Middlewareにも同様に修正されました。
認証エラーに失敗した際のカスタムメッセージを設定するオプション名のTypoを修正
invalidAuthenticationHeaderMeasage から invalidAuthenticationHeaderMessage にTypoが修正されました。
上記の変更で 4.6.0 がリリースされています
ビルドしたファイルの参照パスが // と連続するスラッシュがパスとして出力されないように修正
Honoのビルドをする設定にものによればファイルパスを結合する処理で // とスラッシュが2つ続いてファイルを参照するコードが生成されてしまうことがあるようです。これはランタイム(報告ではDeno。というかDenoの中の人)によっては不具合を起こしてしまうようで、 // とならないように正常にファイルパスを出力するビルド処理となるように修正されました。
上記の変更で 4.6.1 がリリースされています
4.6.1以降の修正
ESLint v9にアップデートおよびflat configに対応
Hono自体の処理に変更は無いようです。あくまでESLint v9およびflat configに対応したようです。ESLint v9にアップデートと同時に eslint-plugin-import-x から sort-imports に変更したようです。
4.6.1以降の修正 その2
事前に圧縮済み静的ファイルを返す場合のパフォーマンスを改善
具体的には以下の変更により処理を早くしたようです。
- Requestの
Accept-Encodingから検索する圧縮ファイル種類のロジックを最適化 - Responseが圧縮可能な
Content-Type以外は圧縮ファイルを検索しない -
Content-Typeは圧縮ファイルが見つかった場合にのみ設定する
という処理の変更を加えて少しでも速度の改善を行ったようです。
4.6.1以降の修正 その3
事前圧縮済みの静的ファイルの拡張子からMimeTypeが取得出来ない場合は Content-Type に application/octet-stream を設定するように修正
昨日の事前圧縮ファイルを配信するためのパフォーマンス改善の処理の変更により Content-Type は圧縮ファイルが存在した場合に設定するように変更されました。また、見つかっても拡張子から判断出来ない場合は Content-Type が text/plain が設定されていました。しかし、バイナリファイルの可能性があるため Content-Type が適切ではないとして拡張子で判断出来ない場合は 'application/octet-stream を設定するように修正されました。
上記の変更で 4.6.2 がリリースされています
ランタイムに依存するテストコードのディレクトリ名のアンダーバーをハイフンにリネーム
Honoのリポジトリでは、ハイフンを用いたファイル名やディレクトリ名で設定されているようですが、ランタイムに依存するディレクトリ名だけがアンダーバーが使用されており、他と統一するためにハイフンに変更されました。
4.6.2以降の修正
型チェックを行う場合のパフォーマンスを計測するように修正
以前 RPCを使用する場合に返るJSONの型を変更した修正がありましたが、その際にパフォーマンスが低下してしまうという問題が一時発生してしまいました。そこでPRの段階でパフォーマンスの低下が起きていないかチェックを行うCIが導入されました。
4.6.2以降の修正 その2
不要な await の記述を削除して、 renderToReadableStream の型を修正
renderToReadableStream に不必要な await が定義されていましが、それが不要になるようにコードがリファクタリングされました。これによりコードを読む際の混乱がなくなるようになりました。
ハンドラーのパスからの型生成のパフォーマンスを10%改善する修正
Honoではパスからパラメータなどの型が生成する処理がありますが、その型を生成する処理の速度が改善する修正が行われました。これは前回記載した型チェックのパフォーマンス計測より変更後のコードを適用すると測定した結果では10%程度早くなるようです。
同水準の型を纏めて型の分岐を抑えるように修正
RPCなどのJSONを返す場合の型の返り値を分岐している箇所にて何通りか存在しますが、ほぼ同じ型については分岐せず1つに纏めて型定義をするように修正されました。
型チェックのパフォーマンスの計測結果の出力結果のテーブルフォーマットを調整
型チェックのパフォーマンス結果はテーブルフォーマットで出力されますが、その出力を微調整して見やすくするように修正されました。
useSyncExternalStore の第一引数のsubscribe関数の型を正しい型に修正
HonoもReact互換なので useSyncExternalStore が存在します。 useSyncExternalStore の第一引数はsubscribeとなる関数を指定しますが、これは引数なしの関数を指定する必要があり、引数が存在する型となっていたので、引数を持たない関数の型に修正されました。型の修正のみであり、実動作に変更ありません。
4.6.2以降の修正 その3
Combine Middlewareの every 関数にてReponseを返すと以降のmiddlewareは実行されないように修正
Combine Middlewareには every という関数がありますが、これは複数のmiddlewareをすべて実行して1つでも失敗したらハンドラーを実行しないというものですが、この every に指定したmiddlewareで1つでもReponse相当(c.textなど)を返すと指定されたResponseをmiddlewareから返すという風に変更されました。
これによりエラーのReponseだけでなく独自のReponseを返すことが可能になります。
Secure Headers Middlewareにて Content-Security-Policy-Report-Only をサポートするように修正
Secure Headers Middlewareで Content-Security-Policy はサポートされていましたが、 Content-Security-Policy-Report-Only はサポートされていませんでしたが、この変更によりサポートされるようになりました、。
JWT Auth Middlewareの JwtVariables 型をジェネリックで指定できるように修正
JWT Auth Middlewareの JwtVariables は固定で以下の型でした。
export type JwtVariables = {
jwtPayload: any
}
なので内部の jwtPayload は常にanyでしたが、 jwtPayload の型をジェネリックで指定できるように修正されました。
HonoRequest をインスタンス化できるように exports の設定を追加
Honoを使用したフレームワークに Danet というものがあるらしいのですが、そのフレームワークでHonoを使用するためにHonoでRequestオブジェクトを扱うための HonoRequest を独自にインスタンス化して使用するためアクセスできる必要があるという要望のために exports の設定が追加されました。これはJSRに移行する前のHonoでは出来たことらしいですが、JSRに移行したと同時に HonoRequest がインスタンス化できなくなったということで修正が認められたようです。
JSXにて precompile を指定した場合に属性値が正常に出力されない不具合修正
HonoのJSXはDenoで動作させるためには precompile という設定を行う必要があるのですが、この設定を行うと属性値が文字列で正常に出力されず [object Object] で出力されてしまう不具合が修正されました。
serveStatic にて絶対パスをサポートするように修正
serveStatic にて スラッシュから始まるパスを指定することで絶対パスとして認識するように修正されました。
上記の変更で 4.6.3 がリリースされています
devDependencies にて使用するパッケージのバージョンを指定を修正
Honoが開発で使用するパッケージのバージョンが以下のように修正されました。
-
@hono/eslint-configを1.0.2にアップデート -
wranglerを3.58.0に固定
wrangler のバージョンを固定した糸がちょっとわからないです。
crypto-js を devDependencies から削除
テストコード内でSHA256を生成してテストしているコードがありますが、SHA256は crypto APIを使用して生成できるために crypto-js で生成する必要がないということで変更されたと同時に crypto-js は使用されなくなったので削除されました。
4.6.3以降の修正
変数として宣言されているが、型としか使用していないESLintの警告を無効化するように修正
テストコードの中にはHonoをインスタンス化してテストとして使用していますが、インスタンス化したオブジェクトを変数に入れて型としか使用していないものが存在します。テストコードとしては仕方ないのですが、ESLintの警告が常に出続けるため、PRを出した場合にCIが動いた結果にノイズとして出力されていました。
そこでノイズになるので、その警告を出力しないように該当ファイルはESLintのルールを一部無効化する修正がされました。
4.6.3以降の修正 その2
Bunもカバレッジを計測するように修正
Bunがlcovによるカバレッジの計測に対応したことによりHonoでのテストのカバレッジ計測でBunも計測されるように修正されました。
4.6.3以降の修正 その3
denoのmiddlewareのテストで不要なルーティングを削除
middlewareのテストで同一のルーティングが2重に登録してしまっているテスト用のHonoアプリケーションから不要なルーティングが削除されました。
4.6.3以降の修正 その4
hono/jsx でもカスタムコンポーネントにkeyを設定できるように修正
Reactではどんなコンポーネントでも key のPropsを定義することが出来ますが、 hono/jsx ではカスタムコンポーネントに key を指定すると型エラーが発生するようです。なので key を渡しても型エラーが発生しないように修正されました。
function RenderCustomComponent() {
return <RenderDivComponent key={"key"} value={1} /> // type error: Property 'key' does not exist on type '{ value: number; }'
}
function RenderDivComponent({ value }:{ value: number }) {
return <div key='div'>{value}</div> // no type error
}
4.6.3以降の修正 その5
createMiddleware のジェネリックに指定する型が異なる2つのミドルウェア関数にContextを渡すと型エラーになる不具合修正
自分でもどうタイトルを書くとわかりなすか悩ましいです。
コードを見るのが早いと思います。
const middlewareOne = (_variable: string) =>
createMiddleware<{ Variables: Variables }>(async (c, next) => {
await next()
})
const middlewareTwo = createMiddleware<{ Bindings: Bindings }>(async (c, next) => {
const mw = middlewareOne(c.env.MY_VAR_IN_BINDINGS)
await mw(c, next) // type error
})
このように createMiddleware で生成するミドルウェアの関数でジェネリックに指定する型が異なる場合にミドルウェアの関数からもう1方のミドルウェアを呼び出す際にコンテキストを指定すると型エラーとなる不具合が修正されました。
Service Worker Adapterを使用してルーティングが存在しないURLにアクセスするとエラーが発生する不具合の修正をさらに修正
「4.5.2以降の修正 その2」でservice worker adapterでの不具合に触れましたが、 globalThis からの fetch を正しく取得する方法についてさらに修正されました。
hono/jsx の toStringToBuffer 関数が deno の環境下のテストでエラーが出ないようにリファクタリング
Denoの環境下のテストで toStringToBuffer のエラーが出るようなので override を付与してテスト時にエラーとならないようにリファクタリングされました。
上記の変更で 4.6.4 がリリースされています
app.route の型評価の速度を改善
Honoで app.route という2つの route を結合するような関数が存在しますが、それを使用した場合のハンドラー関数への型評価速度が改善するように修正されました。
4.6.4以降の修正
denoのCI環境でv2を使用するように変更
CIの環境下のdenoのバージョンが1だったものが2に変更されました。
4.6.4以降の修正 その2
denoのCI環境でv1を使用が残っていたためv2に変更
昨日、CIでdenoをv2環境で動作させる修正を行いましたが、まだv1で動作しているCI環境があったため、v2に変更されました。
4.6.4以降の修正 その3
Honoの内部で使用される ExcludeEmptyObject という型を削除
ExcludeEmptyObject というのはいわゆるカラのオブジェクトなのですが、これを別の定義場所に持っていこうとすると Type instantiation is excessively deep and possibly infinite. というエラーが発生するようです。なので使用しなくてもいいように型が修正されました。
CORS Middlewareで設定したOriginと一致しない場合は Response Headersに Access-Control-Allow-Origin を設定しないように修正
CORS MiddlewareでOriginを設定することが出来ますが、設定したOriginとリクエスト元のOriginが一致しない場合でも Access-Control-Allow-Origin が設定されてレスポンスを返していたようです。なので一致しない場合は Access-Control-Allow-Origin を設定せず厳格にレスポンスを返すという修正がされました。
4.6.4以降の修正 その4
Powerd By middlewareを使用して 'X-Powered-By を指定できるように修正
X-Powerd-By は Hono 固定でしたが、このミドルウェアを使用して、Server名を指定することでカスタムのServer名を設定できるオプションが追加されました。
「createMiddleware のジェネリックに指定する型が異なる2つのミドルウェア関数にContextを渡すと型エラーになる不具合修正」の変更を元に戻す
「4.6.3以降の修正 その3」で書いた修正がリバートされました。リバートした理由としては c.get が正常に型が設定されないという不具合を招いてしまったようです。そこで前回の問題の修正を行うためにはすぐに対応方法がないため、リバートされたようです。
CSRF ProtectionにてRequest Headerの Content-Type が未指定の場合は text/plain としてみなすように修正
CSRFのチェックにてRequest Headerをチェックしますが、 Content-Type が未指定のRequestについては text/plain としてみなして動作するように変更されました。なので未指定の場合は基本的にはエラーとなるはずです。
異なるバージョンのHonoを2つ以上プロジェクト内に配置すると #private の型エラーが発生しないようする修正
詳しくは見てませんが、Honoを異なる2つのバージョンをインストールした場合に型の参照がおかしくなるようです。そこでビルド後に出力される型ファイルからprivateな型は削除してエラーが発生しないようにする対応がされました。
bun.lockb を更新
理由はわかりませんが、lockファイルの更新が行われました。何かバージョンの差異が出ていたのでそうか。
上記の変更で 4.6.5 がリリースされています
Powerd By middlewareのJSDocの追加
Powerd By middlewareについてのJSDocが追加されました。現状Powerd By middlewareに関するドキュメントは公式のサイトにはないので後に追加するようのでしょうか。
4.6.5以降の修正
HonoをVS Codeのdevcontainerで使用する際にpodmanで動作するように修正
Honoの開発環境はVS Codeのdevcontainerで動作する設定が存在します。この設定をdockerではなく、podmanでも動作するように修正されました。
4.6.5以降の修正 その2
Secure Headers Middlewareの nonce 値を生成するロジックを読みやすいようにリファクタリング
Secure Headers Middlewareで設定する nonce は c.get('secureHeadersNonce') で取得できますが、ミドルウェアで c.set('secureHeadersNonce', value) をする際の value の値の決定ロジックが内部関数を生成して実行しているため少し読みにくいのか、リファクタリングが提案されてマージされました。
Denoで serveStatic を使用した場合に配信ファイルが見つからない場合は警告表示を非表示にする
Denoではファイルの存在確認が行えないので、存在しないファイルを取得しようとすると必ず例外となるようです。そのため存在しないファイルへのアクセスをするとcatch節に入り、warningのログを必ず出力してしまうようです。そこでファイルが存在しない例外以外の場合だけwarningのログを出力するようにするという変更がされました。
RPCの $url にクエリパラメータを指定した場合にクエリパラメータが付与されたURLで返ってくるように修正
HonoのRPCには $url というメソッドが使用でき、エンドポイントへのURLオブジェクトを返すメソッドがあります。この $url にクエリパラメータを付与しても返ってくるURLオブジェクトにはクエリパラメータ(SearchParams)が無い状態で返ってきていたので、クエリパラメータを含めたURLオブジェクトが返ってくるように修正されました。
上記の変更で 4.6.6 がリリースされています
4.6.6以降の修正
Vercel Adapterのハンドラー関数をNext.js 15で使用できるハンドラーに変更
Next.js 15ではルートハンドラーを定義する際の第2引数はオプショナルとなりました。また、第2引数で指定したとしてもURLパラメータが取得できるだけなので、Honoでは c.req.param() で取得できるため、第2引数は指定しないハンドラー固定を提供するように修正されました。
JWTの認証処理にカスタムSecret Keyで署名されたJWTも認証できるように修正
タイトルの通りそのままなのですが、JWTには署名する際に secret ととなる文字列を指定することができますが、これを指定したJWTの認証処理が行えるように修正されました。
4.6.6以降の修正 その2
カスタムWebSocket Adapterを作成しやすいように接続するためのAPIとなるインターフェースを変更
WebSocketを接続するためにあるヘルパーの UpgradeWebSocket を使用して、独自のAdapterを構築した際に、 UpgradeWebSocket のインターフェースが変更されてしまうとカスタムAdapter側もHonoの変更に追従する必要があります。そこで、ヘルパーのAPIが変更となってもカスタムAdapter側で変更が少なくなるようにWebSocket接続のためのインターフェースとなるAPIが一部変更となりました。
使用感としては今まで通りですが、WebSocketを使った独自Adapterを実装した場合のインターフェースが変更に耐えれるように修正されたくらいだと認識して大丈夫です。
4.6.6以降の修正 その3
ルーティングの速度を改善
コードを読む限り内部的な変更ですが、以下のような修正を行ったようです。
-
for ofからforにループを変更して速度を改善 - ルーティング判定用の内部ルーティング名を削除して、一致したハンドラーは一致フラグ(ループインデックス)から取得
一部IF文のリファクタリングも行われて、可読性を向上させたとありますが、元は早期リターンで書いていたのがIFがネストする形になっているのはいいのだろうかとは思いますが、Honoを使用するユーザ的には「変数が減ってメモリが微小だが軽く」なり「for-of から forに変更して判定速度が微小だが向上」くらいの内容だと思って大丈夫だと思います。
上記の変更で 4.6.7 がリリースされています
4.6.7以降の修正
BunでWebSocketのハンドラーの型を正しい型に修正
Bunを使用して、WebSocketを使用する場合に以下のコードで websocket のハンドラー部分で型エラーが発生してしまっていたようです。原因はWebSocketで処理するメッセージの型が誤っていたようです。型のエラーだけなので型エラーさえ無視してしまえば動作には問題ないようです。
import type { ServerWebSocket } from 'bun'
import { Hono } from 'hono'
import { createBunWebSocket } from 'hono/bun'
const { upgradeWebSocket, websocket } = createBunWebSocket<ServerWebSocket>()
const app = new Hono()
Bun.serve({
port: 4000,
fetch: app.fetch,
websocket, // type error
})
Cookieのパーテイション分割の属性名を正しい属性名に変更
Cookieにはパーティション分割を行う属性名( partitioned )を設定することができますが、Honoから設定しようとすると誤った属性名で型定義されているため、正しい名称で設定しようとすると型エラーが出るそうです。なので正しい属性名の partitioned で設定できるように型定義が修正されました。
4.6.7以降の修正 その2
WebSocket接続のコンテキストクラス名のTypoを修正
「4.6.6以降の修正 その2」で触れましたがWebSocketを使った独自Adapterを構築する際にAPIの変更に耐えれるようにということを書きましたが、それがコンテキスト(Context)というクラスでインターフェースが定義されましたが、Context ではなく、 Contest とTypoされていたクラス名などが修正されました。
WebSocketでストリーミングデータを送信する際にバッファ全体を返してしまう場合がある不具合の修正
具体的には Uint8Array の場合にはバッファ全体を送信する場合にバッファ全体を返すという処理になっていました。そうするとストリーミングで Unit8Array のデータをクライアントに返す際にバッファ全体を送ってしまうので、不要な帯域データを流すことになってしまうということです。
ですので、 Unit8Array でも問題なくストリーミングで送信できるようにそのままデータを送信するという風に変更されました。
Bunでホットリロードした際にWebSocket接続でエラーが起きないように修正
Bunを使用して開発する際に --hot というオプションを付与して起動するとホットリロードするようになるようです。そこでWebSocketを使ったアプリケーションを構築しているとサーバ側はファイルを再読み込みしますが、クライアントからはWebSocketの接続が失われ再接続がされますが、サーバ側は接続情報をグローバルに持っており、古い接続が切れたことを認識できずに古い接続先に対して処理をしようとしてエラーとなるというのが原因だそうです。
なので、接続情報はHono側で覚えるのではなく、Bunが接続しているWebSocket接続に対して処理をするという方法に変更されました。
Request Headerから値を取得する場合のキーに補完されるように型を修正
今まではResponse Headerの設定時に型による補完が効いていましたが、今回はRequest Headerの値を取得する際にキーを指定する c.req.header('<key name>') のキー名に対して補完が効くように型が修正されました。
Hono開発用の docker compose の設定から不要な設定を削除
Honoでは開発環境がすぐに用意できるようにリポジトリにVSCodeのdevcontainerの設定が入っています。その設定の中でPodman対応時に入ってしまった不要な設定(ルートレスの場合の設定)が削除されました。
仮にルートレスでPodmanを使用している方がいればこれが必要かもしれませんが、現状は不要ということで削除されました。
Hono内部の型が循環参照になっているのを修正
Hono内部にはいくつかの型定義があるのですが、型ファイルの参照が循環参照になっているということでそうならないように修正されました。
上記の変更で 4.6.8 がリリースされています
4.6.8以降の修正
様々なTypoを修正
基本的に「テスト内容(it, test, describe)」や「変数名」を中心に多岐にわたるタイポが修正されました。
パスパラメータに無効はURLエンコード文字列があった場合は、無効な文字をそのまま使用するように修正
例えば以下のようなルーティングを作成します。
const app = new Hono()
app.get('/test/:path', (c) => {
retrun c.text(c.req.param('path'))
})
Honoでは :path 部分がダイナミックなURLとして認識されますが、2バイト文字やその他URLに含めれない文字はURLエンコードするとURLとして使えますが、そのURLエンコードが正しくエンコードされてなく、デコード出来ない場合にはそのままの文字を返すという修正が行われました。
以前はデコード出来ない場合はエラーをスローしており、最悪はアプリケーションが停止するという外部からの攻撃をうける可能性があるということでこのように変更されました。
hono/jsx のメモ化の実装方法を変更
ちょっとコード的には難しいのですが、今まではレンダリングした結果をメモリ上に保持し、それをもってメモ化つまりは前回と同一かどうかのチェックを行っていましたが、この変更によりレンダリングする際にそもそも再評価する対象化どうかを新旧のPropsで判断するという手法に変更されました。
フラグメントが連続するJSXが正しくレンダリング出来るように修正
以下のような連続するフラグメントがあった場合に今までは正しくレンダリング出来なかったようなのですが、それが正しくレンダリングされるように修正されました。
const componentChild = () => {
return (
<>
<div>
test child
</div>
</>
)
}
const componentParent = () => {
return (
<>
<componentChild />{/* “Fragment is continuous across components */}
<div>
test parent
</div>
</>
)
}
判定処理を都度行うのではなく、使い回すように修正
Honoには compose という複数のmiddlewareなどを実行を制御している処理があるのですが、その中である引数で渡ってきた値が、 instanceof で特定のものと同一かチェックを行っているのですが、その instanceof の判定を最初に変数にセットして後の処理はその変数の値を使い回すという風にコードが変更されました。
リファクタリングに近い感じのコードですが、Node.jsでは若干のパフォーマンス改善となったため、マージされたようです。
配列のマージ処理にスプレッド構文を使用せず .concat を使用してパフォーマンスを改善
2つの配列を1つの配列にマージするコードとして以下のようにスプレッド構文を使用する方法から .concat を使用するコードに変更されました。
const arrayA = ['A', 'B', 'C']
const arrayB = ['a', 'b', 'c']
// use spread syntax
console.log([...arrayA, ...arrayB])
// use `concat`
console.log(arrayA.concat(arrayB))
このように2つの配列を結合するような処理ではスプレッド構文を使用するよりも .concat を使用した方が処理速度に軍配があがるようです。
deno adapterの処理内に使用されている一部の any を削除するように型定義を修正
DenoのAdapter内に静的ファイルを返す処理があり、そこで一部型定義に any が使用されているので any を使用しないように型定義が修正されました。
4.6.8以降の修正 その2
無駄なスプレッド構文の展開処理などをリファクタリング
大きくは固定オブジェクトにプロパティを追加する際に、元のオブジェクトをわざわざスプレッド構文で展開するというコードなどがリファクタリングされました。
関数を他にある代替の関数に変更することで参照されなくなった元の関数を削除
元々あった存在した関数A(仮称)の中身は他の関数B(仮称)を呼ぶ関数だったため、その関数Aを削除して、関数Aを呼んでいた箇所は直接関数Bを呼ぶという風にコードが変更されました。
変更することにより元々の関数Aは参照されなくなり、コードを削除することでHono自体のバンドルサイズも気持ちですが小さくなるというリファクタリングがされました。
文字列検索に正規表現ではなく、 indexOf を使用することで処理を高速化
URLの中に % の文字(URLパラメータのチェック処理とだと思われます)が入っているかどうかのチェックに正規表現である /%/.test が使われていましたが、固定文字を検索するだけであれば indexOf の方が高速ということで indexOf を使った判定に修正されました。
オブジェクトを entries でKey/Valueでループする処理を for に書き換えて高速化
これはちょっと面白いなと思ったのですが、具体的には以下のようなコードです。
const target = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
}
Object.entries(target).forEach(([key, value]) => {
console.log(`key: ${key}, value: ${value}`))
}
という風にキーと値をセットでループしたい時によく書くコードですが、これは以下のような for で書いた方が処理が早いようです。勉強になりました。
for (let i = 0, keys = Object.keys(target), len = keys.length; i < len; i++) {
const key = keys[i]
console.log(`key: ${key}, value: ${target[key]}`)
}
4.6.8以降の修正 その3
配列判定を Array.isArray を使用するように修正
修正理由はちょっと細かいようですが、ESLintではデフォルトで instanceOf を使うより Array.isArray を使うようにというルールがあるようです。また、コードのバイト数的にも Array.isArray の方が短いということで修正されたようです。
undefined を typeof を使用しない評価式に変更
undefined を評価する方法としてJavaScript(TypeScript)はいくつかありますが、Hono内部で一部 typeof で取得したものから文字列で undefined と一致するかどうかという評価式の記述が、変数自体が、 undefined と等価かどうかの評価式に変更されました。
JavaScriptって怖いのは undefined という変数を作ってそこに値を入れれます。それを評価式に使うと…(笑)
無駄なスプレッド構文を削除してコードを読みやすく変更
このコミットは何パターンかのスプレッド構文を読みやすくしているのですが、例えば以下のような無駄なスプレッド構文の変更などがされています。
const hoge = { fuga: 'fuga' }
const other = { test: 'value' }
-{
- ...{
- hoge,
- ...other
- }
-}
+{
+ hoge,
+ ...other
+}
for ループに書き換えた速度改善コードを一部 for-of に戻す
昨日の for への繰り返し処理のコード変更から配列自体がそこまで大きくないと for-of もそこまで遅くないのと、コードの可読性から読みやすい for-of に戻したようです。
c.redirect の引数に URL を渡せるように修正
リダイレクトの処理には c.redirect の引数に文字列でURLを指定する必要がありましたが、URLオブジェクトそのものを渡せるようにするという変更がされました。これにより文字URLオブジェクトわざわざ文字列に変換せずとも渡せるようになりました。
4.6.8以降の修正 その4
CIでBunおよびDenoの最新バージョンを使用するように修正
Denoは何回かCIのバージョン修正が行われていますが、まだ少し残っていたようです。Bunに関しては使用するGitHub Actionsのバージョンをv2にアップデートしつつ、Bunの最新バージョン(今日 1.1.34 がリリースされてますが)である 1.1.33 にアップデートされました。
Issue Templateに可能であればランタイムのバージョンも記載してもらうように修正
1つのランタイムでもバージョンごとに動作が異なる可能性も無いので、バージョンを記載してもらい報告内容の再現を用意にしたい目的だと思います。
Logger Middlewareの出力ログのカラーを最適化
今まではhttpステータスで以下のカラー表示でした。
- 700番台 : マゼンタ(ピンクぽい色)
- 500番台:赤
- 400番台:黄
- 300番台:シアン(水色ぽい色)
- 200番台:緑
- 100番台:緑
- 100未満:黄色
- 上記以外は白
それが以下のように変更されました。
- 500番台:赤
- 400番台:黄
- 300番台:シアン(水色ぽい色)
- 200番台:緑
- 上記以外は白
700番台はそもそも出力できないので削除していいとは思うんですが、100番台ってWebSocketのステータスで使うような気がして、そこは削除しないくてもよかったのかなとか見てて思ったりしました。
重複しているMimeTypeの型定義を1つに定義するように修正
微妙に書き方が異なる2つのMimeTypeの型があったのを1つに纏めて定義するように型定義が修正されました。
4.6.8以降の修正 その5
バグでないIssue報告は自動的にCloseするcronジョブを作成
Issue報告で not bug のラベルが付与されたIssueは最短で9日後に自動的にCloseされるCIのジョブが作成されました。これにより報告後に放置されたIssueが自動的に削除されるようになります。
Math.floor をビット論理和に変更して速度を改善
ハックぽいコードですが、整数以下を切り捨てる Math.floor の関数がありますが、ビット論理和を使用して同等のことをして速度を改善するというコードに一部変更されました。
console.log(Math.floor(560 / 100))
console.log(560 / 100 | 0)
この2つのコードは結果的には 5 を出力し、同値になります。ただし、これは 正数値ではという条件になりますので、使用には注意が必要です。
Cookieのパース処理でNameが指定されている場合のデータ返却を高速化
単純なロジックの変更ですが、今まではCookie全体をパースしてからNameが指定されている場合は指定のNameに対応したCookieを返すという処理でしたが、Cookieをパースしていく過程で指定のNameのものが見つかった場合は即座に返すという処理に変更されました。
Privateな関数名がMinifyされた場合にMinifyされるようにリファクタリング
ESBuildでは class 定義でprivateな関数を定義してビルドした際は関数名がそのまま出力されてMinifyされないようです(知らなかった)そこで、privateな関数はMinifyされてHonoサイズを小さくしようというのがこのコミットの意図です。対応としてはprivateな関数の先頭に # を付与するとMinifyされるということでそのように変更されています。
class A {
#myPrivateMethod() {}
myPublicMethod() {
this.#myPrivateMethod()
}
}
"use strict";class A{#t(){}myPublicMethod(){this.#t()}}
Cloudflare Workers環境下ではWebSocketの onOpen イベントハンドラを使用できないように型定義を修正
HonoのWebSocketを使用する場合に接続が開始されたイベントに onOpen が存在しますが、Cloudflare Workers環境だけは使用することができません(ドキュメントに記載あり)。しかし、TypeScriptの型定義上は使用できる風に書けてしまうので、Cloudflare WorkersでのWebSocketは onOpen のイベントハンドラを型定義から除外するように修正されました。
4.6.8以降の修正 その6
StreamingでResponseを返す際にETagが正常に動作するように修正
HonoにはEtagのHeaderを設定してくれるミドルウェアがあります。このミドルウェアを使用するとEtagに関するレスポンスヘッダーを設定してくれるのですが、Streamingでデータを返却する際には同じEtagを返してしまい、正常にEtagが設定されないという問題があったようです。
原因としてはStreamingを返す際にETagに設定するsha1を何で計算するかということで、StreamingのレスポンスBodyではうまく計算できなかったようです。ですのでこの修正ではレスポンスのBodyからETagに設定するsha1の計算をロジックを変更して(sreamから読み込み crypto.subtle でsha1を計算)StreamingでもEtagが正常に設定されるという変更を行ったようです。
ハッシュ値計算関数の引数の型から曖昧な object の型を削除
Etagの修正と同時にハッシュ値の計算を行う関数が受け入れる引数に object という型がありましたが、正確にはJSONデータであり、 object という曖昧な型からJSONという正確な型に変更されました。
上記の変更で 4.6.9 がリリースされています
jsrのpublishに bunx を用いて行うように変更
元々はdenoのコマンドで実施していたのですが、なぜかbunxを用いてdenoを動かしています。直近v2に変更した影響ですが、理由等が書いてないので不明です。
jsrのpublishを行う時に必要なライブラリをインストールするように変更
上記の理由不明の原因はこれでしょう。どうやら 4.6.9 をリリースがうまく動作しないのは環境の問題(bunを入れて動作してみたが動作しなかったのでしょう)ではなく、そもそもリリースする deno のコマンドを打つ時に必要ライブラリをインストールする(deno install)という手順がなくライブラリがなくてコマンドが失敗していたのを修正したようです。
cronジョブのCIから無駄な空白を削除
昨日の「4.6.8以降の修正 その5」に書きましたが、バグでないIssueを自動的に削除するcronのCIが設定されましたが、yamlファイルに無駄な空白があったようなのでそれが削除されました。
4.6.9以降の修正
deno環境下でのカバレッジを計測するように修正
Honoではいくつかのランタイムでテストが実施されていますが、denoの環境下ではカバレッジが計測されていなかったので、計測するように修正されました。
ちなみに計測自体はしていたのですが、deno環境下固有のテストについてのカバレッジが計測されてなかったので、無理やりdeno用のテストカバレッジのみを抽出して出力しているようです。
devDependencies のパッケージをバージョンアップ
devDependencies つまり開発のために使用しているライブラリが複数アップデートされました。特に以下のパッケージはマイナーバージョンアップを行っております。(特に zod が古かった?)
-
@hono/node-server(1.8.2 -> 1.13.5) -
ws(1.17.0 -> 1.18.0) -
zod(3.20.2 -> 3.23.8)
4.6.9以降の修正 その2
JSRからhonoをインストールした場合にTimeout Middlewareが使用できない不具合修正
JSRに公開されているHonoではTimeout Middlewareが使用出来ないようです。どうやら原因はユーザがインポートするための設定が jsr.json に記載する必要がありますが、Timeout Middlewareの記載が漏れていたのが原因だそうです。
objectのプロパティ設定に省略記法に修正して少しでもサイズを小さくするようにリファクタリング
objectのプロパティを設定する場合は { key: key } という風に key というプロパティに key という変数を設定する場合は省略記法として { key } という風に記載するように出来ますが、これをすることでHono自体のminifyした際に少しでもサイズが小さくなるということで軽いリファクタリングがされました。
package.json と jsr.json の exports に差異がないかチェックを行うように修正
Timeout Middlewareが利用出来ない件がありましたが、結局 jsr.json 自体が人の手によって管理されていることが原因ということで、それを自動的チェックしましょうというのがこのコミットの意図だと思います。ミドルウェアが追加された場合はnpm側のために package.json の exports が修正されますが、 jsr.json も同時に修正する必要がありそれをビルド時にチェックするという修正がされました。
この修正により ConnInfo Helper がJSRの参照が漏れているらしく同時に修正されています。
4.6.9以降の修正 その3
Denoの環境下でディレクトリへのURLアクセスで404を返さない不具合修正
コミットの内容を見る限り、Denoだけのようですが、serve-static を使用して静的ファイル配信を設定した場合にディレクトリへのアクセス( /public/hoge/ のような)が404にならずアプリケーションがエラーになってしまう不具合が修正されました。
Service Worker Adapterのtypoの修正
Service Worker Adapter内にあるJSDocのコメントで Service Worker ではなく Cloudflare Workers とtypoされているコメントが修正されました。
4.6.9以降の修正 その4
不要な判定の削除と1度しか使用しない変数の削除を行うリファクタリングを実施
タイトルからわかる通り2つの変更がこのコミットにあります。1つは「そもそもif文の判定が必要ないものの削除」という風にそもそも判定する必要がなくなったものが残っているので、それを削除したようです。
もう1つは1回しか使用しない変数定義を削除して、インラインの記述に変更するコードのリファクタリングを実施したようです。インラインにすることで可読性が失われますが、Hono自体のバンドルサイズが小さくなるということでマージされたようです。
4.6.9以降の修正 その5
判定が必要ないIF文を削除してバンドルサイズが小さくなるように修正
Honoのルーティング判定処理にて判定が必要ないIF文を削除することによりHono自体のバンドルサイズが小さくなるように修正されました。
また、IF文の修正とは別にprivateな関数名に略称が使用されており、名称がわかりにくいので略さない関数名に直すといった細かな修正も一緒に入っているようです。
4.6.9以降の修正 その6
classのprivateなメンバ変数に # を付与してバンドルサイズが小さくなるように修正
ここ最近Honoがprivateな関数名がMinifyされて小さくされるように # を関数名の先頭につけていますが、classのメンバ変数名もMinifyされて小さくなるように修正されました。
ただ、ここ最近の違和感が私にはあって、そもそも現状がpublicの関数だったり、メンバ変数なんで冒頭に private と書けばMinifyされるのでは?とか思ったりしてるので試してみる価値はあると思っています。
class Sample {
#sampleAttribute = '' // こう宣言するのではなく↓
private sampleAttribute = ''
set setAttr(val: string) {
this.sampleAttribute = val
}
get attr(): string {
return this.sampleAttribute
}
}
const sample = new Sample()
console.log(sample.sampleAttribute) // これはprivateなのでエラーになる
console.log(sample.attr) // output => ''
sample.setAttr = 'B'
console.log(sample.attr) // output => 'B'
Combine Middlewareの every を使用すると正しいURLパラメータが取得できない場合がある不具合修正
複数のmiddlewareを組み合わせて検証を実行するCombine Middlewareというものがあり、そのmiddlewreには every というすべてのmiddlewareの検証が正しくないとエラーとなるAPIがあります。しかしその every を使用するとURLパラメータが正しく取得できない場合があるという不具合がこのコミットで修正されました。
上記の変更で 4.6.10 がリリースされています
ただ、ここ最近の違和感が私にはあって、そもそも現状がpublicの関数だったり、メンバ変数なんで冒頭に private と書けばMinifyされるのでは?とか思ったりしてるので試してみる価値はあると思っています。
どうやらesbuild, 各minifierの仕様で、privateって書いてもminifyされないみたいです。
これに関しては、TypeScriptがprivate ~をJavaScriptにするときに、publicなプロパティにしてしまうので、minifiy時にプロパティ名が圧縮されないんだと思います。
https://www.typescriptlang.org/play/?#code/MYGwhgzhAEASD2A7e0DeAoaXoAcBOAlgG5gAuAptAGYF7kAUAlGgL7otA

(授業中なので超簡易的ですが、お許しください・・・)
情報ありがとうございます!
このPRも読んだはずが、private修飾子のことまで言及されてるのが抜けてました。
TypeScript上はprivateでも結局はJavaScriptのpublicなプロパティとして残るのか。
4.6.10以降の修正
READMEに記載しているバンドルサイズの修正
4.6.9までにclass構文の関数名やメンバ変数の先頭に # を付与することでMinifyされるようになり、Honoのバンドルサイズが13kbから12kbになったことによるREADME記載のバンドルサイズが修正されました。(実態としては11.5kbらしいです)
ビルド時の不要な型削除の進行状況カウントが1から始まるように修正
「4.6.4以降の修正 その4」で記載したようにビルド時にprivateな型の削除を行いますが、その際に表示されるログに進行状況を示す数字が出力されますが、それが0から始まるのではなく、1から始まり、全体数で終わるように修正されました。
4.6.10以降の修正 その2
クエリパラメーターのベンチマークに qs のライブラリを追加
Honoでは他のライブラリとの比較にベンチマークを使用したりしますが、そのベンチマークの中に qs というクエリパラメータを処理するライブラリを追加してHonoとの速度比較を行うように修正されました。
私自身 qs というライブラリを知らなかったのですが、どうやらHonoの方が数倍処理が早いようです(ランタイムによって若干のばらつきがある)
createHandlers で作成したハンドラーの Context は、前段のミドルウェアで設定した Context を考慮した型となるように修正
Honoに createHandlersという複数のミドルウェアやハンドラーを組み合わせてルートのハンドラーを作成するというAPIがあります。このAPIを使用すると以下ようなルーティングの定義ができます。
import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'
// ...
const factory = createFactory<Env>()
const middleware = factory.createMiddleware(async (c, next) => {
c.set('foo', 'bar')
await next()
})
const handlers = factory.createHandlers(logger(), middleware, (c) => {
return c.json(c.var.foo) // this line is type error
})
app.get('/api', ...handlers)
この例では前段のミドルウェアで c.set('foo', 'bar') があるので、後続の処理では c.var.foo つまりは c の Context の型が自動的に変わっててほしいのですが、そのような型定義になっていないという問題がありました。このコミットにより createHandlers のジェネリックの型が修正されて、前段のミドルウェア等のハンドラーの処理で返る Context の型が後続のハンドラーに渡るようになりました。
Honoのバンドルサイズが変更前後でどのように変化するかのCIを追加
バンドルサイズを少しでも小さくした方が使用するユーザとして嬉しいのでHonoとしてはサイズを極力小さくするようにしています。そこでPull Requestやマージ後のファイルサイズがどのように変化したかを見るためのCIが作成されました。
4.6.10以降の修正 その3
Honoの修正前後による計測プログラムを整形処理の対象とするように修正
HonoにはCIで型の速度チェックやバンドルサイズのチェックを変更前と変更後に計測するプログラムがあります。そのプログラムが格納されているディレクトリも prettier による整形の対象とするように修正されました。
4.6.10以降の修正 その4
ビルドおよび計測プログラムもLinterを行うように修正
「4.6.10以降の修正 その3」ではコードの整形を対象としましたが、ビルドおよび計測用のコードもLinterの対象とするように修正されました。
Pull Requestごとにバンドルサイズはファイル数やコード行数などの変化が修正前後で自動でコメントされるようにCIを修正
今までHonoのバンドルサイズの変化などの見るコードの変更はありましたが、Pull Requestごとにコメントとして表示される対応はされていませんでした。しかし、このコミットにより変更前後でバンドルサイズやファイル数や型数などがどのように変化するかというのがPull Requestに自動的にコメントされるように修正されました。
4.6.10以降の修正 その5
Hono内部で使用していた errorHandler メソッドを # を使用せずprivate修飾子で定義するように修正
どうやら修正の意図としては # を先頭に付与したprivateな関数名を別のところから呼び出すとうまく呼び出せずエラーになるようです。そこで # の使用は諦めてprivate修飾子で定義するように修正されました。
上記の変更で 4.6.11 がリリースされています
4.6.11以降の修正
CIのバンドルサイズのチェックにKB単位のサイズを表示するように修正
バンドルサイズの変更前後を表示するCIの処理にキロバイト単位で表示する処理が追加されました。
マッチしたリクエストのルーティングをソートする処理の速度を向上させる変更
特定条件になりますが、マッチしたルーティングをスコア順(マッチ順序)にして返す場合にそもそもマッチしたルートが1もしくは0(無い)場合のルート定義を並び直して返す必要がないため、そのまま返すという条件文を追加して少しでも処理速度をあげる修正がされました。
4.6.11以降の修正 その2
style タグと script タグに nonce を設定できるように修正
style タグと script タグにはCSPである nonce 属性が設定できますが、この変更により hono/jsx で2つのタグに nonce 属性値つまりPropsが設定できるようになりました。
import { Style } from 'hono/css'
export const Sample = () => {
return (
{/* <style nonce='1234'>...</style> */}
<Style nonce='1234' />
)
}
4.6.11以降の修正 その3
AWS Lambdaでコンソールからテストを実行するエラーとなる問題を修正
HonoをAWS Lambda adapterを使用してAWS Lambdaで使用することができますが、AWSのコンソールから該当のLambdaのテストを実行するとエラーとなってしまうようです。原因としてはAWS Lambda adapter内でALBからの呼び出しかを判定している処理があるのですが、コンソールから直接呼ぶため、その判定で使用するオブジェクトが null になっており、判定そのものは object が来ると想定しており、その object の中に特定のプロパティを持っているかチェックしているためにエラーとなるようです。
なので、プロパティのチェックの前にそもそも該当の object が存在するかのチェックを行うことでエラーを回避するように修正されました。
上記の変更で 4.6.12 がリリースされています
4.6.12以降の修正
配列の最後の値を取得するための処理を Array.prototype.at() にリファクタリング
配列の最後の値を取得する方法はいくつかありますが、今では Array.prototype.at() を使用して取得するのが一番てっとり早いです。そこで Array.prototype.at() を使用するようにリファクタリングされました。リファクタリングすることで少しですが、バンドルサイズも小さくなるようです。
4.6.12以降の修正 その2
API Gateway v1での multiValueQueryStringParameters をサポートするように修正
かなり前ですが、HonoのAWS Lambda adapterで multiValueQueryStringParameters いわゆる配列となるクエリストリングの対応がされました。対応したのではAPI Gateway v2での対応で、API Gateway v1は対応されていなかったため、この修正で対応されるようにようなりました。
Cloudflare Workers adapterの serveStatic のdeprecatedの理由を追記
Cloudflare Workers用のadapterにも serveStatic いわゆる静的ファイル配信のAPIがありますが、Cloudflare Workersは9月にCloudflare Workersから静的ファイルを配信するための機能追加がされました。そのため serveStatic に頼らずとも配信が可能です。
そこで serveStatic のdeprecatedの理由にCloudflare Workers Assetsのことがコメントで追記されました。
4.6.12以降の修正 その3
CORS Middlewareで204を返す場合に statusText を固定で返すように修正
CORS Middlewareで204を返す場合に前の処理の statusText を返していましたが、前の処理などで404を設定すると正しい statusText になるとは言えないので204を返す場合は 'No Content' を固定で返すように修正されました。
4.6.12以降の修正 その4
IPv6の後ろにIPv4が付与されるアドレスが正常に処理できない不具合の修正
IPv6の形式にはIPv4が後ろに付与されたアドレスを指定することができます。例えばISATAPというもので使用したりします。
::ffff:127.0.0.1
このようにIPv6の後ろにIPv4の形式のアドレスが付与されるようなアクセスをした場合にHonoがうまくIPアドレスを取得できず、エラーになってしまうという不具合が修正されました。
上記の変更で 4.6.13 がリリースされています
4.6.13以降の修正
カラオブジェクトの生成を事前に行い、routeのマッチ時のパフォーマンスを改善する修正
routeがマッチするかどうかに正規表現が使用されている箇所があります。その正規表現で一致した groups つまりはURLパラメータになる部分(たぶん、、、全部のコードを読んでないので自信がない)を格納していますが、 groups がない場合はカラのオブジェクトを保持する処理があります。そのカラのオブジェクトを groups が存在しない場合に都度 Ojbect.create(null) を使用して生成していましたが、予め処理外で作成しておき、それを使い回すようにしてrouteのマッチ処理のパフォーマンス改善をしたという修正のようです。
スプレッド構文による展開するカラオブジェクトを事前に生成したものを使用してパフォーマンスを改善する修正
これも上記の修正と同じように事前に Object.create(null) を処理外の変数に保持して、使い回すことでパフォーマンスを改善する修正のようです。こちらはスプレッド構文内で Object.create(null) がされていたのをやめたという方針は一緒ですが、修正箇所が若干異なるというものです。
4.6.13以降の修正 その2
serveStatic で静的のJSONファイルを返す場合にMINE Typeに charset を付与しないように修正
タイトルのままですが、serveStatic でJSONファイルを返す場合のMINE Typeに charset つまり application/json; charset=utf-8 のような文字列のMINE Typeが設定されますが、そもそもJSONはUTF-8のみなので charset は出力すること自体が仕様として正しくないということで修正されました。
Streaming Helperの pipe 使用時に不要なログが出ないように修正
HonoでStreamingを使用するのを簡易にできるStreaming Helperというものが存在しますが、そのヘルパーでstreamingを pipe するAPIがありますが、そのAPIを使用すると undefined のログが出力されるという不具合が修正されました。この不具合はNode.jsでは発生しませんが、他のランタイム(AWS LambdaやBun)では出力されてしまっていたようです。
上記の変更で 4.6.14 がリリースされています
4.6.14以降の修正
JSRのリリースに不要なマークダウンファイルを含めないように修正
JSRのリリースに含めるファイルの中に CODE_OF_CONDUCT.md や CONTRIBUTING.md などのマークダウンファイルを含めてリリースしていましたが、現在では不要なのでリリースファイルの中に含めないように修正されました。
レスポンスBodyを設定する場合に 204 などのスタータスコードを設定すると型エラーとなるように修正
httpステータスに 101 や 204 といったBodyを返さないステータスコードがあります。HonoではBodyを設定した上でBodyを返さないステータスコードを設定してしまうとエラーになる場合があるそうです。そこでBodyを設定する場合には 101 などのステータスを設定すると型エラーになるように修正されました。
三項演算子によるLintエラーを修正するようにリファクタリング
Honoで設定している三項演算子のLintでエラーが発生したため、if文に変更するリファクタリングが行われました。
4.6.14以降の修正 その2
Bodyを返さないステータスを指定する場合に、型エラーとならない場合がある不具合の修正
前回の修正で、204などのBodyを返さないステータスコードを指定する場合は型エラーとなるように修正されましたが、あくまで c.json や c.text などの第2引数に数字つまりステータスの数字が指定される場合は対応されていましたが、 { status: 204 } などのレスポンスの第2引数ようのような指定方法ではBodyがあっても204などのステータスを指定しても型エラーとなっていなかったようです。
そこでこのコミットでは第2引数にレスポンスを生成する第2引数のような指定でも型エラーとなるように修正されました。
CookieのPriority属性のサポート
私も知らなかったのですが、CookieにはPriorityという属性が指定できるようです。Chromeだけの仕様?Cookieのデータが消える際にどれを優先して消していくかという指定の属性のようです。
HonoでこのPriority属性を指定できるようにサポートが追加されました。
モノレポで2つの異なるHonoのバージョンを使用している場合にSSGヘルパーが正しく動作しない不具合の修正
そもそもこの修正の再現というか現象の説明が困難なようですが、タイトルような場合の不具合が発生するようです。原因としてはルーティングを設定する場合に一致するハンドラーを探す場合にSymbolをキーに設定しているようですが、なぜかSymbolが一致するにも関わらず、一致しないルーティングとして認識されるのが原因のようです。そこで修正としてはSymbolを使用せず、文字列で一致するかどうかの判定に変更されました。
上記の変更で 4.6.15 がリリースされています
4.6.15以降の修正
hono/jsx の useContext を使用して状態を変更しても変更された状態が取得されない不具合の修正
hono/jsx もReactと同様に useContext を使用してコンテキストに設定した状態を管理することができますが、4.5以降に useContext を使用した状態管理では状態を変更しても変更された状態が取得されない、つまりメモ化されたデータが取得されてしまうという不具合が修正されました。
4.6.15以降の修正 その2
複数のResponseを返すハンドラー内で c.body を使用するとHono RPCでレスポンスの型が1つに固定される不具合を修正
例えば以下のような複数のResponseタイプを返すハンドラーを定義します。
import { Hono } from 'hono';
const app = new Hono()
.get('/hello', async c => {
const time = Date.now();
if (isWinter(time))
return c.text('You cannot use this winter', 400)
if (isSummer(time))
return c.text('You cannot use this summer', 400)
return c.body(null, 204)
})
この場合にHono RPCを使用して、返り値の型は400や204のResponseが返ってくるという型になるはずです。しかし、型は204のResponseのみが返ってくるという型になってしまうという不具合が修正されました。
不具合が起きた原因としては直近に修正された204などのhttpステータスコードを設定する場合にBodyを設定しないようにする型修正が行われましたが、その影響によるものです。ですので、4.6.15を導入済みのユーザはバージョンを更新するのが良いです。
app.on でContextの型が拡張されない型エラーを修正
app.use や app.get には処理を行うハンドラーと同時にミドルウェアの設定も可能です。同じく app.on というものもあり、同様にミドルウェアを設定が出来ます。しかし createMiddleware<YourType> といったContextの型を拡張したミドルウェアを app.on に渡すと型エラーとなり、ミドルウェアのハンドラーの型エラーが発生するという型の不具合が修正されました。
上記の変更で 4.6.16 がリリースされています
4.6.16以降の修正
createMiddleware の返り値の型を修正して、コードサイズを削減
createMiddleware に定義されている返り値の型を依存関係を正しい依存関係として、シンプルな型定義に修正されました。これによりビルド後の型定義が少しだけ小さくなるように修正されています。
4.6.16以降の修正 その2
Compress MiddlewareとStreaming Helperを併用してもレスポンスが圧縮されないように修正
Compress Middlewareを使用した上で、Streaming Helperを使用してレスポンスを生成するとストリーミングのレスポンスにならず、期待したレスポンスとならない不具合がこのコミットで修正されました。原因としてはServer Sent Event(SSE)のレスポンスがCompress Middlewareによって圧縮されることが原因のようです。
ですので修正としてはCompress Middlewareで、SSEは圧縮しないように判定処理が追加されました。
ビルド時のprivateな型定義を削除する処理を高速化
4.6.4以降の修正 その4で以前書きましたが、Honoはビルド時にprivateな不要な型を型定義から削除する処理が入っています。その処理を高速化する変更がこのコミットで行われました。
具体的な高速化の方法は以前は単純にfor文で処理を繰り返していたのですが、Worker Threadsを使ってCPUのコア数分に並列に削除処理を行うようにするという処理に変更して高速化を実現したようです。
4.6.16以降の修正 その3
誤っているコメントの削除
Honoにある誤っているコメントが削除されました。
上記の変更で 4.6.17 がリリースされています
4.6.17以降の修正
型推論パフォーマンスが向上するリファクタリングを実施
どちらも目的としてはTypeScriptでの型を推論するためのパフォーマンスチューニングが実施されています。これら2つのコミットはともにTypeScriptの Instantiations が減少し、型推論のパフォーマンスが向上するようになっています。
4.6.17以降の修正 その2
3つ以上のミドルウェアを定義する場合に、中間のミドルウェアでContextの型が正常に生成されない型不具合の修正
Honoでは1つのルーティングに対して、複数のミドルウェアを定義することが出来ます。その定義したミドルウェアは前のミドルウェアのContextを引き継いだ状態のContextの型となりますが、3つ以上ミドルウェアを定義した場合に中間つまり最初と最後以外のミドルウェアハンドラーのContextの型が正しくなくなるという型の不具合が修正されました。
type UserContext = {
Variables: {
userId: string
}
}
const app = new Hono().get(
"/ws",
createMiddleware<UserContext>(async (c, next) => {
c.set('userId', "12345")
await next()
}),
async (c, next) => { // cの型が正しくない
await next();
},
async (c, next) => { // cの型は正しい
await next();
}
);
Issueにあったサンプルコードを拝借しましたが、このように中間のミドルウェアのContextつまり c の型が正しくなくなってしまいます。そこで型が正しくなるように修正されましたが、今回の修正でTypeScriptの型推論の計算量が増えることになるようです。
4.6.17以降の修正 その3
factory.createMiddleware で生成したミドルウェアを使用したルーティングの hono/client で正しい型が生成されるように修正
Honoのミドルウェアは createMiddlewre および factory.createMiddleware を使用して作成することが出来ます。これらで作成したミドルウェアを .use でミドルウェアを定義した場合に factory.createMiddleware で作成したミドルウェアを使用したルーティングで hono/client つまりはRPCでの型が正しく生成されないという型の不具合が修正されました。
上記の変更で 4.6.18 がリリースされています
4.6.18以降の修正
handlerの型にResponseの型がジェネリックで定義するように修正
Handlerの型はジェネリックで指定することが出来ますが、Handlerが返すResponseの型がジェネリックから漏れていた型の修正がされました。
4.6.18以降の修正 その2
hono/adapter の env が new Hono<T> のジェネリックの型を参照出来ていない型不具合の修正
new Hono<{ Bindings: { SAMPLE: string } }> という風に Context の env の型をジェネリックスで指定することが出来ますが、 env を参照する方法として hono/adapter で Context の env を参照する方法もあるようですが、そちらで参照した場合の env の型がジェネリックで指定した型にならないという型定義が修正されました。
import { Hono } from "hono"
import { env } from "hono/adapter"
type Env = {
Bindings: {
MY_VAR: string
}
}
const app = new Hono<Env>()
app.get('/var', (c) => {
const { MY_VAR } = env<{ MY_VAR: string }>(c) // ここで型エラーが出る
return c.json({
var: MY_VAR,
})
})
上記の変更で 4.6.19 がリリースされています
4.6.19以降の修正
Bunの特定のバージョン以降ではStreamでAbortSignalによるキャンセルを行わないように修正
Bunの1.1.27以降はStreamをキャンセルするのにAbortSignalを送らずともキャンセル処理がされるようになったようです。そこでBunの1.1.27以前のバージョンではAbortSignalでキャンセルを行いますが、それ以降のバージョンではAbortSignalを行わないように修正されました。
4.6.19以降の修正 その2
ロックファイルをテキストベースの bun.lock に変更
HonoではパッケージマネージャにBunを使用していますが、Bunがテキストベースのロックファイルに対応しています。Bunのブログで1.2の変更にも記載されていますが、テキストベースのロックファイルに対応した最小のバージョンは1.1.39からのようです。
npm publishするためのライブラリのバージョンを更新
上記でBunのテキストベースのロックファイルに変更されましたが、それに付随してHonoではnpm publishするために np というライブラリを使っています。そのnpを変更したBunのテキストベースに対応するためのバージョンに更新がされました。
Lambda Edge AdapterでCNAMEに対応するように修正
CloudFrontでは1つで複数のCNAMEに対応できますが、それを対応するための変更が行われました。また合わせて、Cookieに複数のキーを設定できるようにも対応されています。
上記の変更で 4.6.20 がリリースされています
4.6.20以降の修正
CONTRIBUTING.md から yarn に関する記述の削除
先日bunのロックファイルがテキストベースに変更されましたが、その際に yarn.lock も削除されました。削除した理由はBunのロックファイルがバイナリであったためテキストベースとして yarn.lock を使用していたためですが、Bun自体でロックファイルをテキストベースに変更したため、 yarn.lock は削除されております。
そこで CONTRIBUTING.md には yarn を使っての記述がありましたが、 yarn.lock が無くなってしまったので使用することはできず、 yarn の記述は削除されました。
4.6.20以降の修正 その2
リクエストヘッダーの値取得のためのキーを小文字に変換する処理を削除
リクエストヘッダーから値を取得する際にキーを指定しますが、指定されたキーを小文字に変換してから取得する処理がありました。わざわざ小文字に変換せずとも取得できるので、変換処理分の計算コストを削除して少し処理が効率化されるように変更されました。
4.6.20以降の修正 その3
hono/adapter の env が new Hono 時にenvironmentの型を指定していない場合にジェネリックの型を型不正が出る不具合修正
タイトルだけ見ても何言ってるかわからないと思うのでコードで書きます。Honoで env を使用する際はドキュメントにあるようにこのように書きます。
import { env } from 'hono/adapter'
app.get('/env', (c) => {
// NAME is process.env.NAME on Node.js or Bun
// NAME is the value written in `wrangler.toml` on Cloudflare
const { NAME } = env<{ NAME: string }>(c)
return c.text(NAME)
})
この例では new Hono が省略されていますが、 new Hono 時にジェネリックで型を渡すのではなく env を使用する際にジェネリックで型を指定しますが、この new Hono 時にジェネリックで指定しない場合に型が正常に定義されないという不具合が修正されました。
4.6.20以降の修正 その4
VitestをVer3にアップグレード
先月リリースされたVitestをVer3にメジャーアップグレードさせたようです。Vitest ver3がリリースされてからパッチリリースがいくつか出ましたが落ち着いてきたようですね。
4.6.20以降の修正 その5
末尾がワイルドカードの場合のパラメータ取得が正常に行えるように修正
HonoのTrieRouterで以下のようなルーティングを定義した場合にパラメータである dir が正常に取れないということがあったようです。そこで params('dir') でパラメータ取得が正常に行えるようにという修正がされました。
router.add('GET', '/:dir{[a-z]+}/*/file.html', 'file.html')
// GET /foo/bar/file.html => params('dir') is undefined
4.6.20以降の修正 その6
ここからはリリースされた 4.7.0 のコミットの説明になっていきます。
私の都合上今日で全部書くのは無理なんで、少しだけにして、後日すべて記載します。
Proxy Helperの追加
Honoに新たなHelperとしてProxy Helperが登場しました。その名の通りHonoをProxyとして使用する場合に処理を簡単にしてくれるものです。実際にProxyを使用した場合としてない場合の処理の違いは以下です。
app.get('/proxy/:path', (c) => {
return proxy(`http://${originServer}/${c.req.param('path')}`)
// fetch(
// `http://${originServer}/${c.req.param('path')}`,
// {
// method: c.req.raw.method,
// headers: c.req.raw.headers,
// body: c.req.raw.body,
// }
// )
})
わかりやすく書くとこんな感じの処理をProxy Helperがしてくれます。もちろん元のリクエスト情報をそのまま別サーバに渡すだけでなく、RFC2616つまりHTTP/1.1の仕様による「Hop-by-Hop」というサーバを経由した場合のResponse Headersの処理などもやってくれているようです。
Loggerの出力パスにクエリパラメータを付与して出力するように変更
今までのLoggerはクエリパラメータ部分がパラメータ値だけでした。クエリパラメータを多様するようなアプリケーションではあまり親切ではないので、クエリパラメータを含むURLのパス部分をすべて出力するように変更されました。
4.6.20以降の修正 その7
続きで、リリースされた 4.7.0 のコミットの説明になっていきます。
createFactory に Honoのデフォルトオプションを指定できるように修正
4.7以降は createFactory で作成したインスタンスに予め new Hono する際のデフォルトのオプションを指定できるようになりました。ドキュメントにも書いています。
const factory = createFactory({
defaultAppOptions: { strict: false },
})
const app = factory.createApp() // `strict: false` is applied
仮に上記の factory.createApp を何回も呼び出すようにものなら更に恩恵がありますが、最初に指定した { strict: false } が常に new Hono つまりは createApp する際に渡されるようになるということです。
Language Middleware の追加
多言語対応するような場合にクライアントの言語を対応するかというのを行ってくれるミドルウェアが追加されました。このミドルウェアの言語判定は以下の4つ存在するようです。
- URLパスの一部を言語判定を行う
- クエリストリングで言語判定を行う
- Cookieの値から言語判定を行う
- リクエストのヘッダーから言語判定を行う
という風に4つ中から開発者が判定の優先順を決めて、言語を判定する処理が行えるようにするためのミドルウェアのようです。ミドルウェアが判定した言語は c.get('language') で取得できるようです。
const app = new Hono()
app.use(
languageDetector({
supportedLanguages: ['en', 'ar', 'ja'], // Must include fallback
fallbackLanguage: 'en', // Required
})
)
app.get('/', (c) => {
const lang = c.get('language')
return c.text(`Hello! Your language is ${lang}`)
})
レスポンスボディにBuufersを指定できるように修正
ファイルをStreamで返すのではなく、データそのものつまりはBuffersで返そうと思うと現状は指定することができません。そこでBuffersでもレスポンスボディに指定して返すことが出来るようにという修正がされました。
JWK Auth Middlewareの追加
JWTによる認証のミドルウェアは存在していましたが、JWTの署名のチェックとして、JWK(Json Web Key)という公開鍵方式によるチェックを行えるようにするミドルウェアが追加されました。
JWKにより鍵を独自に発行する場合は管理しやすくなったり、外部サービスの鍵を使用してトークンに入れ込むなどが可能になり、Honoにそのように使えるようになったようです。
ETagMiddlewareにて生成するETagの値をカスタマイズ出来るように修正
ETag Middlewareを使用するとETagがレスポンスに付与されましたが、その付与するETagの値を違う暗号化方式(デフォルトは sha-1 )にしたり、全然別の独自の方式にしたりするようにするためのオプションが追加されました。
以下のように暗号化の方式を変えたい場合などにこのオプションを使用するとよいです。
app.use(
'/etag/*',
etag({
generateDigest: (body) =>
crypto.subtle.digest(
{
name: 'SHA-256',
},
body
),
})
)
このように sha-256 で生成するように変更することが可能になりました。
正規表現によるパス階層を指定した後続に静的パスを指定できるように修正
正規表現によるパス階層を指定してから、その後続に静的パスを指定するようにルーティングを指定した場合にルーティングがマッチせず、404となってしまうという動作があったようです。
import { Hono } from 'hono';
const app = new Hono({ strict: false });
app.get('/:first{.+}/test1/:second', (c) => c.text('hit'))
const res = await app.request('/part/test/latest');
console.log(await res.text()); // 404
しかし、この変更により正規表現によるパス指定の後ろに静的パスを指定してもルーティングがマッチするように変更されました。
c.json にカラの連想配列({})を渡すと型エラーが出る型不具合修正
タイトル通りなのですが、 c.json にキーが無い連想配列つまりは {} を渡そうとすると型エラーとなってしまっていたようです。この修正でこの場合に型エラーが出ないように修正されました。
上記の変更で 4.7.0 がリリースされています
使用していない import 宣言を削除
Streaming Helper内のコードに使用していないimport宣言があったので該当のimport宣言が削除されました。
4.7.0以降の修正
ハンドラーでエラーがthrowされるとミドルウェアが再評価されてしまう不具合を修正
Combine Middlewareの some を使用して、最初のミドルウェアで true を返すと後続のミドルウェアは評価されましたが、その後のハンドラーで例外をthrowすると実行されなかった後続のミドルウェアが実行されるという不具合が修正されました。
const middleware: MiddlewareHandler = async (c, _next) => {
await some(
async (_, next) => {
console.log('middleware 1');
await next();
},
async (_, next) => {
console.log('middleware 2', 'should not be called'); // Called after "error thrown"
await next();
}
)(c, async () => {
console.log('error thrown');
throw new Error('some error');
});
};
4.7.0以降の修正 その2
Zod OpenAPIで出力したOpenAPI Swagger ドキュメントでがトレイリングスラッシュになってしまうことのある不具合を修正
Zod OpenAPIを使用してOpenAPI Swagger ドキュメントを出力した際に定義したパスがトレイリングスラッシュなしだとしてもトレイリングスラッシュで出力されてしまうという不具合が修正されました。再現するコードはIssueから拝借しています。
import { OpenAPIHono } from '@hono/zod-openapi'
const app = new OpenAPIHono<HonoContext>();
const v1 = new OpenAPIHono<HonoContext>().basePath("/v1");
v1.openapi(
createRoute({
method: "get",
path: "/",
responses: {
200: {
description: "Get message",
},
},
}),
(c) => c.json({ message: "Hello" }),
);
app.route("/", v1); // output path is '/v1/'
app.doc("/doc", {
openapi: "3.0.0",
info: {
version: "1.0.0",
title: "My API",
},
});
4.7.0以降の修正 その3
URLパスを生成するロジックを変更して、コードサイズの縮小化および高速化を実施
先日行われたトレイリングスラッシュの対応の際に2つのパスを結合してパスを生成するロジックに変更が行われましたが、そのパスを結合して生成する関数全体をリファクタリングして、最終的なHonoのコードサイズが小さくなりつつ、高速化されるようにリファクタリングが実施されました。
4.7.0以降の修正 その4
LLRTランタイム対応のために不要なimportを削除
AWS LambdaにはJavaScriptランタイムとしてNode.jsの他にLLRTというランタイムが存在します。そのLLRTでHonoを動作させるためにAWS Lambda adapterで構築すると node:crypto の参照があり、LLRTはNode.jsではないので動作しないという問題がありました。
その問題に対応するために node:crypto の参照を削除されました。元々AWS LambdaのNode.jsの最小サポートバージョンである18では、 node:crypto をimportすることなく globalThis に存在することから crypto を使用できるので、削除しても問題ないという判断だそうです。
ETag Middlewareで crypto APIが使用できるかどうか判定するように修正
上記のLLRTに若干影響がありますが、ETag Middlewareではダイジェストを生成するオプションを渡さなければデフォルトで crypto による値を生成します。仮に crypto のAPIが存在しないランタイムなどで実行されると crypto APIがある前提でコードが書かれているので、エラーとなってしまうため、 ダイジェスト生成オプションが無く、 crypto が存在する場合にはデフォルトの crypto による値の生成を行うという変更がされました。
また、同時にダイジェスト生成オプションが指定されておらず、 デフォルトの生成が出来ない状況( crypto APIが使用できないランタイム等)の場合はダイジェストを生成しないという変更も同時行われたようです。
上記の変更で 4.7.1 がリリースされています
4.7.1以降の修正
Proxy Helperで追加されたResponseヘッダーの値がundefinedの場合もヘッダーとして設定される不具合を修正
4.7で追加されたProxy Helperでレスポンスを返す際にヘッダーを指定できますが、その値が undefined であってもヘッダーが設定されるという不具合が修正されました。
修正としては値をチェックし、 null もしくは undefined の場合はResponseヘッダーには設定しないようにという修正がされているようです。
4.7.1以降の修正 その2
Proxy Helperにてシグナルプロパティに対応するように修正
Requestオブジェクトにはシグナルプロパティというものが設定出来ます。これは簡単にいうとリクエスト途中で切るためのものだと思ってくれて結構ですが、Proxy Helperも結局は裏で別のオリジンに向けてリクエストするので、それをキャンセルするためにもこのシグナルプロパティに対応しておいた方がいいということでしょうか。
このPRで面白いのはCloudflare Workerもこのシグナルプロパティの対応を現在行っているという情報が一緒に添付されており、これは私も正直対応してほしいなと思っていたので嬉しい情報でした。
4.7.1以降の修正 その3
Proxy HelperのStatusが正常に設定されるように修正
Proxy Helperでオリジンなどから返ってきたレスポンスを加工してクライアントに返しますが、返す際のレスポンスに設定する元のオリジナルのレスポンスからステータスコードなどを設定する方法にスプレッド演算子を使っているので正常にステータスコードが正常に設定されないということがあったようです。ですので、スプレッド演算子を使用しないように修正されました。
SSG Helperのレスポンスに設定するオリジナルのレスポンス指定にスプレッド演算子を使用しないように修正
SSG HelperでもProxy Helper同様にオリジナルのレスポンスからクライアントに返すためのレスポンスを生成する処理でスプレッド演算子を使用しないようにする修正がされました。
元々ただスプレッド演算子で展開してただけなので、そもそも展開する処理自体が無駄なのでいいリファクタリングの修正と思われます。
Honoの内部APIの型などを現在の実装に合わせたリファクタリングを実施し、Honoのバンドルサイズが小さくなるように修正
結果論かもしれませんが、Hono内部で使用するAPI(詳しくは見ていませんが、Middlewareを処理する内部APIのようです)の型などを現在のHonoが定義するContext型を使用する型変更などが行われました。これにより不要な型定義などが削除や処理が見直されることによりバンドルサイズ少し小さくなったようです。
上記の変更で 4.7.2 がリリースされています
4.7.2以降の修正
Deno 2.2でTypeScript 5.7を使用する型エラーが発生してしまう問題の修正
Deno2.2ではTypeScript5.7に対応するためにArrayBufferに関する修正がされたようです。そのためHonoをDeno2.2かつTypeScript5.7を使用すると型エラーが発生してしまうようです。その問題を解決するためにWeb Socketの送信処理やJWTのエンコード処理などに修正を行い型エラーが発生しないように修正されました。
pattern router内で使用されている不要な変数宣言を削除するリファクタリング
変数宣言をそもそも行わずとも、コードが動作するようにリファクタリングが行われました。これに数バイトですが、バンドルサイズが小さくなると思われます。
4.7.2以降の修正 その2
Bunでwebsocketハンドラーをエクスポートすると型エラーが発生する不具合修正
Bunで createBunWebSocket から返ってきた websocket をエクスポートすると型エラーが発生するという型の不具合があったようです。その型エラーが発生しないように型の修正が行われました。
4.7.2以降の修正 その3
Hono インスタンス時に渡すオプションが副作用を起こさないように修正
ちょっとタイトルだけ読んでもわからないと思うので以下にPRにあるサンプルコードで解説します。
const opts = { strict: false }
const a1 = new Hono(opts) // <- opt is `{ strict: false }`
const a2 = new Hono(opts) // <- opt is not `{ strict: false }`
a2.get('/hello', (c) => c.text('hello'))
const res = await a2.request('/hello/')
expect(res.status).toBe(200)
expect(await res.text()).toBe('hello')
これは Hono をインスタンスした際に opts というオプションを渡していますが、1つ目の a1 をインスタンス化した時点で opts に副作用が起こってしまうコードになっており、2つ目の a2 は strict のオプションが付与されないという不具合があったようです。そこでこのPRは副作用が起きないように修正されました。
URLパラメータにオプションパスの存在チェックを修正し、パフォーマンスを改善
Honoでは設定するパスに /api/animals/:type? と type をオプションとして設定して、 /api/animals と /api/animals/:type の2つのパス設定を1つで行うということが出来ます。この設定で、Hono内部ではオプションとしてパスの一部が存在するかどうかのチェックが行われているわkですが、そのチェックに正規表現を使用しないで行うことで、パフォーマンスが改善するという修正がされました。
上記の変更で 4.7.3 がリリースされています
Bun(JSR)にも以前のDeno 2.2およびTypeScript 5.7での型エラーを対応
以前にDeno 2.2およびTypeScript 5.7で型エラーが発生する対応で型が修正されましたが、Bun側にその修正が入っていなかったので追加で修正されました。
上記の変更で 4.7.4 がリリースされています
4.7.4以降の修正
マイグレーションドキュメントにおけるTypoの修正
マイグレーションのドキュメントにて deno.land/x からJSRにマイグレーションする内容がありますが、その部分におけるTypoが修正されました。
4.7.4以降の修正 その2
BunのWebSocketハンドラーで使用する型をimportで使用できるように修正
BunでWebSocketハンドラーである createBunWebSocket を使用した際に返り値の型がHonoからパブリックになっておらず、 createBunWebSocket の返り値を使用する場合に使用しにくいということがあったようです。そこで createBunWebSocket の返り値の型などをパブリックとして定義して、使用できるように修正されました。
以前のResponseヘッダーの値が undefined が値として設定される不具合修正における追加の型修正を実施
以前にProxy MiddlewareでResponseヘッダーに値が undefined でも値が設定されてしまう不具合が修正されましたが、その修正に伴うJSdocと型の修正を追加で行われました。型修正としていっても動作的なものは何も変更はありません。
4.7.4以降の修正 その3
AWS Lambdaで multiValueHeaders と headers の両方に値が設定されてしまい、正常にレスポンスヘッダーが返らない不具合修正
AWS Lambda環境のレスポンスには headers もしくは multiValueHeaders で返すレスポンスのヘッダーを設定しますが、headers と multiValueHeaders の両方に設定しまうと両方に存在するキーと値のペアしか返らない仕様があるようです。
Honoでは特定パターン時に両方に設定してしまう不具合があり、headers もしくは multiValueHeaders にしか設定しないように修正して、正常にレスポンスが返るように修正されました。
上記の変更で 4.7.5 がリリースされています
4.7.5以降の修正
Compress Middlewareにて Transfer-Encoding が設定されている場合は圧縮しないように修正
httpヘッダーには Transfer-Encoding というものが設定があります。この Tranfer-Encoding はプロキシを経由してサーバにアクセスするような場合にサーバ側で圧縮しているにも関わらずプロキシで再圧縮しないで済むように参照するようなものだと思ってよいとおもいます。
今回の修正はこの Transfer-Encoding が設定されているにも関わらずComparess Middlewareを通してしまうとレスポンスが圧縮されてしまい、正常に処理出来ないという不具合が修正されました。
4.7.5以降の修正 その2
ESLintで表示されるワーニングの解消
ESLintを実行すると使用していないライブラリのインポートなどのエラーが表示されるため、それを解消するための修正が行われました。ちなみにテスト系のファイルのみの修正なのでHono自体に修正があったわけではありません。
(エイプリルフールネタ)「Honoは熱い」というメッセージに変更
Honoのドキュメントにいくつかサンプル文字列として「Hono is cool」という文字がありますが、Honoは熱いフレームワークというエイプリルフール用のネタPRでしたが、ユーモアがあるということでマージされました。
4.7.5以降の修正 その3
Array.prototype.at をサポートしていないブラウザで hono/client が動作するように修正
現在メジャーなブラウザでは Array.prototype.at がサポートされていますが、サポートされていないブラウザでも動作するように hono/client で使用している箇所を削除し添字での要素取り出しに変更されました。
上記の変更で 4.7.6 がリリースされています
4.7.6以降の修正
Trailing Slash MiddlewareでHEADリクエストでも動作するように修正
Trailing Slash MiddlewareではURL末尾のスラッシュを有か無に統一するためにGETリクエストをリダイレクトする処理があります。この変更ではGETリクエストだけでなく、HEADリクエストが対象外となっており、場合によっては404となるため、HEADリクエストもリダイレクトするように修正されました。
4.7.6以降の修正 その2
Proxy Helperで行うfetch処理にRequestオブジェクトが正しく設定できない不具合修正
Proxy Helperには proxy というAPIがあり、この proxy の実態は fetch をラップした処理ですが、fetch 同様にRequestオブジェクトを初期設定として渡せますが、渡したRequestオブジェクトが fetch の初期設定に渡せていないという不具合が修正されました。
Deno 2.2.9 でリクエストを中止するシナリオのテストを安定して行えるように修正
Steamを中止するテストがあるのですが、中止するのが10ms後に停止するシナリオを書いていますが、10msが短すぎて、Streamが開始する前に中止処理が呼ばれてテストが正常に行われないということが発生したようです。そこで、Streamを中止する処理はStreamを開始してから行うというように修正されたようです。
Codecovの新機能であるバンドルサイズを計測するCIの処理を追加
CodecovにはBundle Analysisという機能が存在して、バンドルサイズの経過計測を行ってくれる機能があるようです。そこでHonoもCodecovを使用しているので、この機能を使ってみるということでCIに組み込まれたようです。ただし、このCIを動作させても正常にバンドルサイズが測れないことが判明し、後にリバートされています。
fetchしたResponseをそのまま返した場合にミドルウェアでheaderを書き換えてもエラーが発生しないように修正
PRの再現コードをそのまま書いて説明します。
import { Hono } from 'hono'
const app = new Hono()
app.use(async (c, next) => {
await next()
c.header('foo', 'bar')
})
app.get('*', () => {
return fetch('http://example.com')
})
export default app
上記のコードのようにハンドラー内で fetch したResponseをそのまま返したとします。ミドルウェアでは返すResponseに変更を加えることが出来ますが、この場合のResponseはイミュータブルなため、ヘッダーを書き換えようとするとエラーが発生します。今までの回避策としては fetch で取得したResponseオブジェクトをクローンしてから返すという処理が必要でしたが、この修正ではHonoがResponseオブジェクトをクローンしてくれるのでわざわざ開発者がResponseオブジェクトをクローンしなくてもミドルウェアでは自由にResponseオブジェクトを変更できるようになりました。
上記の変更で 4.7.7 がリリースされています
4.7.7以降の修正
テストで使用する wrangler のバージョンを4系にアップデート
これまでHonoのテストでCloudflare環境下でのテストを wrangler の3系で行っていましたが、この変更により4系に変更されました。
4.7.7以降の修正 その2
ルーティングのハンドラーで upgradeWebSocket を返せるように修正
HonoでWeb Socketを使用するにはWebSocket Helperを使用して定義するのが容易ですが、WebSocket HelperのAPIである upgradeWebSocket はあくまでミドルウェアのように定義して使用する前提でした。しかし、この変更により通常のルーティングハンドラー内でレスポンスを返すようにupgradeWebSocketを返すことが出来るようになりました。
app.get('/', (c) => {
return upgradeWebSocket(c, {
onOpen: (_e, ws) => {
ws.send('Hello World!')
}
})
})
こうすることで、そもそもWeb Socketとして接続を許可しない場合は upgradeWebSocket を返す前に403を返したりすることが出来るほかに、upgradeWebSocket 内で Context の型が正常に取得出来ない問題があったそうですが、upgradeWebSocket 外で取得した値をカリー化した関数として upgradeWebSocket で返すようなことも可能になり、upgradeWebSocket を返すことが出来るのは大きなメリットして変更されました。
4.7.7以降の修正 その3
mount 時の replaceRequest オプションにRequestをそのままマウントされたアプリケーションに渡す指定が追加
Honoには他のアプリケーションで定義したルーティングをそのままマウントさせるという mount というAPIがあります。その mount の際にマウントしたアプリケーションに渡すリクエストオブジェクトはHono側で加工されたりします。ユーザからのリクエストオブジェクトをそのまま渡す際には replaceRequest というオプションを使って、もらったリクエストオブジェクトをそのまま返す処理を書く必要がありますが、 false を指定することでそのままリクエストオブジェクトがマウントされたアプリケーションに渡るようになりました。
import { Router as IttyRouter } from 'itty-router'
import { Hono } from 'hono'
// Create itty-router application
const ittyRouter = IttyRouter()
// Handle `GET /itty-router/hello`
ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
// Hono application
const app = new Hono()
// Mount!
app.mount('/itty-router', ittyRouter.handle, { replaceRequest: false })
// 今までは以下のようにRequestをそのまま返す関数を定義する必要があった
// app.mount('/itty-router', ittyRouter.handle, { replaceRequest: (request) => request })
上記の変更で 4.7.8 がリリースされています
4.7.8以降の修正
Cookie Helperの getSignedCookie の型が誤っているのを修正
Cookie Helperにある getSignedCookie の引数はいくつかのパターンがあるのですが、そのすべてのパターンで第2引数は文字列か BufferSource の型を受け入れるはずですが、1つのパターンだけ文字列しか受けれない型指定になっていました。この修正で、すべての第2引数は文字列か BufferSource の型で受け入れれるようになりました。
4.7.8以降の修正 その2
toSSG に渡すオプションの extensionMap が動作しない不具合の修正
HonoにはSSGをするためのSSG Helperがありますが、 そのヘルパーのAPIである toSSG にはいくつかのオプションを渡すことができ、 extensionMap という Context-Type から出力するファイルの拡張子を決めるオプションがあります。その extensionMap オプションが動作しないという不具合が修正されました。
deleteCookie のオプションで prefix を指定した場合に削除されるCookieが返って来ない不具合修正
Cookie Helperで deleteCookie というAPIがあり、これは削除するCookeのデータが返り値として取得出来ますが、Cookieを取得する際の getCookie と同様にprefixを指定することが出来ますが、prefixを指定した場合は返り値が取得出来ないという不具合が修正されました。
上記の変更で 4.7.9 がリリースされています
4.7.9以降の修正
basePath より前に onError を定義すると onError のハンドラーが正常に処理されない不具合修正
Honoには onError というエラーをハンドリングするための関数が存在しますが、その onError の後ろに basePath を呼び出すと onError のハンドラーが呼び出されないという不具合が修正されました。
const app = new Hono()
.onError((error, c) => {
console.log('Error caught in handler:', error)
return c.json(
{ success: false, message: '>>>> Something went wrong!' },
500,
)
})
.basePath('/api')
.get('/test', async () => {
throw new Error('API Test error')
})
.get('/hello', async (c) => {
return c.text('hello')
})
修正の内容を見ると onError の例外エラーだけでなく、 404の処理も正常に呼び出せないようだったので修正されております。
4.7.9以降の修正 その2
JWKSの検証にて、フォールバックとしてtokenヘッダーの署名アルゴリズムを使用するように修正
JWKのヘルパーを使用してJWKSの認証をかけて実装した場合に署名のアルゴリズムはtokenヘッダーから指定されたキーの kid が一致するものから取得していましたが、署名アルゴリズムの決め方はこれだけでなく、tokenヘッダーの alg も使用できることから、 kid が一致する署名アルゴリズムが無い場合はtokenヘッダーの alg を署名アルゴリズムとして使用するように修正されました。
上記の変更で 4.7.10 がリリースされています
4.7.10以降の修正
クエリパラメータの解析に URLSearchParams を使用した場合のベンチマークを追加
Honoは昔にクエリパラメータの解析に URLSearchParams を使用しようとした経緯があるようですが、どうやらそれは行われなかったようです。どうやら URLSearchParams を使用するとクエリパラメータの解析が今より遅くなるようです(といってもナノ秒の世界)。しかし、 URLSearchParams を使用する場合はプログラムコードも削れて数バイト浮くので、「小さく」はなるようです。
今回は一旦ベンチマークだけの追加のようです。
4.7.10以降の修正 その2
型のベンチマークに skipLibCheckをtrue` にして計測するように修正
skipLibCheck はライブラリなどの *.d.ts までチェックを行わないようにするオプションですが、実際の開発では skipLibCheck が true に設定されることが多いため、Honoでも実際の開発に近い形で計測するようになりました。
また、この変更は typescript-go での型ベンチマーク追加の過程で発生した問題の解消であり、Honoの型ベンチマークに typescript-go のでベンチマークが追加される予定だそうです。
4.7.10以降の修正 その3
TypeScript-Goによる型パフォーマンスのベンチマーク追加
HonoはPRを出すと動作するCIで型のパフォーマンスを計測します。その際に型のパフォーマンス計測にTypeScript-Goによるパフォーマンスも測るように修正されました。
4.7.10以降の修正 その4
Claude Codeを使用する際の設定ファイルをコミットの対象外とするように修正
Claude Codeを使用する際に前提の知識として CLAUDE.md などにそのリポジトリの全体的な説明などをドキュメントとして作成しておき、Claude Codeがそれらドキュメントを元にコードを読んだり作成したりします。そのClaude Codeをローカルで使用する際に CLAUDE.local.md を .gitignore に追加してコミットの対象外として修正されました。これによりHonoのリポジトリでClaude Codeを使用する際に自身のローカルルールなどは CLAUDE.local.md に記載しておくと使えるようになるはずです。
リクエストヘッダーの If-None-Match の条件一致の場合に304が返るように修正
リクエストヘッダーには If-None-Match というヘッダーを渡すことが出来て、サーバー側は受け取った値をEtagとの比較で一致すれば304を返すというRFCがあります。それがHonoでは動作しないということで修正されました。
どうやら修正を見るとEtagの値の比較アルゴリズムに問題があり(弱い比較アルゴリズムを使わないといけない)それが正しいアルゴリズムに修正されたようです。
4.7.10以降の修正 その5
READMEにDeepWikiのバッジを追加
DeepWikiとはGitHubを参照してライブラリの使用方法や中身の構造などを解説してくれます。そのDeepWikiの内容を自動的に更新するにはDeepWikiへのバッジをREADMEに追加する必要があり、HonoのコードをDeepWikiへ自動更新するために追加しました。
4.7.10以降の修正 その6
HTTPException をthrowした際のtry catchのfinalyブロックが実行されない不具合修正
HTTPExeptionをthrowするとそこで指定したhttpレスポンスを返すことになりますが、そのthrowをtry catch構文で実行しつつ、finalyブロックで更にレスポンスを修正するような処理を書いてもfinalyブロックの内容は処理されないという不具合が修正されました。
import { deleteCookie } from 'hono/cookie'
import { HTTPException } from 'hono/http-exception'
app.use(async (c) => {
try {
await maybeError()
} catch (cause) {
throw new HTTPException(302, {
cause,
res: c.redirect('/?error=invalid_request', 302),
})
} finally {
deleteCookie(c, 'foo') // <-- 処理が反映されない
}
})
上記の変更で 4.7.11 がリリースされています
Etag middlewareがAWS Lambdaの環境で動作するように修正
どうやらAWS Lambdaの環境下ではResponseオブジェクトにある .clone() が正常に動作しないため、ETag middleware内で行っているDigestの生成処理がうまく動作しないようです。そこで .clone().body() が正常に動作しない場合は .arrayBuffer() で取得した値からDigestを生成するように修正されました。
4.7.11以降の修正
Etag middlewareがAWS Lambdaの環境で動作するように修正をリバート
先日修正して対応ですが、修正した内容では不具合が解消されなかったためリバートされました。
4.7.11以降の修正 その2
devcontainerの docker-compose.yml から version の記述を削除
Honoの開発環境を設定する方法はいくつかあるのですが、devcontainerで立ち上げることもできます。その中ので docker-compose.yml が定義されていますが、 version の記述が残っており削除されました。そもそも version はだいぶ前にdocker compose v2からversionが不要になっています。
そうなると docker-compose.yml というファイル名も古い気はしますが…。