筆者が所属するチームで、Honoを使って業務改善ツールを作った事例を紹介します。
業務における課題
筆者が所属するチームでは、1分間隔で更新されるリアルタイム情報を扱っています。
このリアルタイム情報は、AWS S3を使って外部システムと連携しています。
リアルタイム情報を使った開発をする中で、以下のような課題がありました。
デバッグの難しさ
リアルタイムデータは、gzip形式で圧縮された状態でS3に保存されます。またデータ量も多いため、解凍したデータを確認するのが面倒でした。チーム内では、データを確認する際に以下のような手順が取られていました。
- S3からgzipされたJSONをダウンロード
-
gunzip
コマンドで解凍 - vscodeで開き、ファイル内検索
検証手順が複雑なことで、属人化の問題もありました。
また、先述の通り、データは1分間隔で更新されていくため、動作確認が難しいという問題がありました。
例えば「30分に1回だけ出現するデータパターン」などもあり、実データを使った動作検証が難しくなっていました。
過去データを使った検証の難しさ
リアルタイムデータについては、S3に過去ログを残しています。
しかしこの過去ログ、単純に1分に1ファイルずつ保存されていく形式のため、一定期間分のデータを使った動作確認も難しくなっていました。
例えば、「デバッグのためにあるデータのステータスが変化した時刻を知りたい」といった要求があった場合でも、S3から履歴ファイルを1つずつ手動でダウンロードし、手動でgunzip
して…という手順が取られていました。
こうした業務における課題に対処するため、弊チームでは
- S3に格納されたリアルタイムデータを容易に閲覧できる
- 過去ログを時系列で表示できる
というようなツールを作成することになりました。
技術選定
技術選定にあたっては、以下の点を考慮しました。
- チーム内ではNode.jsがメインで使用されているため、ツールの作成においてもNode.jsを使用すること
- 本来の業務と並行してツールを作成するため、工数を短時間で済ませること
- アクセス制限をかけるため認証の機構があること
- チーム内にはフロントエンドを扱うメンバーが少ないため、フロントエンドJavaScriptの知識が無くても動作させられること
- AWS Lambda上で動作できること
以上の要件から、バックエンド側の処理でSSRを完結させることができ、動作原理も比較的シンプルで扱いやすいフレームワークということで、Honoを採用しました。
実装
具体的な実装については割愛しますが、S3のデータをAWS SDKで取得し、hono/jsx
で表示するというシンプルな実装になっています。
import { Hono } from "hono";
const app = new Hono();
app.get("/", async (c) => {
const data = await getDataFromS3(); // S3からデータを取得する処理
return c.html(
<html>
<head>
...
</head>
<body>
{/* S3から取ってきたデータを表示 */}
{data.map(d => (<div>{d}</div>))}
</body>
</html>
);
});
上記の実装に加えて、ミドルウェアなどをいくつか使用しています。
basic認証
まずbasic認証ミドルウェアです。
ツールの利用時に、ここで指定したユーザー名とパスワードを使ってログインすることを必須にできます。
const app = new Hono();
app.use(
basicAuth({
username: "<ユーザー名>",
password: "<パスワード>",
invalidUserMessage: "Unauthorized. Please see https://github.com/... .",
}),
);
app.get("/", async (c) => {
...
invalidUserMessage
で認証に失敗した時のエラーメッセージをカスタマイズできます。
hono/jsx
tsconfig.jsonに以下の設定を追記することで、honoからhtmlを返却する際に、jsxを使用できるようになります。
{
"compilerOptions": {
// hono向け設定
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
}
}
app.get("/", async (c) => {
return c.html(
<html>
...
</html>
);
});
zod validator
honoでは、zodというライブラリと組み合わせることで、クライアントサイドから送られてくるパラメータをバリデーションできます。
zodを使うことで型安全になるだけでなく、クエリパラメータの値が間違っていた時のエラーハンドリングやエラーメッセージ返却も行ってくれます。
import { z } from "zod";
import { zValidator } from "@hono/zod-validator";
app.get(
"/",
// zodによるバリデーション処理
zValidator(
"query",
z.object({
foo: z.string(),
bar: z.string(),
})
),
async (c) => {
// バリデーション後の値を受け取る
const { foo, bar } = c.req.valid("query");
...
},
);
Lambda Server
HonoをAWS Lambda上で動作させるためにHonoのLambda用のヘルパを使っています。
環境変数で条件分岐することで、
- ローカル実行時はNode.js Serverを使用してlocalhostを立ち上げ
- Lambda上ではLambda Serverを使用し、
handler
をexportすることでサーバー立ち上げ
という仕組みにしています。
import { handle } from "hono/aws-lambda";
import { serve } from "@hono/node-server";
// lambda用のhandlerをexport
export const handler = handle(app);
// ローカル実行
if (!process.env.LAMBDA_TASK_ROOT) {
console.log("Server running at http://localhost:8080/");
serve({ ...app, port: 8080 });
}
以上のような仕組みを用いて、S3のデータを手軽に閲覧できる社内向けツールを作成することができました。
ツールを作成した結果
このツールを作成したことで、以下のような改善ができました。
- レビューやデバッグにかかる時間が減少した
- データの中身が可視化されたことで、不正なデータや異常なデータが来ていないかを一目で確認することができるようになった
- 他チームで障害が発生しデータの更新が止まっていても気づけるようになった
デバッグにかかる時間が減少したことで、本来の開発業務にかける時間をより増やすことができました。
まとめ
HonoとAWS Lambdaを使って業務改善ツールを作成しました。
Honoを使用したことで、短期間でツールを開発することができました。Honoはmiddleware、contextといったAPIのデザインに一貫性があり、学習コストが低く、導入しやすかったです。
またzod validatorなどを使用し、型安全を保ったコードを記述することができた点もよかったです(expressだとcontextがany型になりがち)。
こうしたツールをサクッと作りたい時はHonoが最適だと感じました!