今回は、JavaScirptのサーバーサイドフレームワークであるHonoで簡単なAPIを実装し、
AWS Lambdaにデプロイしてみた際のメモです。
手間ですが全て手動で行っています。当然、terraformやCloud Formationで自動化できると思います。
目次
バージョン
Node.js:v24.11.1
Hono:4.0.0
honoインストール
package.json初期化
npm init -y
npm install hono @hono/node-server
対話形式でHonoテンプレートプロジェクトごとインストールしたい場合は、以下などで行います。
npm create hono@latest
簡易アプリ実装
POST、GET等の簡単なサンプル実装です。
以下はローカル実行用です。後述でほぼ同様の内容のLambda実行用ファイルも作成します。
src/index.js
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
// Honoアプリケーションインスタンスの作成
const app = new Hono()
// ミドルウェア設定
app.use('*', logger())
app.use('*', cors())
// ルート
app.get('/', (c) => {
return c.json({
message: 'Honoへようこそ!',
timestamp: new Date().toISOString()
})
})
// パラメータ付きGETリクエスト
app.get('/money/:type_str', (c) => {
const type_str = c.req.param('type_str')
// 通貨記号マップ
const symbols = {
'円': '¥',
'ドル': '$'
}
const symbol = symbols[type_str] || '?'
return c.json({
currency: type_str,
symbol: symbol,
message: `${type_str}の記号は${symbol}です。`
})
})
// POSTリクエストの例
app.post('/money/calc', async (c) => {
const body = await c.req.json()
const { amount, currency } = body
// 為替レート(本来は外部APIから取得)
const exchangeRates = {
'円': 1,
'ドル': 110
}
const rate = exchangeRates[currency] || 1
const convertedAmount = amount * rate
return c.json({
message: '変換が完了しました',
originalAmount: amount,
currency: currency,
convertedAmount: convertedAmount
}, 201)
})
// HTMLレスポンスの例(簡素デザイン/一重エスケープ+テンプレ不使用)
app.get('/html/response_sample', (c) => {
const html =
'<!DOCTYPE html>' +
'<html lang="ja">' +
'<head>' +
'<meta charset="utf-8" />' +
'<title>Hono App</title>' +
'<style>' +
'body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 24px; line-height: 1.6; }' +
'h1 { font-size: 20px; margin-bottom: 12px; color: #111827; }' +
'ul { padding-left: 20px; }' +
'li { margin: 4px 0; }' +
'code { background: #f3f4f6; padding: 2px 4px; border-radius: 3px; }' +
'</style>' +
'</head>' +
'<body>' +
'<h1>Hono サンプルエンドポイント</h1>' +
'<ul>' +
'<li><code>GET /</code> — トップページ(JSON)</li>' +
'<li><code>GET /money/:type_str</code> — 通貨記号(例: 円、ドル)<br><small>例:</small><code>http://localhost:3000/money/円</code></li>' +
'<li><code>POST /money/calc</code> — 通貨変換<br><small>例:</small><code>curl -X POST http://localhost:3000/money/calc -H "Content-Type: application/json" \'-d {"amount": 10, "currency": "ドル"}\'</code></li>' +
'</ul>' +
'</body>' +
'</html>';
return c.html(html);
});
// 404ハンドラー
app.notFound((c) => {
return c.json({
message: 'ページが見つかりません'
}, 404)
})
// エラーハンドラー
app.onError((err, c) => {
console.error(`エラー: ${err}`)
return c.json({
error: 'サーバーエラーが発生しました',
message: err.message
}, 500)
})
// サーバー起動
const port = 3000
console.log(`🚀 サーバーが起動しました: http://localhost:${port}`)
serve({
fetch: app.fetch,
port
})
ローカル挙動確認
npm run dev
http://localhost:3000
http://localhost:3000/money/ドル
curl -X POST http://localhost:3000/money/calc -H "Content-Type: application/json" -d '{"amount": 10, "currency": "ドル"}'
http://localhost:3000/html/response_sample
Lambda デプロイ 資材作成
Lambda実行ファイル作成
既存のindex.jsをベースにLambda実行ファイルを作成します。
ほぼ同じ内容ですが、以下の部分を修正して作成します。
- インポート
削除:import { serve } from ‘@hono/node-server’
追加:import { handle } from ‘hono/aws-lambda’ - サーバー起動
削除:serve({ fetch: app.fetch, port: 3000 })
追加:export const handler = handle(app)
lambda_function.js
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
const app = new Hono()
// ミドルウェア設定
app.use('*', logger())
app.use('*', cors())
// ルート
app.get('/', (c) => {
return c.json({
message: 'Honoへようこそ!',
timestamp: new Date().toISOString()
})
})
// パラメータ付きGETリクエスト
app.get('/money/:type_str', (c) => {
const type_str = c.req.param('type_str')
// 通貨記号マップ
const symbols = {
'円': '¥',
'ドル': '$'
}
const symbol = symbols[type_str] || '?'
return c.json({
currency: type_str,
symbol: symbol,
message: `${type_str}の記号は${symbol}です。`
})
})
// POSTリクエストの例
app.post('/money/calc', async (c) => {
const body = await c.req.json()
const { amount, currency } = body
// 為替レート(本来は外部APIから取得)
const exchangeRates = {
'円': 1,
'ドル': 110
}
const rate = exchangeRates[currency] || 1
const convertedAmount = amount * rate
return c.json({
message: '変換が完了しました',
originalAmount: amount,
currency: currency,
convertedAmount: convertedAmount
}, 201)
})
// クエリパラメータの例
app.get('/money/multiplication', (c) => {
const money_type = c.req.query('money_type')
const count = c.req.query('count')
// 単価マップ
const unitPrices = {
'円': 100,
'ドル': 1
}
// 計算処理
const unitPrice = unitPrices[money_type] || 0
const countNum = parseInt(count, 10) || 0
const result = unitPrice * countNum
return c.json({
money_type: money_type,
count: countNum,
unitPrice: unitPrice,
total: result
})
})
// HTMLレスポンスの例(簡素デザイン/一重エスケープ+テンプレ不使用)
app.get('/html/response_sample', (c) => {
const html =
'<!DOCTYPE html>' +
'<html lang="ja">' +
'<head>' +
'<meta charset="utf-8" />' +
'<title>Hono App</title>' +
'<style>' +
'body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 24px; line-height: 1.6; }' +
'h1 { font-size: 20px; margin-bottom: 12px; color: #111827; }' +
'ul { padding-left: 20px; }' +
'li { margin: 4px 0; }' +
'code { background: #f3f4f6; padding: 2px 4px; border-radius: 3px; }' +
'</style>' +
'</head>' +
'<body>' +
'<h1>Hono サンプルエンドポイント</h1>' +
'<ul>' +
'<li><code>GET /</code> — トップページ(JSON)</li>' +
'<li><code>GET /money/:type_str</code> — 通貨記号(例: 円、ドル)<br><small>例:</small><code>http://localhost:3000/money/円</code></li>' +
'<li><code>POST /money/calc</code> — 通貨変換<br><small>例:</small><code>curl -X POST http://localhost:3000/money/calc -H "Content-Type: application/json" \'-d {"amount": 10, "currency": "ドル"}\'</code></li>' +
'</ul>' +
'</body>' +
'</html>';
return c.html(html);
});
// 404ハンドラー
app.notFound((c) => {
return c.json({
message: 'ページが見つかりません'
}, 404)
})
// エラーハンドラー
app.onError((err, c) => {
console.error(`エラー: ${err}`)
return c.json({
error: 'サーバーエラーが発生しました',
message: err.message
}, 500)
})
// Lambda用のハンドラーをエクスポート
export const handler = handle(app)
デプロイ用Zip作成
コマンド実行
zip -r lambda-deployment.zip src/lambda_function.js node_modules package.json
手動でも作成できますが、
src/lambda_function.js、node_modules配下全て、package.jsonを含める形で作成します。

※本来Lambda実行用には、@hono/node-servernなどは不要です。
本番実行用の資材を作成する場合は、含める依存関係を整理することをオススメします。
AWS Lambda 作成・デプロイ
動作させるLambdaを作成してデプロイします。
AWS Lambda作成
関数名を任意の名称で命名し、ランタイム:Node.jsを指定します。
資材デプロイ
作成したZipファイルをアップロードしてデプロイします。
アップロード元のところよりアップロードできます。

アップロードされると、コードソース部分に内容が展開されます。

Lambda 設定調整
動作させるためのLambda設定を行なっていきます。
タイムアウト設定調整
念の為、タイムアウト時間を調整します。
エンドポイント作成
挙動確認用の関数URLを作成します。
認証タイプ:NONEを指定します。
※外部公開され全てのユーザーが実行できますのでご注意ください。
ここで作成された関数URLが挙動確認用になります。
ランタイム設定
ランタイム設定より作成したlambda_function.jsを実行するための設定を行います。
ハンドラを以下のような形で指定します。
src/lambda_function.handler
AWS Lambda Hono 挙動確認
設定が全て済んだら、関数URLで挙動確認を行います。
エラー等問題が起きた場合、
CloudWatchログでログを確認できますので確認してトラブルシュートします。

今回のメモは以上となります。
Honoは軽量で実装しやすいJavaScriptバックエンドフレームワークです。
特にLambdaとの相性が良いと感じます。
ルーティングも簡単に実装側で制御できますし、ちょっとしたAPIを用意するのに打って付けだと思います。















