Search code examples
next.jslambdahostingserver-side-renderingstatic-site

NextJS SST Static pages problem: Why static page get "Miss from CloudFront"?


I'm testing NextJS hosting with SST, so I deploy a simple nextJS app that only renders this static page:

// src/pages/index.tsx
function Home() {
  return <h1>Hello</h1>;
}

export default Home;

Here is the Stack Code:

import { SSTConfig } from "sst";
import { NextjsSite } from "sst/constructs";

export default {
  config(_input) {
    return {
      name: "test-next",
      region: "sa-east-1",
    };
  },
  stacks(app) {
    app.stack(function Site({ stack }) {
      const site = new NextjsSite(stack, "site");

      stack.addOutputs({
        SiteUrl: site.url,
      });
    });
  },
} satisfies SSTConfig;

Everything is working perfectly, but one thing I notice is that all page response headers get the header X-Cache as Miss from Cloudfront. Another strange thing is that all requests to the CloudFront URL hit the lambda function that server-side renders the NextJS pages, I know that because of the cloud watch Log group named siteServerFunction that logs an invocation each time I request is made.

The problem is that this page doesn't use SSR, it is a page that should be generated at compile time, be served by s3, and cached by CloudFront. So, what is happening? Does SST support don't static site generation?


Solution

  • So this is likely just a bit of confusion. I have the exact same setup on https://campaign.tools. It's also a Next.js site deployed through SST as a StaticSite.

    Let me help you understand the process that's going on...

    When SST makes a StaticSite it automatically configures the CloudFront distribution caching. These settings can be manually overridden with assets.fileOptions in the StaticSite configuration object, but they default to a reasonable behavior. The documentation explains that the default behavior is to cache all JS/CSS files and not cache HTML files:

    assets.fileOptions?

    Type: Array

    Default: No cache control for HTML files, and a 1 year cache control for JS/CSS files.

    With that said, you're getting cache misses from CloudFront, or at least it seems that way. For the JS and CSS files, that is fine since these files are being cached on your client. If you look at the JS/CSS files, you will see the following headers:

    X-Cache:         Miss from cloudfront
    

    That seems like we're not getting any CloudFront cache hits; however, if you look at the Status Code in the General section, I expect you would find the following:

    Status Code:     200 OK (from disk cache)
    

    If that's the case, it means it was a miss on the first call your client made to CloudFront, but it then cached that request in the browser, due to the Cache-Control header. You should see the following value for that header:

    Cache-Control:   max-age=31536000,public,immutable
    

    If this is the case, then your client is simply caching that first "miss" from CloudFront, and it looks like you're constantly failing to hit the cache. If you want to, click Disable cache in the network tab of your client and reload the site. You should now start to see cache hits! But don't worry, it was always cached :D

    I know this because I battled with the same thing when setting up my site. Please let me know if toggling the Disable cache doesn't help, since that might indicate you have other issues.