AWSAWS CDKHono / SonikJavaScript

AWS Lambda(with AWS CDK)とHonoでサーバーレスなWebページを作ってみた

HonoがAWS Lambdaで動くことがわかったので、HTMLを配信するための設定を試しました。CDKとLambdaを使用してHonoアプリをセットアップし、HTMLを返すRouteを追加しました。サーバー側でHTMLを組み立てて表示させるため、metaタグなども作成可能です。AWS CDKでデプロイして、/testなどのパスにアクセスするとHTMLが表示されます。また、APIを呼び出して結果を表示する動的な処理を追加することもできます。HonoはUIとAPIをまとめて作成できる軽量なツールです。ただし、実務で使用する場合はTwigやJSXなどでHTMLを構築する仕組みを用意する必要があります。参考記事もあります。

広告ここから
広告ここまで

HonoがAWS Lambga (with functions URL)で動くことがわかったので、今度はHTMLを配信できないか試してみました。

Honoアプリのセットアップ

Honoのドキュメントにあるガイドに従ってアプリをセットアップしましょう

% mkdir my-app
% cd my-app
% cdk init app -l typescript
% npm i hono
% mkdir lambda

ここまではAPIを作る時と全く同じです。

CDKのスタック定義も、APIと同様LambdaとLambdaのfunctions URLだけにしました。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Architecture, FunctionUrlAuthType } from "aws-cdk-lib/aws-lambda";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";

export class HonoOnAwsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const lambda = new NodejsFunction(
      this,
      'hono-app',
      {
        entry: './lambda/main.ts',
        handler: 'handler',
        architecture: Architecture.ARM_64
      }
    )
    const url = lambda.addFunctionUrl({
      authType: FunctionUrlAuthType.NONE,
    })
  }
}

HTMLを返すRouteをHonoに追加する

HTMLを返すRouteは、app.gethono/htmlを利用します。

import { Hono } from "hono";
import { handle } from "hono/aws-lambda"
import { html } from 'hono/html'

const app = new Hono()
app.get('/*', c => {
    return c.html(
      html`<!DOCTYPE html>
        <h1>Hello!</h1>
        <p>The current router is ${app.routerName}</p>
        `
    )
})

export const handler = handle(app)

サーバー側でHTMLを組み立てるので、metaタグなどもここで作れます。


app.get('/*', c => {
    return c.html(
      html`<!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>サイトタイトル</title>
          <meta name="description" content="ページ: ${c.req.path}のデモです">
        </head>
        <body>
          <h1>ページ: ${c.req.path}のデモです</h1>
        </body>
        </html>
        `
    )
})

AWS CDKでデプロイ

あとはcdk deploy --hotswapなどでデプロイするだけです。

/testなどのパスにアクセスすると、HTMLが表示されます。

クライアント側で、APIを呼び出す

サーバー側でHTMLを作って表示させているため、scriptタグを含めれば動的な処理を追加できます。

例えば、/apiにGETリクエストを送り、その結果を表示する処理を追加しましょう。

import { Hono } from "hono";
import { handle } from "hono/aws-lambda"
import { html } from 'hono/html'

const app = new Hono()

app.get('/*', c => {
    return c.html(
      html`<!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>サイトタイトル</title>
          <meta name="description" content="ページ: ${c.req.path}のデモです">
        </head>
        <body>
          <h1>ページ: ${c.req.path}のデモです</h1>
          <div id="content"></div>
          <script>
            fetch('/api')
                .then(data => data.json())
                .then(response => {
                    const target = document.getElementById("content")
                    const elm = document.createElement('pre')
                    elm.textContent = JSON.stringify(response)
                    target.appendChild(elm)
                })
          </script>
        </body>
        </html>
        `
    )
})

export const handler = handle(app)

そしてHonoでGET /apiも追加します。

app.get('/api', c => {
    console.log(c)
    return c.json({
        path: "hello hono",
    })
})

デプロイすると、APIのレスポンスもページに表示されます。

試してみて

簡単なワークショップなどでは、UIもAPIもまとめて作れる & 軽量なので「もうHonoでいいんじゃないか?」感があります。集客力の強さや機能面の関係で、Next.jsの出番が減ることはまだない気もしますが・・・

とはいえ実務で運用に載せるには、HTMLをTwigなりJSXなりで構築する仕組みを用意しないとちょっとつらいかもしれません。

参考記事

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts