Nuxt.js(v2.2.0)+TypeScriptなアプリをAWS Lambda+αにデプロイしてみた

Nuxt.js(v2.2.0)+TypeScriptなアプリをAWS Lambda+αにデプロイしてみた:


概要

Nuxt.jsのv2系でTypeScriptを利用しつつ、AWS Lambda+αにデプロイできるか確認してみました。


手順

GitHubにいい感じのコードをアップいただけている御方がおられたので、利用させてもらいます。

jeehyukwon/nuxt-serverless: Nuxt.js Serverless SSR Starter on AWS (Lambda + API Gateway + S3) with Serverless Framework
https://github.com/jeehyukwon/nuxt-serverless

静的ファイルはS3、AWS LambdaのNode.jsでExpressを立ち上げて、SSRをして、API Gatewayがエンドポイント、ドメインはカスタムドメインを利用する構成です。

カスタムドメインを利用する前提でしたので、それを外してデプロイするようにしてみます。

Githubに上記リポジトリをフォークしたものがありますので、よければご参考ください。
https://github.com/kai-kou/nuxt-serverless


ソースの取得と環境構築

ローカル環境で構築します。

nodenpm がインストールされている前提です。

> node -v 
v10.11.0 
 
> npm -v 
6.4.1 
> git clone https://github.com/jeehyukwon/nuxt-serverless.git 
> cd nuxt-serverless 
コンテナ内
> npm install 


動作確認

ローカルで動作するか確認します。

> npm run dev 
 
(略) 
✔ success Builder initialized 
✔ success Nuxt files generated 
 
 READY  Listening on http://localhost:3000 
ブラウザでアクセスします。
http://localhost:3000


スクリーンショット 2018-11-13 11.07.17.png




スクリーンショット 2018-11-13 11.07.37.png


はい。

ソースを確認するとSSRしてますね。


デプロイ準備


API Gatewayのステージ対応

AWS Lambdaへデプロイする場合、HTTPアクセスにはAWS API Gatewayを利用することになります。

カスタムドメインを利用しない場合、API GatewayのURLはhttps://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/ のように、ステージ名dev が含まれます。

Nuxt.jsでこのステージ名をBaseURL として設定してやる必要があります。

詳細は下記記事で詳しく解説されています。感謝!

Nuxt.js on AWS Lambda with Serverless Framework - mya-ake com
https://mya-ake.com/posts/nuxtjs-on-aws-lambda/

nuxt.config.jsrouter.base を追加します。

nuxt.config.js(一部抜粋)
module.exports = { 
  (略) 
  router: { 
    base: '/dev/' 
  }, 
  (略) 
} 
Nuxt.jsの設定以外にExpressでも設定が必要となります。リクエストのURLにステージ名dev が含まれないため、強制的に含めてやります。BaseURLはNuxtの設定nuxtConfig.router.base から取得しています。

handler.js
app.use((req, res) => ( 
  setTimeout(() => { 
    req.url = `${nuxtConfig.router.base}${req.url}`.replace('//', '/') 
    nuxt.render(req, res)} 
  , 0) 
)) 


カスタムドメインを利用しない設定

カスタムドメインを利用しないので、package.jsonscripts に指定されているsls create_domainsls delete_domain を削除します。

package.json(一部抜粋)
"scripts": { 
    "dev": "nuxt", 
    "build": "cross-env NODE_ENV=production nuxt build", 
    "start": "nuxt start", 
    "sls:local": "sls offline", 
    "sls:create": "npm run build && sls deploy", 
    "sls:delete": "sls remove", 
    "sls:deploy": "npm run build && sls deploy" 
  }, 
serverless.yml でもカスタムドメイン作成の定義を削除します。(ここではコメントアウトしています。)serviceregionBUCKET_NAMESPACE は任意で変更してください。

serverless.yml
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 
    BUCKET_NAMESPACE: nuxt-serverless  # 3. Specify a new AWS S3 bucket namespace for bundled assets and static assets (should be unique) 
    ASSETS_BUCKET_NAME: ${self:provider.environment.BUCKET_NAMESPACE}-assets-${opt:stage, 'dev'} 
    STATIC_BUCKET_NAME: ${self:provider.environment.BUCKET_NAMESPACE}-static-${opt:stage, 'dev'} 
    ASSETS_BUCKET_URL: https://s3.${self:provider.region}.amazonaws.com/${self:provider.environment.ASSETS_BUCKET_NAME} 
    STATIC_BUCKET_URL: https://s3.${self:provider.region}.amazonaws.com/${self:provider.environment.STATIC_BUCKET_NAME} 
 
custom: 
  # customDomain: 
  #   domainName: service.mydomain.io  # 4. Specify a new domain name to be created 
  #   stage: ${opt:stage, 'dev'} 
  #   certificateName: mydomain.io  # 5. Enter the certificate name in AWS Certificate Manager (us-east-1) for https connection 
  #   createRoute53Record: true 
  serverless-offline: 
    port: 4000 
  s3Sync: 
    - bucketName: ${self:provider.environment.ASSETS_BUCKET_NAME} 
      localDir: .nuxt/dist/client 
    - bucketName: ${self:provider.environment.STATIC_BUCKET_NAME} 
      localDir: static 
 
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 
 
resources: 
  Resources: 
    AssetsBucket: 
      Type: AWS::S3::Bucket 
      Properties: 
        BucketName: ${self:provider.environment.ASSETS_BUCKET_NAME} 
    AssetsBucketPolicy: 
      Type: AWS::S3::BucketPolicy 
      Properties: 
        Bucket: 
          Ref: AssetsBucket 
        PolicyDocument: 
          Version: "2012-10-17" 
          Statement: [ 
            { 
              Action: ['s3:GetObject'], 
              Effect: 'Allow', 
              Resource: { 
                Fn::Join: ['', ['arn:aws:s3:::', { Ref: 'AssetsBucket' }, '/*']], 
              }, 
              Principal: '*' 
            }, 
          ] 
    StaticBucket: 
      Type: AWS::S3::Bucket 
      Properties: 
        BucketName: ${self:provider.environment.STATIC_BUCKET_NAME} 
    StaticBucketPolicy: 
      Type: AWS::S3::BucketPolicy 
      Properties: 
        Bucket: 
          Ref: StaticBucket 
        PolicyDocument: 
          Version: "2012-10-17" 
          Statement: [ 
            { 
              Action: ['s3:GetObject'], 
              Effect: 'Allow', 
              Resource: { 
                Fn::Join: ['', ['arn:aws:s3:::', { Ref: 'StaticBucket' }, '/*']], 
              }, 
              Principal: '*' 
            }, 
          ] 
 
plugins: 
  - serverless-offline 
  - serverless-s3-sync 
  # - serverless-domain-manager 


デプロイする

npm run sls:create またはnpm run sls:deploy することで、Nuxt.jsのビルドと、AWSへのデプロイがされます。

> npm run sls:create 
(略) 
Entrypoint app = 55e8f003a83a598dd113.js 5e45cc8df25adbaac94b.js 1d1bc122ddb9c7b7f271.css 6a943e90e669a1de7258.js 
[13:27:00] Compiling server 
[13:27:04] Compiled server in 4s 
 
Hash: 2c7c34f6c1ea4aefd63d 
Version: webpack 4.25.1 
Time: 3924ms 
Built at: 2018-11-13 13:27:04 
             Asset     Size  Chunks             Chunk Names 
server-bundle.json  213 KiB          [emitted] 
Entrypoint app = server-bundle.js 
✨  Done in 114.07s. 
(略) 
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 
S3 Sync: Syncing directories and S3 prefixes... 
.... 
S3 Sync: Synced. 
デプロイができたら、ブラウザでアクセスしてみます。xxxxxxxxxx はご自身の環境に合わせてください。

https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/



Hello__Nuxt_Serverless_Template.png




Hello__TypeScript.png




view-source_https___vvb2o02739_execute-api_ap-northeast-1_amazonaws_com_dev_.png


なんとか動きました^^


はまりポイント


nuxt dev でホスト名に0.0.0.0 が指定できない

当初Dockerコンテナ内で実行させようとしたのですが、ホスト名に0.0.0.0 が指定できなかったので、ローカル環境で構築しました。

Host and Port - Nuxt.js
https://nuxtjs.org/faq/host-port

0.0.0.0 を指定すると、ランダムっぽいIPが振られてしまいます。。。

環境変数HOSTNUXT_HOSTpackage.json で指定も --hostname もだめ。むむぅ。なんでしょう。。。

ドキュメントには

Note: If port is assigned the string value of '0' (not 0, which is falsy), a random port will be assigned to your Nuxt application.
とありますので、ポートはわかるのですが、ホスト名でも同じような挙動です。。。ローカルでもDockerコンテナ内でも同じ挙動でした。

ローカル
INFO Building project 
 
✔ success Builder initialized 
✔ success Nuxt files generated 
 
READY Listening on http://192.168.34.25:3001 
Dockerコンテナ
INFO Building project 
 
✔ success Builder initialized 
✔ success Nuxt files generated 
 
READY Listening on http://172.28.0.2:3001 


API Gatewayのパスが面倒

Nuxt.jsとExpressと別でBaseURL の設定が必要だったのが非常にわかりにくかったです。今回Serverless-httpを利用していたのですが、いくつかIssueが上がっていました。どうにかならないものでしょうか^^

Correct path for non-custom endpoints by bsdkurt · Pull Request #42 · dougmoscrop/serverless-http
https://github.com/dougmoscrop/serverless-http/pull/42

Include baseUrl in request object · Issue #35 · dougmoscrop/serverless-http
https://github.com/dougmoscrop/serverless-http/issues/35


まとめ

ローカル環境の構築がさくっと終わったのでAWS Lambdaにもさくっと構築できるだろうと思って取り組んだら、思いの外ハマって時間がかかりました。Nuxt.jsもv2がリリースされたこともあり、かつTypeScriptを利用だったので、正しい情報・設定を見極めるのに試行錯誤することになりました。

デプロイできることは確認できましたので、ひとまずは

やったぜ^^


参考

jeehyukwon/nuxt-serverless: Nuxt.js Serverless SSR Starter on AWS (Lambda + API Gateway + S3) with Serverless Framework
https://github.com/jeehyukwon/nuxt-serverless

Nuxt.js on AWS Lambda with Serverless Framework - mya-ake com
https://mya-ake.com/posts/nuxtjs-on-aws-lambda/

Host and Port - Nuxt.js
https://nuxtjs.org/faq/host-port

Correct path for non-custom endpoints by bsdkurt · Pull Request #42 · dougmoscrop/serverless-http
https://github.com/dougmoscrop/serverless-http/pull/42

Include baseUrl in request object · Issue #35 · dougmoscrop/serverless-http
https://github.com/dougmoscrop/serverless-http/issues/35

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)