Next.js Serverless App. How to work with multiple stages and custom environments
In this article I would like to show you, how to build and deploy your Next.js App on AWS using @sls-next/serverless-component. Currently there are not a lot of examples or documentation to do this, so I put some effort to read up on it.
At this point I assume you have already initialized Next.js project. If not please follow this getting started documentation.
Default Next.js environment:
Next.js has built-in support for loading environment variables from .env files.
Next.js allows you to set defaults in .env
(all environments), .env.development
(development environment), and .env.production
(production environment).
.env.local
always overrides the defaults set.
Our new environment set up:
In our scenario we will only use .env which will be located in the root of our project and it will hold the environment variables that will be used in all stages.
So, create .env file and add you shared environment variables in there. Next we will create new file directory in the root level of the project which will hold configuration settings for each stage. Lets name it “environment”
Your file structure should look something like this:
Next we should set up scripts in our package.json for building and starting the app locally.
In order to load the right environment we will use env-cmd (you can also use dotenv-cli).
Add these scripts to you packag.json:
So, if we want to make a production build with staging environment, we should run npm run build:staging. This will take all environment variables from .env and all environment variables from environment/staging/.env.staging and it will merge them.
So the up is built with staging environment. At this point you can start it locally with command: next start (check if it is working :) ).
Deploying the App to AWS Lambda@Edge
As mentioned above we will use @sls-next/serverless-component to deploy our app on AWS. This will create Cloudfront distribution , S3 bucket and the app will run on Lambda@Edge.
As you can see on the file structure above, in each of the environments we have separate serverless.yml file. So when you deploy in particular stage it will use that file. .serverless directory will be created there.
Here is how it should look like. Lets go with staging environment:
The good thing using @sls-next/serverless-component is that there is zero configuration by default. You can just go with
my-app:
component: "@sls-next/serverless-component@version"
But anyway. The only thing you should pay attention to, is nextConfigDir which points to the root of the code where .next is located and where .serverless-nextjs will be created after deploy.
The settings in the serverless.yml file above are good to go, it will use the default configuration. But you can always add custom inputs as needed.
Check for all custom configuration inputs here.
Lets add scrips for deployment in package.json. This are all scripts needed for this article:
In order to deploy your app, you will need to build it first with the right environment, then navigate where that particular stage serverless.yml file is located and run only “sls”.
When running the sls command serverless creates its own environment, thats why in order to have the custom stage environment variables you need to pass them to serverless again.
Also as said above serverless creates .serverless directory. If you delete this directory and try deploy it again, this will create new Cloudfront distribution. So have this in mind.
Serverless next.js is regionless. By design, serverless-next.js
applications will be deployed across the globe to every CloudFront edge location. The lambda might look like is only deployed to us-east-1
but behind the scenes, it is replicated to every other region.
With this approach you can work with stages, but it is not good for CI/CD.
I hope you find this article useful.
Cheers :)