DEV Community

Jacob Anavisca
Jacob Anavisca

Posted on

Host Nuxt SSR app on AWS using Serverless

I struggled through being able to get my portfolio site online because I haven’t found any suitable documentation online for this process. There are a lot of random articles online that say this is how you can host Nuxt SSR on AWS but a lot of them either end up mentioning using the Nuxt generate option (not SSR) or can be a bit complex to actually set up. I’ve never made a post about anything but wanted to in order to help anyone else out that’s struggling with the same issue.

The great thing about using Serverless for deploying a Nuxt site is that if you have other AWS services you want to integrate it’s as simple as adding some iamRoleStatements. Then you can access the data from those services through an Expressjs middleware and retrieve them from the res of the Nuxt context.

Prerequisites:

Step 1: Create demo Nuxt app

To create the demo project run

$ npm init nuxt-app nuxt-serverless
Enter fullscreen mode Exit fullscreen mode

in your terminal. For the Rendering mode prompt select Universal (SSR / SSG). For the Deployment target select Server (Node.js hosting). For all other prompts select which options you want for your project. Next to install the necessary dependencies cd into your project folder and run

$ npm i aws-serverless-express express serverless-http
Enter fullscreen mode Exit fullscreen mode

To install the necessary devDependencies run

$ npm i -D serverless serverless-offline
Enter fullscreen mode Exit fullscreen mode

Once the project is created open it in your preferred text editor. You’ll need to create an app.js file in order to programmatically serve Nuxt info using Expressjs. Copy and paste in this code:

// app.js
'use strict'

const { createServer, proxy } = require('aws-serverless-express')
const express = require('express')
const { Nuxt } = require('nuxt')
const config = require('./nuxt.config.js')

const app = express()
const nuxt = new Nuxt({
  ...config,
  dev: false,
  _start: true
})

app.use(async (req, res) => {
  if (nuxt.ready) {
    await nuxt.ready()
  }
  nuxt.render(req, res)
})

const server = createServer(app, void 0, [
  'application/javascript',
  'application/json',
  'application/manifest+json',
  'application/octet-stream',
  'application/xml',
  'font/eot',
  'font/opentype',
  'font/otf',
  'image/gif',
  'image/jpeg',
  'image/png',
  'image/svg+xml',
  'image/x-icon', // for favicon
  'text/comma-separated-values',
  'text/css',
  'text/html',
  'text/javascript',
  'text/plain',
  'text/text',
  'text/xml',
  'application/rss+xml',
  'application/atom+xml'
])

module.exports.handler = (event, ctx) => {
  proxy(server, event, ctx)
}

Enter fullscreen mode Exit fullscreen mode

You’ll need to create a serverless.yml file in order for serverless to package your code into a Lambda. Copy and paste in this code:

# serverless.yml
service: nuxt-serverless

provider:
  name: aws
  runtime: nodejs12.x
  stage: ${opt:stage, 'dev'}
  region: us-west-2
  apiGateway:
    binaryMediaTypes:
      - '*/*'
  environment:
    # stops telemetry output from nuxt
    NUXT_TELEMETRY_DISABLED: 1

functions:
  nuxt:
    timeout: 30
    handler: app.handler
    events:
      - http: ANY /
      - http: ANY /{proxy+}

package:
  include:
    # ensures that the build output gets packaged
    - .nuxt/**

plugins:
  - serverless-offline

Enter fullscreen mode Exit fullscreen mode

Step 2: Test run Serverless-Offline

To make sure there are no issues once deployed you’ll want to run:

$ npm run build && sls offline --stage dev --noTimeout --noPrependStageInUrl
Enter fullscreen mode Exit fullscreen mode

While it’s running go to http://localhost:3000/ and you’ll see your Nuxt app working through Serverless! If there are any issues you should try to google the error outputs and try to determine what’s going on before deploying. You can always reach out to me and I can try my best.

Step 3: Deploy that sucker

Go ahead and run

$ sls deploy --stage dev
Enter fullscreen mode Exit fullscreen mode

Whatever URL it spits out won’t work due to the staging path Serverless adds but you can go to the URL to see some content load, it’ll just look kind of weird. A custom domain name is required for it to work correctly.

Step 4: Domain mapping

Sign in to your AWS console. If you don’t already have a domain name (Route 53) and ssl certs (Certificate Manager) you’ll want to look through the AWS docs and register/create both of these. If you already have both then in the search bar type in API Gateway and select it. In your left navigation bar click on Custom domain names and click on Create. Type in the domain you’ve registered through Route 53. For the Endpoint type select Edge-optimized (supports only REST APIs). For the ACM certificate select the certificate that was created in Certificate Manager to work with your domain name. Click Create domain name and then select API Mappings. Click on Configure API mappings and click on Add new mapping. Set the API you created and the stage it was deployed to (dev in this setup) and click Save.

Step 5: Magic

Now go to your domain name and see the magic 🎉

Top comments (1)

Collapse
 
rav1export profile image
rav1export

Hi Jacob, do you have a sample Github CI template that will work on Nuxt? Thanks!