前回、以下のリポジトリからカスタムドメインの利用を外した構成で、Nuxt.js(v2.2.0)+TypeScriptのアプリがAPI Gateway+AWS Lambdaにデプロイできることを確認しました。
Nuxt.js(v2.2.0)+TypeScriptなアプリをAWS Lambda+αにデプロイしてみた
https://qiita.com/kai_kou/items/5b1ebb9abc5d62545e04
jeehyukwon/nuxt-serverless: Nuxt.js Serverless SSR Starter on AWS (Lambda + API Gateway + S3) with Serverless Framework
https://github.com/jeehyukwon/nuxt-serverless
今回は、以下のような記事を発見してしまったので、S3を外した構成を試してみます。発見したからには仕方がないです。やってみます。
Serverless-Side Rendering With AWS Lambda & NuxtJS
https://medium.com/@fernalvarez/serverless-side-rendering-with-aws-lambda-nuxtjs-b94d15782af5
手順
環境構築
GitHubに今回のソースをアップしていますので、よければご参考ください。
https://github.com/kai-kou/nuxt-serverless/tree/feature/no-use-s3
前回フォークしたリポジトリを利用します。
kai-kou/nuxt-serverless: Nuxt.js Serverless SSR Starter on AWS (Lambda + API Gateway + S3) with Serverless Framework
https://github.com/kai-kou/nuxt-serverless
> git clone https://github.com/kai-kou/nuxt-serverless.git
> cd nuxt-serverless
> npm install
必要となるライブラリのインストールと、不要となるライブラリをアンインストールします。
> npm install --save-dev serverless-apigw-binary
> npm install --save aws-serverless-express
> npm uninstall --save serverless-http
> npm uninstall --save-dev serverless-s3-sync
serverless.yaml
を編集します。S3に関する定義を削除、LambdaとAPI Gatewayで静的ファイルが返せるように定義を追加しています。service
やregion
は任意でどうぞ。
service: nuxt-serverless # 1. Edit whole service name
provider:
name: aws
runtime: nodejs8.10
stage: ${opt:stage, 'dev'}
region: ap-northeast-1 # 2. Edit AWS region name
environment:
NODE_ENV: production
custom:
serverless-offline:
port: 4000
apigwBinary:
types:
- '*/*'
package:
exclude:
- src/**
include:
- serverless.yml
functions:
nuxt-renderer:
handler: handler.render
memorySize: 512
timeout: 30
events:
- http:
path: /
method: ANY
cors: true
- http:
path: /{proxy+}
method: ANY
cors: true
plugins:
- serverless-offline
- serverless-apigw-binary
実装
handler.js
の実装を分割します。
ほぼ、記事通りの実装となります。
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./server')
const binaryMimeTypes = [
'application/javascript',
'application/json',
'application/octet-stream',
'application/xml',
'font/eot',
'font/opentype',
'font/otf',
'image/jpeg',
'image/png',
'image/svg+xml',
'text/comma-separated-values',
'text/css',
'text/html',
'text/javascript',
'text/plain',
'text/text',
'text/xml'
]
const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes)
module.exports.render = (event, context) => awsServerlessExpress.proxy(server, event, context)
server.js
にExpressの実装を引っ越しました。ポイントは/_nuxt
と/static
へのアクセス時にS3にリダイレクトさせていたのを、直接ファイルを返すようにしている点です。
前回同様に、ステージ名のパス対応も入れています。
const express = require('express')
const {Nuxt} = require('nuxt')
const path = require('path')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const app = express()
app.use(awsServerlessExpressMiddleware.eventContext())
app.use('/_nuxt', express.static(path.join(__dirname, '.nuxt', 'dist', 'client')))
app.use('/static', express.static(path.join(__dirname, 'static')))
let config = require('./nuxt.config.js')
const nuxt = new Nuxt(config)
app.use((req, res) => {
req.url = `${config.router.base}${req.url}`.replace('//', '/')
nuxt.render(req, res)
})
module.exports = app
デプロイ
デプロイしてみます。
> npm run sls:create
(略)
Entrypoint app = 55e8f003a83a598dd113.js 5e45cc8df25adbaac94b.js 1d1bc122ddb9c7b7f271.css 1417c3d6af1ef683305c.js
[15:20:26] Compiling server
[15:20:31] Compiled server in 5s
Hash: f66c1442df8e32ec8ab4
Version: webpack 4.25.1
Time: 4754ms
Built at: 2018-11-13 15:20:31
Asset Size Chunks Chunk Names
server-bundle.json 213 KiB [emitted]
Entrypoint app = server-bundle.js
(略)
Serverless: Stack update finished...
Service Information
service: nuxt-serverless
stage: dev
region: ap-northeast-1
stack: nuxt-serverless-dev
api keys:
None
endpoints:
ANY - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
ANY - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
nuxt-renderer: nuxt-serverless-dev-nuxt-renderer
動作確認
デプロイができたら、ブラウザでアクセスしています。
やったぜ。
ハマりどころ
API Gatewayのパス指定に気をつけよう
今回は参考にした記事だと、serverless.yml
events
にhttp
設定が1つだけですが、それだとhttps://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
にアクセスしても、API GatewayからAWS Lambdaへイベントが発火せず、{"message":"Missing Authentication Token"}
となりました。ここは前回参考にした記事の設定のままだとうまくいきました。
events:
- http:
path: /
method: ANY
cors: true
- http:
path: /{proxy+}
method: ANY
cors: true
events:
- http:
path: /{proxy+}
method: ANY
cors: true
events:
- http: ANY {proxy+}
タイムアウトエラーが発生したらyarn
を利用する
npm
でライブラリをインストールしていると、デプロイできても、URLへアクセスするとタイムアウトエラーになることがありました。その場合には、yarn
でライブラリをインストールし直すとうまく動きました。
> rm -rf node_modules/
> npm install -g yarn # yarnがインストールされていなかったら
> yarn
> yarn build
> sls deploy
注意点
注意点としては、静的ファイルが多くなるとAWS Lambdaのアップロード制限に引っかかる可能性があるかもしれません。
AWS Lambda の制限 - AWS Lambda
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html
AWS Lambda デプロイメントの制限
Lambda 関数デプロイパッケージのサイズ (圧縮 .zip/.jar ファイル) : 50 MB
リージョンあたりの、アップロードできるすべてのデプロイパッケージの合計サイズ : 75 GB
デプロイパッケージ (非圧縮 .zip/.jar サイズ) に圧縮できるコード/依存関係のサイズ: 250 MB
まとめ
シンプルなSSR対応のサービスを提供するにはこちらのほうがシンプルですね。
プロジェクト次第で使い分けが良さそうです。
参考
Serverless-Side Rendering With AWS Lambda & NuxtJS
https://medium.com/@fernalvarez/serverless-side-rendering-with-aws-lambda-nuxtjs-b94d15782af5
Nuxt.js(v2.2.0)+TypeScriptなアプリをAWS Lambda+αにデプロイしてみた
https://qiita.com/kai_kou/items/5b1ebb9abc5d62545e04
jeehyukwon/nuxt-serverless: Nuxt.js Serverless SSR Starter on AWS (Lambda + API Gateway + S3) with Serverless Framework
https://github.com/jeehyukwon/nuxt-serverless