Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve static generated pages via CDN with Next.js

I'm trying to use Next.js (9.5.2) for both Server Side Rendering and Static Site Generation. SSR works fine for me with assetPrefix. I am able to host all my static assets on CloudFront. However, I'm not sure what the best way is to host the static pages.

I am facing 2 issues.

  1. assetPrefix is not applied to SSG pages. so the link to JS/CSS will be something like this <link rel="preload" href="/_next/static/css/styles.31b6de8d.chunk.css" as="style"/>
  2. Assume we host generated HTML on CDN and we are able to serve assets with assetPrefix, how do I use Next.js Incremental Static Regeneration with fallback: true in getStaticPath. My understanding is that page will generated on the server side if the corresponding HTML is not found.

Thanks everyone for helping.

like image 745
Andrew Zheng Avatar asked Aug 17 '20 22:08

Andrew Zheng


People also ask

Does Next.js have support for static CDN?

Can I use a CDN for static assets? Yes! When you deploy your Next. js application to Vercel, your static assets are automatically detected and served by the Edge Network.

Is Next.js good for static sites?

Next. js is a server-side rendering (SSR) tool, but with version 9.3, it also supports static site generation. The idea behind it is to create server-rendered React apps that require minimal to no configuration.

Is Next.js dynamic or static?

Next.js has two forms of pre-rendering: Static Generation and Server-side Rendering. The difference is in when it generates the HTML for a page. Static Generation (Recommended): The HTML is generated at build time and will be reused on each request.

Which method is used in Next.js for statically generating dynamic routes?

The companion life-cycle method getStaticPaths of getStaticProps lets us use the data we have at build-time to specify which dynamic routes (like /pages/blog/[slug] ) we want to generate statically.


1 Answers

I have partial answers to my own question.

For issue 1:

The issue is my own fault. assetPrefix worked with SSR but not for SSG because I didn't pass in environmental variables properly. In my situation, we have 2 different CDN URLs for production and staging. So I have something like the following in next.config.js. Because MY_ENV is passed in from PM2, which starts my app, it is guaranteed that MY_ENV will always be available when Next.js needs to access next.config.js.

// next.config.js
const isProd = process.env.MY_ENV === 'production';
const isStaging = process.env.MY_ENV === 'staging';
const isDevelopment = process.env.MY_ENV === 'development';

if (isProd) {
  assetPrefix = 'https://mycdn.cloudfront.net/';
} else if (isStaging) {
  assetPrefix = 'https://mycdn.cloudfront.net/staging';
}

However, when I run next build for static pages, the build step doesn't use PM2 thus MY_ENV is not available. To make it work, I need to run the build twice with different variables.

"build": "npm-run-all --parallel build:production build:staging",
"build:production": "MY_ENV=production next build",
"build:staging": "MY_ENV=staging next build",

For issue 2:

If I'm able to pre-generate all static pages. I can just put everything on CDN and they will work.

In my situation, ISR is a better fit. The way I get ISR to work is to ask the server to return the HTML for every request instead of hosting on the CDN. Since all other assets are hosted on the CDN, the performance is still pretty good and this solution works out well for my situation.

If you are like me who struggled a bit on this issue, I hope my answer helps you out.

like image 54
Andrew Zheng Avatar answered Sep 28 '22 22:09

Andrew Zheng