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なりで構築する仕組みを用意しないとちょっとつらいかもしれません。

    参考記事

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark