Useful Snippets

Welcome!


This blog is used to collect useful snippets related to Linux, PHP, MySQL and more. Feel free to post comments with improvements or questions!

Are your smart devices spying on you? Make better purchasing choices and find products that respect your privacy at Unwanted.cloud

RSS Latest posts from my personal blog


Most viewed posts


Subscribe to RSS feed


Fixing infinite redirect loops in SvelteKit applications

Stanislav KhromovStanislav Khromov

I was debugging a strange problem recently in our SvelteKit application – users would get stuck in a state where the page kept refreshing itself over and over in a loop. Closing the browser and/or clearing the cache was the only way to fix the problem.

After some time I finally managed to reproduce the issue. It turns out that this happens after you deploy a new version of your application while a user has an old version open in their browser.

When you deploy a new version all of your asset paths (CSS & JavaScript) will change due to the way Vite and Rollup work. The file names of bundled assets have a unique hash in their names that represent the content of the file.

If a user has the old version open and tries to navigate to a new page this will trigger a client side navigation that usually requires the loading of new JavaScript assets from the server. But since you deployed a new version the old assets are no longer present and will return a 404 error. There is a built in functionality in SvelteKit where it will detect that the asset failed to load and perform a hard refresh of the page.

This is where our issue start. If the HTML response of the page itself is cached in the browser, it will still refer to the now-old asset paths that no longer exist. This triggers a refresh of the page, and the loop has started.

This happens when we don’t pass any cache headers from our application to the browser. The browser will the pick an arbitrary time to cache our content. This is usually not desired behavior.

The solution

We need to set an explicit no-cache header for responses to HTML files coming from your app. You can do this for most adapters in hooks.server.ts using this code:

import type { Handle } from '@sveltejs/kit';

export const handle = (async ({ event, resolve }) => {
  const response = await resolve(event);
  response.headers.set('cache-control', 'no-cache');
  return response;
}) satisfies Handle;

In addition to this, we also need to make sure that our +layout.ts in src/routes file contains the following line:

export const prerender = false;

This is because SvelteKit by default will attempt to prerender the routes and if they are prerendered then they will be considered completely static and won’t even run through our hooks.server.ts logic! This is documented but somewhat odd behavior in the context of adapter-node.

Web Developer at Aftonbladet (Schibsted Media Group)
Any opinions on this blog are my own and do not reflect the views of my employer.
LinkedIn
Twitter
WordPress.org Profile
Visit my other blog

Comments 0
There are currently no comments.