AWS CloudFront + Svelte

No fancy clever title this time, just a simple explanation on how to deploy a statically generated site with Svelte(Kit) to AWS CloudFront.

First off let me state that I quite like Svelte. I looked initially into Nuxt.js and to be honest it all felt like you had to configure it correctly and it was nebulous at the very least in how everything worked. I could not easily within moments see where the routes came from for example.

Svelte is just HTML, CSS and JavaScript separated like it was the 90s but combined in a sense of project management wise. Grouping things together that are meant to be together. Then you can just import from a lib folder and the same goes for icons and assets. It all just flows quite nicely and is easily managed.

Setup

Simple setup is just create an S3 Bucket with static hosting enabled and create a CloudFront distribution. I then also created a Legacy Origin Access Identity and Bucket Access Policy.

All that can be gleaned from tutorials as well to do it on a modern way. That is all fine.

Sync build

Then just build your Svelte app with npm run build and sync the contents of the build dir with your S3 bucket.

One function

All that is needed to make it all work, one CloudFront function. Create your function and name it what you wish then the following content will fix your problems:

async function handler(event) {
    const request = event.request;
    const uri = request.uri;
  
    if (uri.endsWith("/")) {
        request.uri.replace(/\/$/, ".html");
    } else if(uri.indexOf(".") < 0) {
        request.uri += ".html";
    }
  
    return request;
}

Deploy and associate that with a Viewer Request of your distribution that serves Svelte.

That is it. All that functions does is replace the last / with a .html to make urls like /config/base/ load the correct file by making it into /config/base.html in the S3 bucket. Then it does also check if the request contains a . as in any CSS or JavaScript file, or even fonts or icons or what have you.

Then if it does not, urls like /config/base will be made into /config/base.html to load the correct file again.

Why no Lambda@Edge

With Lambda@Edge you get more options, but all we need to do is a simple request path change and you have that access within CloudFront functions. With that, it is also cheaper, as well as easier to setup and maintain. If you do a Lambda@Edge then you need to setup the IAM roles correctly otherwise the distribution cannot execute the function. Then if you want to delete or change the function it consists of more steps and complications then the CloudFront functions.