serverless-nextjs / serverless-next.js

⚡ Deploy your Next.js apps on AWS Lambda@Edge via Serverless Components
MIT License
4.47k stars 456 forks source link

RFC - Static Generation / SSG Improvements #355

Closed danielcondemarin closed 4 years ago

danielcondemarin commented 4 years ago

Problem

Next.js recently released a new API designed to improve Static Site Generation. More details can be found in https://github.com/zeit/next.js/issues/9524.

serverless-next.js is not currently compatible with the new Next.js API and this RFC proposes changes to support these features.

Proposal

getStaticProps.

For pages that declares getStaticProps, Next.js generates a JSON file that holds the return value of executing getStaticProps. The file is used for client-side routing.

All JSON files for a given build can be found in .next/prerender-manifest.json. serverless-next.js will lookup the files and upload them to S3 so they can be fetch-ed from the browser. Also, a new cache behaviour will be created in CloudFront for the path pattern /_next/data/*. This will match any requests made to the JSON files and forward them to S3.

getStaticPaths

When you have a dynamic route you can add a method called getStaticPaths to the page. The way it works is Next.js generates a fallback HTML page that can be served when the route has not been pre-rendered on a previous request.

If the path is returned in getStaticPaths then is pre-rendered at build time. If is not pre-rendered at build time then it needs to be compiled server side in the background the first time the route is visited.

Here is a diagram to illustrate how this will work in serverless-next.js (fallback: true):

Serverless SSG Improvements - GetStaticPaths Fallback_ true

You can also set fallback: false. In this case a 404 is returned instead of pre-rendering:

Serverless SSG Improvements - GetStaticPaths Fallback_ false

getServerProps

getServerProps behaves similarly to getInitialProps. The difference is that on client side transitions, Next.js makes an api request to the server to run getServerProps and uses that to render the page client side. In serverless-next.js this will be handled in the origin-request edge function as illustrated below:

Serverless SSG Improvements - GetServerSideProps

Preview mode

Preview mode enables you to preview the "draft" of a page at request time rather than build time. Next.js achieves this by always calling getStaticProps on the page at request time whenever preview mode is enabled. Details of how to enable preview mode and use it can be found in https://nextjs.org/docs/advanced-features/preview-mode.

In serverless-next.js this will be handled in the origin-request edge function as illustrated below:

Serverless SSG Improvements - Preview Mode

janus-reith commented 4 years ago

I wonder what I'm missing here - A separate lambda invocation makes sense, but why would SQS, or anything else on top be necessary? Couldn't the first Lambda just invoke the second lambda with InvocationType Event and not await its result?

danielcondemarin commented 4 years ago

I wonder what I'm missing here - A separate lambda invocation makes sense, but why would SQS, or anything else on top be necessary? Couldn't the first Lambda just invoke the second lambda with InvocationType Event and not await its result?

You're right @janus-reith. That removes the need for SQS even though I think AWS still uses a queue behind the scenes for async invocations, but if is abstracting it away from us that's best!

My only remaining concern would be latency between regions, say that a user is in us-east-1 and hits one of the edge functions in that region, when invoking the other lambda for background page regeneration what latency are we expected to see? I realise that it won't need to wait for the regeneration lambda to process but the request itself to put the event in the queue what region is that happening and how do we know is not going to a queue somewhere in eu-*. My initial guess would be the queue AWS uses behind the scenes would be colocated in the same region as the async lambda but I'm not sure of that.

danielcondemarin commented 4 years ago

Since all of the features in the RFC have now been implemented will close this and we can open a separate issue for revalidate.

Talhafayyaz11 commented 3 years ago

https://github.com/serverless-nextjs/serverless-next.js/issues/1317