Hono + ViteでLambda Web FunctionsにAPIをデプロイする

Hono + ViteでLambda Web FunctionsにAPIをデプロイする

Lambda Web Functionsへのデプロイをシンプルにするため、ViteとHonoを使ってビルド・バンドルする方法を試してみました。セットアップから本番環境でのデプロイまでの全プロセスを紹介します。
2026.10.14

こんばんは、情報システム室の夏目です。

Lambda Web Functionsへのデプロイする際、単純に tsc するだけでは node_modules が必要になります。
しかし、開発する上で使用するLinterやFormatter、ビルドに使うtypescriptパッケージなど、プロダクション環境では使用しないパッケージも含まれます。

ビルドしてからnode_modulesを削除して、再度必要なものだけインストールするという手段も使えなくはないのですが、少し面倒です。

なので今回はViteでビルドとバンドルをさせてみようと思います。
またAPIバックエンドのフレームワークとしてHonoを使用します。

1. npm init -y と必要なライブラリをインストールする

まず最初に npm init -y をします。

$ npm init -y --init-type module

Wrote to package.json:

{
  "name": "write-blog-vite-hono",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "type": "module"
}

--init-type module とすることでpackage.jsonにおいて type: module とすることができます。
(デフォルトでは mommonjs になる)

次にhonoなど、必要なライブラリをインストールします。

$ npm install hono @hono/node-server
$ npm install -D @hono/vite-build @hono/vite-dev-server @types/node vite

2. tsconfig.jsonとvite.config.tsを作成する

tsconfig.json
{
  "compilerOptions": {
    "target": "es2024",
    "lib": ["es2024"],
    "types": ["node"],
    "module": "preserve",
    "moduleResolution": "bundler",
    "strict": true,
    "noEmit": true,
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "skipLibCheck": true
  },
  "include": ["./src"]
}

今回はViteでビルドを行うので noEmit: true にしています。

vite.config.ts
import build from "@hono/vite-build";
import devServer from "@hono/vite-dev-server";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    devServer(),
    build({
      entryContentAfterHooks: [],
    }),
  ],
});

ローカル実行できるように devServer() (@hono/vite-dev-server)を、ビルドを行うために build() (@hono/vite-build) をpluginsに追加します。

@hono/vite-buildでは entryContentAfterHooks: [] を設定して、ビルド時に自動で serve() (NodeでHonoのAPIサーバーを動かすための関数) を追記しないようにしています。

3. src/index.ts を実装する

index.tsでHonoのAPIサーバーを書きます。

src/index.ts
 import { serve } from "@hono/node-server";
 import { Hono } from "hono";

 const app = new Hono();

 app.get("/", (c) => {
   console.log("called!!");
   return c.json({ ok: true });
 });

+if (process.env.NODE_ENV !== "development") {
+  const address = process.env.AWS_LAMBDA_HTTP_ENDPOINT ?? "0.0.0.0:3000";
+  const [hostname, port] = address.split(":");
+
+  console.log(`address: http://${address}`);
+  console.log("waiting request ...\n");
+
+  serve({
+    fetch: app.fetch,
+    port: Number(port),
+    hostname,
+  });
+}

 export default app;

今回はサンプル用のAPIなので / にアクセスしたら、コンソール出力して {"ok": true} と返すだけのAPIです。

末尾に export default app; としたのはViteのdevServerで動かせるようにするためです。

ハイライトした部分で、nodeで実行したとき(node dist/index.js)に動く部分で、Lambda Web Functionsのホストやポートを指定してHonoのサーバーを起動しています。

process.env.NODE_ENV !== "development"

ViteでdevServerとして動かすとき、 環境変数 NODE_ENV は development という値になります。
単純にnodeで実行したときには明示的に設定しない限り NODE_ENV は設定されません。

そのため、devServerか否かの区別に使っています。

process.env.AWS_LAMBDA_HTTP_ENDPOINT ?? "0.0.0.0:3000"

Lambda Web Functionsでは AWS_LAMBDA_HTTP_ENDPOINT という環境変数でHTTPサーバーがリッスンしなければならないホストとポートを渡されます。
host:port 形式で渡されるので、 : で分割して serve() に渡しています。

4. ViteでdevServerを動かして見る

まずdevServerを動かしてみます。

$ npx vite

  VITE v8.3.4  ready in 163 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

called!!
$  curl http://localhost:5173/
{"ok":true}

devServerも問題なく動きました。

このあたりはpackage.jsonのscriptsに書いても良さそうです。

5. Viteでビルドして、ローカルから実行してみる

Viteでビルドします。

$ npx vite build
npx vite build
npm notice run write-blog-vite-hono@1.0.0 npx
npm notice run 'vite' build
vite v8.3.4 building ssr environment for production...
✓ 32 modules transformed.
computing gzip size...
dist/index.js  38.90 kB │ gzip: 14.78 kB

✓ built in 18ms

$ eza -alT -F auto --time-style=long-iso dist/
drwxr-xr-x@   - natsume.yuta 2026-10-14 18:02 dist/
.rw-r--r--@ 39k natsume.yuta 2026-10-14 18:08 └── index.js

問題なくビルドできました。

nodeで dist/index.js を実行してみます。

$ node dist/index.js
address: https://0.0.0.0:3000

called!!
$ curl http://0.0.0.0:3000
{"ok":true}⏎

nodeでの実行もできそうです。

6. Lambda Dev Functionsにデプロイする

ビルドも問題なくできたので、Lambda Dev Functionsにデプロイします。

$ aws lambda-web deploy --create --name hono-building-by-vite --code ./dist
Creating deployment package ...
Preparing Amazon S3 bucket ...
Preparing AWS IAM execution role ...
Uploading deployment package ...
Creating Lambda Web Function ...
Waiting for endpoint to become active (timeout 600s) ...
Waiting for endpoint to become active (state Pending, 0s elapsed, timeout 600s) ...
Waiting for endpoint to become active (state Pending, 5s elapsed, timeout 600s) ...
https://g3u3v18zicwimvmc.bhb.lambda-web.ap-northeast-1.on.aws
Console: https://ap-northeast-1.console.aws.amazon.com/lambda/home#/web-functions/hono-building-by-vite

デプロイできたので、curlで叩いてみます。

$ curl https://g3u3v18zicwimvmc.bhb.lambda-web.ap-northeast-1.on.aws
{"ok":true}

問題なく動きました。

まとめ

以上、ViteでHonoによるAPIサーバーのビルドとバンドルを行ってみる話でした。

何かのお役に立てたら幸いです。

この記事をシェアする

関連記事