Going completely serverless with Nextjs and Terraform
Tags: javascript, serverless, react, devops
Published: 2019-06-26 11:55:21

If you work in a company where they have serverless infrastructure, you might be interested in this little story.

We went live with an eCommerce website that runs on the cloud infrastructure, the website too.

## Why?

SEO for my customer is important as it is for many websites out there. When we launched the first version of the website ([SPA](https://en.wikipedia.org/wiki/Single-page_application)), we had to put in place redirects, metadata, title, descriptions, etc. After some weeks from our launch, we noticed that on google the new pages were not correctly indexed. We believed that googlebot was able execute JavaScript and to understand asynchronous code, but no. Or at least it was not working as we expected.

That's when we decided to refactor the existing application and use [Nextjs](https://nextjs.org/). It offers SSR, which was what we wanted. 

## Deployment

After a few days, I started to evaluate the how deploy in production the new website. As old school, I could have set up a web server and return the requested HTML. Although this doesn't work well on a serverless for several reasons. Especially with Nextjs.

Nextjs, recently release a fantastic feature that allows us to export page files that can be used directly on a [serverless environment](https://nextjs.org/blog/next-8#serverless-nextjs)! Although, there's a catch: these files cannot be thrown straight away into your cloud provider! Here, you don't have much documentation on how to proceed.

That's when me and my fellow colleague from DevOps decided to use Terraform (instead of CloudFormation) to create our serverless resources. Yes, my client uses AWS as cloud provider.

I did explore different solutions. [Serverless framework](https://serverless.com/) was one of them. Unfortunately this doesn't play well with the quantity of pages we have. After a rough estimation, we found out that we needed more or less 10 resources for each page, for a total of almost 300 resources that would be modified/destroyed/created at each deployment! The cost of these was huge (money and time wise).

## Integration

[Terraform](https://www.terraform.io/) was our way to go. At that point I did start creating a script that would interface Nextjs and Terraform. 

As I said earlier, there are not much examples of how to integrate Nextjs serverless build with existing cloud providers. The example that there are at the moment use only [now](https://zeit.co/now), which is a property software.

After some days of working side by side with my fellow teammate, I ended up having a robust (not fantastic, as there's still room for improvement) build script that was wired among these tools and it was able to give Terraform the resources needed to deploy all the lambdas to AWS!

## Open Source

I decided to open source the project and make it a library the could be potentially used with every cloud provided supported by Terraform.

[**Terraform Nextjs plugin**](https://github.com/ematipico/terraform-nextjs-plugin)

## How to use it

Just create a file `build.js` and let's put inside this code:


```js
const generateResources = require('@ematipico/terraform-next-plugin');
const routes = {
  prefix: '',
  mappings: [
    { page: '/contactUs', route: '/contact-us'},
    { page: '/aboutUs', route: '/about-us'},
    { page: '/product', route: '/products/:product', params: {
       hideComments: false // <= it tells Terraform that this is not mandatory as query string param
    }}
  ]
};
generateResources({
  gatewayKey: 'MyAwesomeProject',
  lambdaPath: '../../ui-project',
  provider: 'AWS',
  routes
}, true) // <= write configuration on disk
```

This snipped will generate two files that should be given to Terraform: `gateway.terraform.tf.json` and `lambdas.terraform.tf.json`.

*You should run the `build.js` script after you run the `next build` command*.

The reason why they have the `tf` inside their name is because Terraform is able to detect, validate and plan them as its own configuration. You can read more about it [here](https://www.terraform.io/docs/configuration/syntax-json.html).

Of course, you still need a main Terraform configuration file in order to deploy everything. So there's still some DevOps work to do. Potentially it could be covered by this library but it depends on the consumer needs.

You can check a small example in the [integration test](https://github.com/ematipico/terraform-nextjs-plugin/blob/master/integration/aws/api.tf).

The library is now in constant development to make sure that it covers much of the requirements out there!