カテゴリー
SvelteKitとAWS Lambda@Edgeで始めるサーバーレスなハイブリット(SSR/SSG)ウェブページを楽々作成する
※ 当ページには【広告/PR】を含む場合があります。
2023/03/21
1. SvelteKitの開発環境の導入
2. AWSウェブサイトとして利用する際のadapter-nodeのデメリット
3. AWS向けのアダプターの使い方・実装方法
4. Serverless FrameworkでのLambda@Edgeの使い方
SvelteKitの導入の始め方
SvelteKitプロジェクトの作成
$ npm create svelte@latest sveltekit-app
Need to install the following packages:
create-svelte@3.1.2
Ok to proceed? (y) y
create-svelte version 3.1.2
┌ Welcome to SvelteKit!
│
◇ Which Svelte app template?
│ Skeleton project
│
◇ Add type checking with TypeScript?
│ No
│
◇ Select additional options (use arrow keys/space bar)
│ none
│
└ Your project is ready!
Install community-maintained integrations:
https://github.com/svelte-add/svelte-add
Next steps:
1: cd sveltekit-app
2: npm install (or pnpm install, etc)
3: git init && git add -A && git commit -m "Initial commit" (optional)
4: npm run dev -- --open
To close the dev server, hit Ctrl-C
Stuck? Visit us at https://svelte.dev/chat
Skelton > No type-checking > No additional option
$ cd sveltekit-app
$ yarn install
$ yarn dev
VITE v4.1.4 ready in 587 ms
➜ Local: http://localhost:5173/
➜ Network: http://172.22.0.2:5173/
➜ press h to show help
11:53:18 AM [vite-plugin-svelte] ssr compile in progress ...
11:53:18 AM [vite-plugin-svelte] ssr compile done.
package files time avg
sveltekit-app 3 93.2ms 31.1ms
5173
http://localhost:5173
adapter-nodeを使ったExpress-SSRサイトを構築する方法
adapter-node
$ yarn add @sveltejs/adapter-node -D
svelte.config.js
//import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [vitePreprocess()],
kit: {
adapter: adapter(),
}
};
export default config;
.env
DEV_CUSTOM_PORT=5173
yarn build
build
index.js
handler.js
+ index.js:
SvelteKit標準のサーバーアプリ本体
+ handler.js:
Express等のカスタムサーバー向けのミドルウェア
index.js
handler.js
Expressサーバーとして試してみる
handler.js
$ yarn add express
$ yarn add @types/express -D
$ touch server.js
import express from "express";
import { handler } from './build/handler.js';
const port = 5173;
const endpoint = `http://localhost:${port}`;
const app = express();
app.use(handler);
app.listen(port, () => {
process.stdout.write(`\x1b[0;32m\x1b[6m👇をCtrl+クリックしてブラウザで開こう!\x1b[0m\n\x1b[0;43;1;37m${endpoint}\x1b[0m`);
});
http://localhost:5173
SSRレンダリング
AWS向けのAdapterでSvelteKit-SSRサイトを構築する方法
AWS-CDK
AWS-CDK
1. Lambda@Edge用にIAM:UpdateAssumeRolePolicyポリシーの追加が必要
2. 基本的にus-east-1リージョン限定
3. スタックの削除の手続きが他より多い
SvelteKit用の専用アダプターでクライアント/サーバー側のリソースをビルド
$ yarn add @yarbsemaj/adapter-lambda -D
svelte.config.js
import { vitePreprocess } from '@sveltejs/kit/vite';
//👇追加
import serverless from '@yarbsemaj/adapter-lambda';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [vitePreprocess()],
kit: {
//👇置き換え
adapter: serverless(),
//...
}
};
export default config;
vite build
build
build
- server:
Lambda(SSR用)にセットされるハンドラ関数(server.js)
- edge:
Lambda@Edge(ルート仕分け)に使われるハンドラ(router.js)
- assets:
S3バケットに保管されるクライアントへ提供する静的アセット
- prerendered
プリレンダリングしたページが存在する場合、
S3バケットにindex.html等が保管され、router.jsからクライアントに配給される
Serverless Frameworkによるデプロイメント
$ yarn add serverless -D
$ yarn add @silvermine/serverless-plugin-cloudfront-lambda-edge -D -E
$ yarn add serverless-s3-deploy -D
iam:UpdateAssumeRolePolicy
serverless.yml
service: 'sveltekit-app'
frameworkVersion: "3"
plugins:
- '@silvermine/serverless-plugin-cloudfront-lambda-edge'
- serverless-s3-deploy
provider:
name: aws
runtime: nodejs16.x
lambdaHashingVersion: 20201221
#👇Lambda@Edgeを使う場合、"us-east-1"が必須
region: us-east-1
stage: ${opt:stage, 'dev'}
#👇①(後述)
package:
individually: true
exclude:
- ./**
include:
- build/server/**
- build/edge/**
#👇②(後述)
custom:
assets:
auto: true
targets:
- bucket:
Ref: StaticAssets
files:
- source: ./build/assets/
globs:
- '**'
empty: true
headers:
CacheControl: max-age=31104000
- source: ./build/prerendered/
globs:
- '**'
empty: true
headers:
CacheControl: max-age=60
#👇③(後述)
functions:
svelte:
handler: build/server/serverless.handler
memorySize: 256
timeout: 15
url: true
cfLambda:
handler: build/edge/router.handler
memorySize: 128
timeout: 1
lambdaAtEdge:
distribution: 'WebsiteDistribution'
eventType: origin-request
resources:
Resources:
StaticAssets:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: ${self:provider.stage}-${self:service}-static-assets
StaticAssetsS3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: StaticAssets
PolicyDocument:
Statement:
- Sid: PublicReadGetObject
Effect: Allow
Principal: "*"
Action:
- s3:GetObject
Resource:
Fn::Join: ["", ["arn:aws:s3:::", { "Ref": "StaticAssets" }, "/*"]]
#👇④(後述)
WebsiteDistribution:
Type: 'AWS::CloudFront::Distribution'
Properties:
DistributionConfig:
Origins:
-
DomainName: !Select [2, !Split ["/", !GetAtt ["SvelteLambdaFunctionUrl", "FunctionUrl"]]]
Id: default
OriginCustomHeaders:
-
HeaderName: 's3-host'
HeaderValue: '${self:provider.stage}-${self:service}-static-assets.s3.amazonaws.com'
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: 'https-only'
Enabled: true
Comment: '${self:service}_${self:provider.stage}'
DefaultCacheBehavior:
TargetOriginId: default
Compress: true
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
CachedMethods:
- GET
- HEAD
- OPTIONS
ForwardedValues:
Cookies:
Forward: all
QueryString: True
ViewerProtocolPolicy: 'redirect-to-https'
①
#...
package:
individually: true
exclude:
- ./**
include:
- build/server/**
- build/edge/**
build/server
build/edge
individually: true
package
②
serverless-s3-deploy
#...
custom:
assets:
auto: true
targets:
- bucket:
Ref: StaticAssets
files:
- source: ./build/assets/
globs:
- '**'
empty: true
headers:
CacheControl: max-age=31104000
- source: ./build/prerendered/
globs:
- '**'
empty: true
headers:
CacheControl: max-age=60
#...中略
resources:
Resources:
StaticAssets:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: ${self:provider.stage}-${self:service}-static-assets
#...
StaticAssets
build/assets
build/prerendered
empty: true
CacheControl
31104000秒 = 360日
60秒 = 1分
③
#...
functions:
svelte:
handler: build/server/serverless.handler
memorySize: 256
timeout: 15
url: true
cfLambda:
handler: build/edge/router.handler
memorySize: 128
timeout: 1
lambdaAtEdge:
distribution: 'WebsiteDistribution'
eventType: origin-request
#...
svelte
cfLambda
build/server/serverless.handler
build/edge/router.handler
svelte
memorySize
timeout
url: true
cfLambda
@silvermine/serverless-plugin-cloudfront-lambda-edge
lambdaAtEdge
eventType: origin-request
④
#...
WebsiteDistribution:
Type: 'AWS::CloudFront::Distribution'
Properties:
DistributionConfig:
Origins:
-
DomainName: !Select [2, !Split ["/", !GetAtt ["SvelteLambdaFunctionUrl", "FunctionUrl"]]]
Id: default
OriginCustomHeaders:
-
HeaderName: 's3-host'
HeaderValue: '${self:provider.stage}-${self:service}-static-assets.s3.amazonaws.com'
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: 'https-only'
「WebsiteDistribution」
「svelte」
DomainName
!Select [2, !Split ["/", !GetAtt ["SvelteLambdaFunctionUrl", "FunctionUrl"]]]
「WebsiteDistribution」
「cfLambda」
#...
OriginCustomHeaders:
-
HeaderName: 's3-host'
HeaderValue: '${self:provider.stage}-${self:service}-static-assets.s3.amazonaws.com'
s3-host
.env
router.js
.env
SvelteKitアプリのデプロイ
$ npx sls deploy --verbose
まとめ
1. SvelteKitの開発環境の導入
2. AWSウェブサイトとして利用する際のadapter-nodeのデメリット
3. AWS向けのアダプターの使い方・実装方法
4. Serverless FrameworkでのLambda@Edgeの使い方
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー