はじめに
Remix を検証がてら実機でお手軽に動かしたいと思い Lambda で動かしてみました。
なぜ Lambda か?
(1) 筆者が慣れていること、
(2) (使いようによっては)お財布に優しこと、
(3) お手軽にデプロイできること、
などが理由です 😅
今回は aws-lambda-web-adapter を用いて Remix を起動するプロジェクトを備忘します。
サンプルリポジトリも用意しているので、必要に応じてご参照ください。
内容
前述の通り、今回は aws-lambda-web-adapter で Remix の WEB アプリを起動します。
と言いつつ、実態としては同ツールの nextjs-zip のサンプルを大いに参考に、それを Remix に転用している程度です。
ざっと今回のプロジェクトの特徴は次になります。
- Remix 側のアプリケーションは init 時から変更はなし
- API Gateway の HTTP API でサクッとエンドポイントを構成
- Makefile で install、build、artifiacts 等の一連のデプロイ処理を集約操作
次にざっと主要なファイルについて紹介します。
(SAM) template.yml
プロビジョニング用の SAM テンプレートです。
ほぼほぼ aws-lambda-web-adapter のサンプルを転用していますが Architectures
と Layers
は、arm64 に変えています。
1AWSTemplateFormatVersion: "2010-09-09"
2Transform: AWS::Serverless-2016-10-31
3Description: >
4 serverless-remix-demo
5
6 Sample SAM Template for serverless-remix-demo
7
8Globals:
9 Function:
10 Timeout: 10
11
12Resources:
13 RemixFunction:
14 Type: AWS::Serverless::Function
15 Properties:
16 CodeUri: ./
17 MemorySize: 256
18 Handler: run.sh
19 Runtime: nodejs20.x
20 Architectures:
21 # - x86_64
22 - arm64 # ここはお使いの環境に合わせてください
23 Environment:
24 Variables:
25 AWS_LAMBDA_EXEC_WRAPPER: /opt/bootstrap
26 AWS_LWA_ENABLE_COMPRESSION: true
27 RUST_LOG: info
28 PORT: 8000
29 Layers:
30 # - !Sub arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerX86:20
31 - !Sub arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerArm64:20
32 Events:
33 RootEvent:
34 Type: HttpApi
35 Properties:
36 Path: /
37 Method: any
38 ProxyEvent:
39 Type: HttpApi
40 Properties:
41 Path: /{proxy+}
42 Method: any
43 Metadata:
44 BuildMethod: makefile
45
46Outputs:
47 RemixFunctionURL:
48 Description: "API Gateway endpoint URL for Remix"
49 Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/"
Makefile
ビルドして、必要なファイルを zip 化しています。
ファイル構成は、公式の indie-stack
と呼ばれるテンプレートの Dockerfile を参考にしています。
1BUILD_DIR=${PWD}
2
3install:
4 rm -rf node_modules
5 npm ci
6
7build:
8 npm run build
9
10artifacts:
11 # Production packages installed
12 npm ci --omit=dev
13
14 cp package.json $(ARTIFACTS_DIR)
15 cp -r node_modules/. $(ARTIFACTS_DIR)/node_modules
16 cp -r build/. $(ARTIFACTS_DIR)/build
17 cp -r public/. ${ARTIFACTS_DIR}/public
18 cp run.sh $(ARTIFACTS_DIR)
19
20 cd $(ARTIFACTS_DIR) && zip -ry ${BUILD_DIR}/lambdaFunctionSrc.zip .
21 rm -rf "$(ARTIFACTS_DIR)"
22 mv ${BUILD_DIR}/lambdaFunctionSrc.zip "$(ARTIFACTS_DIR)"
23
24build-RemixFunction: install build artifacts
run.sh
純正の remix-serve
と言う node サーバーで起動しています。
1#!/bin/bash
2
3HOSTNAME=0.0.0.0 exec ./node_modules/.bin/remix-serve ./build/index.js
デプロイ
あとは、SAM CLI でデプロイするだけです。
1sam build
2sam deploy --guided
余談
定番の API Gateway の Rest API 構成もあるのですが、今回は手軽に起動することを目的としたため外しています。
と言うのも、Rest API ではエンドポイントにステージ名が含まれるため、Remix 側が想定しているパスと API Gateway 側のパスが異なり、静的ファイルのリクエストエラーが起きる問題に遭遇しました。
1# パスずれの例
2
3# API Gateway のエンドポイント
4https://xxx.execute-api.ap-northeast-1.amazonaws.com/prod/hoge.js
5
6# Remix の想定しているパス
7https://xxx.execute-api.ap-northeast-1.amazonaws.com/hoge.js
これを回避するためには、Custom Domain を使うか、Remix 側で basename
を指定するなどが考えられます。
これを Rest API 側で回避できる設定などあるのでしょうか? 🤔
おわりに
キャッシュ周りも取り回したいとなったら CloudFront と組み合わせると、より快適な UX が提供できそうです。
と言いつつ、そこまで体力はなく今回はここまで...と言うかよく分かっていない 😅