Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

nuxt.js を serverless framework と一緒に使う

More than 1 year has passed since last update.

まだまだ検証段階だが、手法を載せる。

追記: nuxtjs 1.0 がリリースされましたが、残念ながら node.js 8 以降のサポートとなり、2018年2月26日現在、AWS Lambda上で動かすことができません。動かしたい場合は、node.js 6 で動作する、RC版の利用が必要そうです。早く、AWS Lambda に、node.js 8 Runtime が来てほしいですね。

追記2: 2018年4月 に AWS Lambda 上に、node.js 8 ランタイムが実装されました。https://aws.amazon.com/jp/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/ 同様の方法で nuxtjs 1.4 が動作することを確認済みです。

追記3: 2018年8月16日以前の記事では、 S3 に server-bundle.json を転送する挙動があったため、CDN側でこちらのファイルを見えないようにする設定がない場合、ソースコードが漏洩する可能性があります。 Nuxtのサーバで動かした場合は、公開されないような挙動になっています。 https://github.com/nuxt/nuxt.js/issues/916

目的

たいしてリクエストのないアプリなので、serverless framework 上で、nuxt.js を動作させたい。

参考にしたもの

手順

nuxt.config.js の調整

js や css などのアセットに関しては、Lambda 経由でのアクセスではなく、CDNで配信したいため、publicPath の設定を変更する。ローカル開発 (nuxt dev) では、publicPath を設定しても反映されないので、ファイルを分けたり分岐を作る必要はない。

また、Lambda上で動作させる場合は、gzip圧縮をしてしまうとうまく動かないことがわかっている。この点は、手前にCloudFrontのCDNを挟み圧縮をかけることでなんとかなると思う。

nuxt.config.js
module.exports = {
  build: {
    // CSSについても別ファイルになるようにする。こちらも開発環境では反映されない。
    extractCSS: true,
    publicPath: `https://xxxxxxx.cloudfront.net/nuxt/`,
  },
  render: {
    gzip: false
  }
}

ビルドを行う

yarn run build 

.nuxt/dist ディレクトリにある中身をCDNで配信する。
自分は、S3に上げて CloudFront から参照しているので、以下のように同期かけてます。

server-bundle.json に関しては、SSRのみで利用するため除外します。

aws s3 sync ./.nuxt/dist/ s3://$ASSET_BUCKET/nuxt/ --acl public-read --cache-control "public, max-age=31557600" --exclude "server-bundle.json"

サーバを組み立てる

aws-serverless-express を使う。

yarn add aws-serverless-express
server.js
import express from 'express'
import { Nuxt } from 'nuxt'
import awsServerlessExpress from 'aws-serverless-express'
import awsServerlessExpressMiddleware from 'aws-serverless-express/middleware'

const app = express()
const config = require('./nuxt.config')
config.dev = false
config.mode = 'universal'
const nuxt = new Nuxt(config)

app.use(nuxt.render)
app.use(awsServerlessExpressMiddleware.eventContext())

const server = awsServerlessExpress.createServer(app)

export function render (event, context) {
  awsServerlessExpress.proxy(server, event, context)
}

babel と backpack 使ってビルド

yarn add -D backpack-core babel-core babel-plugin-dynamic-import-node babel-plugin-transform-es2015-modules-commonjs babel-preset-stage-2 babel-preset-env
.babelrc
{
  "presets": [
    ["env", {
      "modules": false
    }],
    "stage-2"
  ],
  "plugins": ["transform-runtime"],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"]
    }
  }
}
backpack.config.js
module.exports = {
  webpack: (config, options, webpack) => {
    config.entry.server = './server.js'
    return config
  }
}
package.json
{
  "scripts": {
    "build": "nuxt build && backpack build"
  }
}
yarn run build

serverless.yml を作る

service:
  name: ${self:custom.name}

provider:
  name: aws
  region: ap-northeast-1
  runtime: nodejs6.10
  stage: ${opt:stage, 'dev'}
  memorySize: 2048

custom:
  name: sample

package:
  include:
    - .nuxt/**
    - build/**
  exclude:
    # 要らないファイルが結構あるので除去しまくる
    - .git/**
    - .idea/**
    - README.md
    - backpack.config.js
    - components/**
    - layouts/**
    - nuxt.config.js
    - pages/**
    - scripts/**
    - store/**
    - assets/**
    - middleware/**
    - plugins/**
    - server/**
    - static/**
    - test/**

functions:
  render:
    handler: build/server.render
    events:
      - http:
          path: '/'
          method: 'get'
          private: false
      - http:
          path: '{proxy+}'
          method: 'get'
          private: false

これで、 sls deploy で出来上がったエンドポイントにアクセスすればいい感じに展開された。
serverless-domain-manager などを使ってやり、ドメイン割当をすれば、より良い感じに使うことができそう。

ooharabucyou
地球に住んでいます。
http://www.bucyou.net
codeal
即戦力複業ならコデアル。高収入×リモートワークの複業・フリーランス・転職求人多数
https://www.codeal.work
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away