Allow to pass custom headers on load responses
See original GitHub issueIs your feature request related to a problem? Please describe. This can be related to my previous issue, which is really just some details missing in the docs https://github.com/sveltejs/kit/issues/793
Despite svelte-kit
having a way to define maxage
to control caching for HTML pages, we really don’t have a way of setting any other headers. The more common use cases are there: redirect and basic caching. But I feel like we need more control. On Next.js you can use the context
object and use setHeader
. Here on svelte-kit
you can’t even use the context
because that’s for layout only, so I need to resort to “hacky” solutions to get what I need.
My basic use case is to use s-maxage
instead of maxage
. I don’t want to cache HTML pages on the client because JS and CSS hashes change between deploys, and if a user with an HTML page from a previous deploy refreshes the page (without clearing cache), the user gets an unstyled and unscripted page. Browsers make a request even if the assets are cached, but the 404 produced by the CDN (in this case, Vercel), results in those unstyled and unscripted pages. The only way around this is to probably use service workers and cache assets with it, but I want to avoid that.
I feel like a headers
prop is just something that sooner or later will become handy, the same way it is on endpoints.
Describe the solution you’d like
Just allow us to specify the headers
on a load
response, just like on endpoints:
export const load = async ({ fetch }) => {
const res = await fetch("/apistuff.json");
if (res.ok) {
const data = await res.json();
return {
props: {
data
},
headers: {
"cache-control": "public, s-maxage=3600"
}
};
}
return {
error: new Error("error during fetch")
};
};
Describe alternatives you’ve considered I’ve read about hooks and managed to work around this by doing:
import type { Handle } from "@sveltejs/kit";
/**
* Replace all max-age cache controls with s-maxage
*/
export const handle: Handle = async (request, render) => {
const response = await render(request);
if (!response) return response;
const cacheControlHeader = response?.headers?.["cache-control"];
if (cacheControlHeader) {
response.headers["cache-control"] = cacheControlHeader.replace("max-age", "s-maxage");
}
return {
...response
};
};
Not that pretty honestly, but works for me. This replaces all maxage
usages with s-maxage
which is something I’m 100% ok with, but just for this project. But this just fixes the issue for this project and this scenario, if someone wants to pass another random header, no dice.
I also tried using the context
object to pass in headers during the load
function and then apply them on handle
, but you can’t modify the context
from page load
functions. So that was a no-go from the start.
How important is this feature to you?
Very. Working with these recent CDN providers like Vercel, Netlify, and even Cloudflare is amazing, and being able to use s-maxage
to avoid running cloud functions over and over again is just what I need, especially as I do a ton of work with local non-profits that really want to keep costs to a minimum.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:12 (9 by maintainers)
Top GitHub Comments
To clarify,
status
andmaxage
are not ignored in the client.status
provides the status code for the subsequent error page, andmaxage
causes the result of runningload
to be cached in memory for the appropriate length of timeWe talked about this in today’s maintainer’s meeting. Folks thought it made sense to support it on individual pages. Won’t add it to layouts yet since you can use handle, other options are configured only at leaf level, and there’s not a clear use case for adding it to layouts at the moment.