1. 概要
前回はバックエンド側のAPIをSAMで環境毎にデプロイする内容でした。今回はNextJSアプリをServerlessのLambdaにデプロイする内容となります。
- NextJSアプリは簡易なTodoアプリです。
こちらの記事にインスピレーションを受けたので合わせて読んで頂ければ幸いです。
NextJSのソースコード以外はほぼ下記のままです。
2. Nodeのインストール
こちらを参考
3. プロジェクトを作成
3-1. こちらを参考
- 【NextJS】SassとTypescriptでレイアウトを構成
- 今回のプロジェクト名:serverless-nextjs-demo
4. ソースコード
※簡易Todoアプリ
4-1. src/app/page.tsx
"use client";
import { ChangeEvent, MouseEvent, KeyboardEvent, useState } from "react";
export type Todo = {
id: number;
content: string;
};
export default function Home() {
const [text, setText] = useState<string>("");
const [todos, setTodos] = useState<Todo[]>([]);
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
setText(e.currentTarget.value);
};
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
applyData();
};
const keyDownHandler = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.nativeEvent.isComposing || e.key !== "Enter") return;
applyData();
e.currentTarget.focus();
};
const applyData = () => {
if (text.length == 0) return;
const todo: Todo = { id: ++todos.length, content: text };
const newTodos: Todo[] = [...todos, todo].filter(
(todo) => todo != undefined
);
setTodos(newTodos);
setText("");
};
const removeData = (e: MouseEvent<HTMLAnchorElement>, todoId: number) => {
e.preventDefault();
const newTodos: Todo[] = [...todos].filter((todo) => todo.id != todoId);
setTodos(newTodos);
};
return (
<div>
<input
type="text"
value={text}
onChange={(e) => handleChange(e)}
onKeyDown={keyDownHandler}
autoFocus={true}
/>
<button onClick={handleClick}>Register</button>
<br />
Todo list
<ul>
{todos.map((todo: Todo, idx: number) => (
<li key={idx}>
{todo.content}(
<a
href="#"
onClick={(e: MouseEvent<HTMLAnchorElement>) =>
removeData(e, todo.id)
}
>
X
</a>
)
</li>
))}
</ul>
</div>
);
}
5. AWSアカウントにサインアップ
5-1. 前提条件
6. AWSアクセスキーの取得
6-1. AWSアクセスキーの取得
7. AWS CLI のインストール
7-1. インストール
8. AWS SAM CLIのインストール
8-1. インストール
9. 起動シェルを作成
9-1. run.sh
#!/bin/bash -x
[ ! -d '/tmp/cache' ] && mkdir -p /tmp/cache
exec node server.js
10. Dockerfileを作成
10-1. Dockerfile
FROM public.ecr.aws/docker/library/node:20.9.0-slim as builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM public.ecr.aws/docker/library/node:20.9.0-slim as runner
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter
ENV PORT=3000 NODE_ENV=production
ENV AWS_LWA_ENABLE_COMPRESSION=true
WORKDIR /app
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/run.sh ./run.sh
RUN ln -s /tmp/cache ./.next/cache
RUN chmod +x ./run.sh
CMD exec ./run.sh
11. template.yamlを作成
11-1. template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
serverless-nextjs-demo
Sample SAM Template for serverless-nextjs-demo
Globals:
Function:
Timeout: 10
Resources:
NextjsFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: /
MemorySize: 256
PackageType: Image
Architectures:
- x86_64
Events:
RootEvent:
Type: HttpApi
Properties:
Path: /
Method: any
ProxyEvent:
Type: HttpApi
Properties:
Path: /{proxy+}
Method: any
Metadata:
DockerTag: v1
DockerContext: ./
Dockerfile: Dockerfile
Outputs:
NextjsFunctionURL:
Description: "API Gateway endpoint URL for Next.js"
Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/"
- 「samconfig.toml」は「sam deploy」後、作成される。
- 「sam deploy」前に最初から作成しても良い。
- 下記は自動作成後
version = 0.1
[default.deploy.parameters]
stack_name = "serverless-nextjs-demo"
resolve_s3 = true
s3_prefix = "serverless-nextjs-demo"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM"
image_repositories = ["NextjsFunction=123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/serverlessnextjsdemoe3456789/nextjsfunction23456789repo"]
12. NextJSのoutputを指定
12-1. next.config.js
const nextConfig: NextConfig = {
output: "standalone",
};
12-2. ディレクトリ構造
.
├── Dockerfile
├── README.md
├── eslint.config.mjs
├── next-env.d.ts
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── public
│ ├── file.svg
│ ├── globe.svg
│ ├── next.svg
│ ├── vercel.svg
│ └── window.svg
├── run.sh
├── src
│ └── app
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── tailwind.config.ts
├── template.yaml
└── tsconfig.json
3 directories, 21 files
13. アプリケーションを構築
13-1. build
sam build
14. アプリケーションをAWS クラウドにデプロイ
14-1. deploy
sam deploy --guided
.
.
.
CloudFormation outputs from deployed stack
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key NextjsFunctionURL
Description API Gateway endpoint URL for Next.js
Value https://a1b2c3d4e5.execute-api.ap-northeast-1.amazonaws.com/
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - serverless-nextjs-demo in ap-northeast-1
15. アプリケーションを確認
15-1. エンドポイントの値を取得
- 上記14-1ログより「Outputs」を探す
- Key
- NextjsFunctionURL
- Value
- https://a1b2c3d4e5.execute-api.ap-northeast-1.amazonaws.com/
- これがエンドポイント
- Key
15-2. 画面で確認

16. Management Consoleで確認
16-1. 画面で確認

17. AWSクラウドからアプリケーションを削除
※必要に応じ削除
sam delete --stack-name serverless-nextjs-demo
18. 備考
今回はNextJSアプリをServerlessのLambdaにデプロイする内容でした。
19. 参考
- AWS Serverless Application Model (AWS SAM) とは何ですか? – AWS Serverless Application Model (amazon.com)
- aws-lambda-web-adapter/examples/nextjs at main · awslabs/aws-lambda-web-adapter · GitHub
- Introduction | Next.js
投稿者プロフィール

-
開発好きなシステムエンジニアです。
卓球にハマってます。