milliHQ / terraform-aws-next-js

Terraform module for building and deploying Next.js apps to AWS. Supports SSR (Lambda), Static (S3) and API (Lambda) pages.
https://registry.terraform.io/modules/milliHQ/next-js/aws
Apache License 2.0
1.46k stars 152 forks source link

[Question] How to separate frontend build from Infra build #260

Closed sumantapakira closed 2 years ago

sumantapakira commented 2 years ago

In our current React project (deployed on S3 static site hosting + Cloudfront) we are having two separate independent Jenkins pipelines, one pipeline builds React front code which triggers frequently, and another pipeline that builds Infrastructure changes such as the deployment of Lambda/API gateway/S3 etc

I am trying to find out how is it possible to have two separate independent Jenkins builds for NextJS Server-Side rendering. One build will deploy only NextJS static resources and another build will deploy Lambda/API gateway/S3 etc

So for this, I am following these steps-

  1. yarn tf-next
  2. terraform init/plan/apply which deploys Nextjs app correctly
  3. Now I make some changes to the css/js file and execute next build
  4. After I upload manually to S3 (This I am thinking to automate via Jenkins build)

But it does reflect the change. So is it possible to create two different Jenkins pipelines?

ofhouse commented 2 years ago

Hmm, don't see a possible solution since this is limited by Next.js itself. When building a Next.js project it creates a client (frontend) and a backend (SSR) build and both share their information about which files are available in the build.

Bringing together a client and a backend from two different builds would result in an SSR generated page HTML page that links to the wrong frontend assets (e.g. JavaScript files).

What you try to achieve reminds me of the module federation concept, but never tested it if it is worth the expense: https://javascript.plainenglish.io/next-js-11-module-federation-and-ssr-a-whole-new-world-6da7641a25b4

sumantapakira commented 2 years ago

Many thanks for clarifying this. I am reading the blog here and its written as

This is a major key where our architecture is different from the serverless-next.js component: Serverless uses these Lambda@Edge functions to generate the SSR content while we only use it to determine from which origin the content should be served.

Could you please explain in more detail with an example?

ofhouse commented 2 years ago

Could you please explain in more detail with an example?

At the time when I wrote the article the serverless Next.js plugin only created a single Lambda@Edge function that provided all server-side rendered features. Lambda@Edge as the name suggests runs at the edge nodes of CloudFront, so when you make a request to the site, AWS clones the Lambda to the edge location close to the viewer and runs the server from there. However Lambda@Edge was never designed to run a full server on it. It was meant for modifying Requests and Responses from or to CloudFront and so there are some limitations compared to a normal Lambda, that makes it more obvious:

E.g. when you want to create multiple stages (dev, testing, prod) of your app, you have to rebuild your app for every stage, since the environment variables have to be built into the code.

Because we don't want to loose the performance of Lambda@Edge when making requests to static pages (that are prerendered and don't need SSR), we splitted the routing part and the SSR part. So the routing (aka proxy) takes place at Lambda@Edge, where it decides if a request can be served directly from S3 or needs to be forwarded to Lambda. If the route is served by Lambda the request gets forwarded to API-Gateway that invokes a Lambda to serve the request from there.