skip to Main Content

I have a Next.js single page app that uses static paths. If I run it locally, I can navigate to a path, refresh a page and it would work. It also works if I expose the site straight from an AWS S3 distribution. However, when the site is served via AWS CloudFront, the path wouldn’t work. It gives 404 when I type any path except for the root.

I tried playing around with different properties (cache control, redirect rooles) but nothing helped.

Q: How to make CloudFrtont distribution work with Next.js static routes?

Here is my CloudFrtont configuration:

resource "aws_cloudfront_distribution" "s3_distribution_production" {
  origin {
    domain_name = aws_s3_bucket.production_webiste_s3.bucket_regional_domain_name
    origin_id   = aws_s3_bucket.production_webiste_s3.id

    s3_origin_config {
      origin_access_identity = ""
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"

  aliases = ["mycoolwebsite.io"]

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = aws_s3_bucket.production_webiste_s3.id

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 120
    max_ttl                = 300
  }

  viewer_certificate {
    acm_certificate_arn = aws_acm_certificate.multi_domain_cert.arn
    ssl_support_method  = "sni-only"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  custom_error_response {
    error_code         = 404
    response_code      = 404
    response_page_path = "/404.html"
    error_caching_min_ttl = 300
  }
}

Thank you. I would appreciate any suggestions.

2

Answers


  1. If you need every URI to reroute to the root index.html (for a single page application), or need index.html routing at both the root directory and all subdirectories when a file extension is not provided, you can set this up using CloudFront Functions (JavaScript function that runs ahead of each of your requests) in the CloudFront console. You can use to rewrite the request URI on each incoming request.

    Steps:

    • Create and publish a function (example below)
    • Use the viewer request hook (the function will rewrite the URI before the request is forwarded to S3)
    • Associate it with your distribution at each of the cache behaviors

    Here is an example that appends index.html to every request without a file extension – https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/url-rewrite-single-page-apps

    From a cost perspective, CloudFront provides 1TB of data transfer, 10M requests, and and 2M CloudFront Function invocations per month. In most cases this will make CloudFront (and this URI rewrite) free.

    Why is the default root object setting not working?
    The default root object setting only works for the root, so a request to / will load /index.html, but a request to /about will not load /about/index.html

    Login or Signup to reply.
  2. To add to Christian’s answer (I would say he has answered the question correctly so maybe accept his answer):

    Usually SPAs are almost static content. You need some tiny web backend code to perform these tasks:

    • Serving the default document
    • Setting response headers for security and performance, which can be dynamic in some cases

    So it can be a good idea to have a mechanism in place to enable backend logic.

    Here is an example of mine. I preferred to use a code approach though some of it might be possible via AWS config settings. I include it in case stuff like the content security policy is useful to you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search