0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HonoのマージされたPRを読んでいく#31 - #35

0
Last updated at Posted at 2025-12-06

この記事何?

エンジニア歴1年半。業務で利用しているHonoが大好きだが、TSもプログラミング知識も弱々すぎて上手く使いこなせない。速いはずが多分生かせてない。
ちゃんと理解するためにソースコードリーディングしたい。

でも目的なくソースコード眺めても意味ないし……ねむい……
そうだ!PRを全部読めば、変遷やなぜ変更されているかストーリー的に分かるのでは。
と思ったのでチャレンジしてみる。PR2000以上あるので、全部できるかは知らん。
https://github.com/honojs/hono

#31 Feature/html method

Contextにc.html()メソッドを追加
これにより、HTMLレスポンスを簡潔に返せる

src/context.ts

  export class Context {
    // 既存: c.text(), c.json()

    // 新規追加
    html(body: string): Response {
      // 型チェック
      if (typeof body !== 'string') {
        throw new TypeError('html method arg must be a string!')
      }

      // HTMLレスポンスを返す
      return this.newResponse(body, {
        status: 200,
        headers: {
          'Content-Type': 'text/html; charset=UTF-8',
        },
      })
    }
  }
// 変更前
  app.get('/', () => {
    const html = renderSSR(<App />)

    // 手動でResponseを作成
    return new Response(html, {
      headers: {
        'Content-Type': 'text/html',
      },
    })
  })

// 変更後
app.get('/', (c) => {
    const body = renderSSR(<App />)
    
    // c.html() で簡潔に
    return c.html(body)
})

フレームワーク作ったことないけど、こういう「あったら嬉しい」「こう書けたら嬉しい」「アレにあるようなメソッドが欲しい」をつけていく作業なのかもしれない。

#32 Refactor

  1. package-lock.jsonの削除(Yarnを使用しているため)
  2. READMEの改善
  3. JSX-SSRサンプルの改善
  4. Lintの修正

#33 Add worktop benchmark

ベンチマークに worktop を追加。
worktopって何かなと思ったけど、Cloudflare Workers向けの別のフレームワークぽい。

フレームワーク 速度(ops/sec) 順位
hono 748,188 1位
sunder 332,339 2位
worktop 205,906 3位(新規)
itty-router 158,817 4位

おお、READMEの
Hono[炎] - _**means flame🔥 in Japanese**_ - is small, fast and simple...の説明がfast -> ultrafastへ変更になってる。めちゃいい。ワクワク。

#34 status and headers args on context text/json/html method

Context のレスポンスメソッドにオプションでステータスコードとカスタムヘッダーを指定できるように修正

 // 変更前:
 export class Context {
   text(body: string): Response {
     return this.newResponse(body, {
       status: 200,  // 固定
       headers: {
         'Content-Type': 'text/plain',
       },
     })
   }

   json(object: object, replacer?: (string | number)[], space?: string | number): Response {
     const body = JSON.stringify(object, replacer, space)  // JSON.stringifyの引数
     return this.newResponse(body, {
       status: 200,  // 固定
       headers: {
         'Content-Type': 'application/json; charset=UTF-8',
       },
     })
   }
   ...

   app.get('/', (c) => c.json({ ok: true }))  // 常に200

// 変更後:
 export class Context {
   text(text: string, status: number = 200, headers: { [key: string]: string } = {}): Response {
     headers['Content-Type'] = 'text/plain'
     return this.newResponse(text, {
       status: status,
       headers: headers,
     })
   }

   json(object: object, status: number = 200, headers: { [key: string]: string } = {}): Response {
     const body = JSON.stringify(object)  // シンプルに
     headers['Content-Type'] = 'application/json; charset=UTF-8'
     return this.newResponse(body, {
       status: status,
       headers: headers,
     })
   }
   ...

 app.post('/api/posts', (c) => c.json({ message: 'Created!' }, 201))  // ステータス指定可能
 app.get('/api/data', (c) => c.json({ data: 'value' }, 200, { 'X-Custom': 'Header' }))  // ヘッダー追加可能

  • デフォルト引数で後方互換性を維持

#35 Refactor

  • params の戻り値の型を any から string に変更
  • 型をエクスポート
  • JSX-SSRサンプルの改善
    など

Contextが何者かいつもイメージしづらかったけど、PR順番に追っていくと優しさの塊だった。ありがてぇ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?