A crash course on serverless-side rendering with Vue.js, Nuxt.js and AWS Lambda

Adnan Rahić on August 20, 2018

If you liked this tutorial, you can support my writing by buying me a coffee. That's a mouthful of a title right there. Don't let it scare you... [Read Full]
markdown guide
 

Works great, but resulting package is 40MB+
Would be good to see another tutorial on trimming the unused packages. I tried with Exclude/Include in serverless CLI and also the serverless-plugin-optimize and serverless-plugin-include-dependencies, they all had an effect on the output size, but none worked in AWS :(
Shouldn't we compile the application and send only the dist files instead of the entire node_modules folder?

 
 

Any way I can test my site locally? I've tried using the serverless-offline plugin, but although the local web server is starting up, I get no functional endpoints. Navigating to localhost:3000/ just gives a 404 in the server log.

 

I was having the same problem, but got it working with the following:

app.use((req, res) => setTimeout(() => nuxt.render(req, res), 0));

I have no idea why this works, I stole it from the jeehyukwon/nuxt-edge-serverless-template repository.

 

I believe it's safer if you wait till the renderer is ready. To do so, simply listen to the render:done hook. For instance something like should work:

app.use((req, res) => {
  nuxt.hook("render:done", () => {
    nuxt.render(req, res);
  });
});

setTimeout doesn't seem very reliable to me :) On my mac I had to wait around 60ms for instance.

The following works as well.

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

With the nuxt.hook("render:done" () => {}) I was getting random 404 errors when deployed. nuxt.ready() did the trick for me!

Awesome of you to share this! Feel free to add a PR to the GitHub repo with this edit. 👌

 

Can confirm this solution works. Install serverless-offline with npm i serverless-offline. Then in nuxt.js, just replace app.use(nuxt.render) with Pascal's code, above. Run the plugin with sls offline. Be sure to include the http in http://localhost:3000.

 

Render static images in nuxt when deployed

I cloned the repo and deployed and everything worked until i added local file to the static folder of my nuxt app with other plugins like PWA and router etc. When i reference the images, they don't load and the sw.js script returns a 403 http error.

Please what am i to do to fix this error. Do i have to update the serverless.yml file or what?

 

"This will create a CloudFront distribution and hook it up to your domain. Make sure that you've added the certificates to your AWS account."

I new I will stuck in some place.
As I am totaly new to the AWS... how am I supposed to add the certificates to my AWS account?
Should I change the default "vue-ssr.your-domain.com" and if so to what?

I have no domain on AWS this is my first touch with it.

 

I ran into the same problem. There are quite a few steps you need to do manually (i.e in the Web Console) before you can use this guide. I won't get into details, but first you need to register a domain name in Route53 (or add a hosted zone with a domain from another registrar, but that is probably more complicated). Then you will need to add a certificate. Easiest way is to use the Certificate Manager. Enter yourdomain.com and *.yourdomain.com in your certificate request, then follow the guide to verify it. After you've done this, you are ready to go with sls create_domain. It will add the vue-ssr subdomain for you.

 

Fantastic post, Adnan. Really enjoying this series of threads relating to serverless.
One (silly?) question.
Is further setup required to be able to serve static assets like images etc.?

 

Hey Luca

Not a silly question at all! To be direct, no further setup is required. Even though a lambda function is ephemeral, you can store static assets and serve them just as from any other server (check this out in the repo).

However, I would argue against this for a real-world use case. You should really use an S3 bucket to store the images and serve them from there.

Another cool fact is that you can use Nuxt to generate static files and host everything on S3, without using AWS Lambda at all. It all comes down to preference.

Hope this clears some things up. I'm glad you liked the article. Stay in touch or send me a message through the chat if you have any questions. 😃

 

Very nice example and article! Any thoughts on how to store the static dist files on S3? I mean lambda for the SSR first hit from the client. Then any other nuxt dist files needed once the the SPA is hydrated on the client are then retrieved form the s3 bucket/cloud-front distribution?

Alright, I spent my weekend on this, here's the insights:

  1. You need a "manually setup" cloudfront distribution and stop relying on the automated edge optimized domain name by serverless.
    You configure the cloudfront distribution with 2 behaviors:
    "/" to your API Gateway
    "/_nuxt/*" to your s3 bucket.
    And you configure manually the custom domain name in cloudfront and in Route53 DNS
    Its a bit of initial work but you'll do this only once. You can remove the serverless plugin for domain management.

  2. I used serverless-finch plugin which handle the upload to s3 + a manually s3 bucket setup
    You can remove the "app.use('/nuxt', express.static(path.join(_dirname, '.nuxt', 'dist')))" as your lambda won't be called anymore for serving static files.

  3. You need to optimize (aka reduce) your dependencies, rely on nuxt-start (check npm), which is a production-only distribution of nuxt.

Exclusively for aws lamba (not sure for other cloud providers):

  • I packaged expressjs in a lambda layer
  • I packaged nuxt-start and my other dependencies in a second layer

So I excluded the directory "node_modules/**" from my serverless deployment. Which means every time I install another npm package, I have to update my layer, you can automate this with a specific ".sh", but it's still cumbersome tbh.

For my serverless deployment, it becomes extremly lightweight and simple:
exclude everything, include only:

  • .nuxt/dist/server/*
  • index.js
  • prismic.config.js
  • nuxt.config.js
  • nuxt.js

The client ones are hosted on s3 thanks to the serverless-finch plugin:
bucketName: ********
distributionFolder: .nuxt/dist/client
keyPrefix: _nuxt

The result is efficient: the lambda size is around 15.7 Kb deployed.

Layers uploaded only once as my deps are not really moving:

  • The expressjs layer: 678 Kb zipped
  • My project dependencies layer: 4.7 Mb zipped

I might be writing a blog post about it here on dev.to soon.

 

Awesome article. I stumble upon one thing. My endpoint (nearby region) takes 1 second time to first byte, I am wondering if there is something in configuration that I missed in order to serve it more efficiently.

 

stuck at the part where i need to create a domain. there's like 0 explanation on this. annoying.

 

Thank you for a good article. I have a question. Is it possible to use nuxt v2 on this way?

code of conduct - report abuse