Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapters should add cache-control headers to static assets #3194

Open
Rich-Harris opened this issue Jan 3, 2022 · 13 comments
Open

Adapters should add cache-control headers to static assets #3194

Rich-Harris opened this issue Jan 3, 2022 · 13 comments
Labels
adapters - general Support for functionality general to all adapters feature request New feature or request
Milestone

Comments

@Rich-Harris
Copy link
Member

Describe the problem

As noted in #909 (comment), most adapters don't configure cache-control headers for the three categories of static assets — hashed (Vite output), static directory contents, and prerendered pages.

Describe the proposed solution

For hashed assets there's no real reason they shouldn't have cache-control: public, immutable, max-age=31536000.

For the contents of the static directory, it really ought to be configurable. This could be done on a per-adapter basis (e.g. there's a PR for adapter-cloudflare-workers here), but since it's a universal requirement I think it belongs in the main config. Straw man:

// svelte.config.js
export default {
  kit: {
    static: {
      // cache everything in `static` for 1 hour
      cache: 3600

      // cache large images for one hour, small images for ten minutes, don't cache anything else
      cache: ({ filename, size }) => {
        if (filename.startsWith('images') {
          return size > 1_000_000 ? 3600 : 600;
        }

        return 0;
      }
    }
  }
};

Prerendered pages should adhere to whatever the cache-control header was at the time of prerendering. For some platforms it may be difficult or impossible to set cache headers for static assets, but here we can at least cache stuff in the browser with a <meta http-equiv> tag.

Alternatives considered

No response

Importance

would make my life easier

Additional Information

No response

@bjon
Copy link
Contributor

bjon commented Jan 3, 2022

This would be great.

@bjon
Copy link
Contributor

bjon commented Jan 4, 2022

@Rich-Harris Shouldn't this return a cache-control string, instead of a max-age integer?
That way we can control everything. private, no-store, etc.

@Rich-Harris
Copy link
Member Author

Static assets are public by definition; there's no value in being able to mark them non-public. Perhaps it makes sense to expose revalidate, but what's a situation in which you would need no-store (rather than just setting max-age=0)?

Flexibility isn't always a good thing — cache-control headers can be a footgun. I'd argue it's a good thing, for example, not to expose the ability to inadvertently mark prerendered pages or static contents as immutable. For the sake of both avoiding the possibility of those bugs, and exposing a more intuitive API (nothing is simpler than a single max-age value), it's very possible that the more restrictive API is preferable. Are there real world use cases that would be prevented by that?

@Rich-Harris Rich-Harris added this to the post-1.0 milestone Apr 24, 2022
@dummdidumm dummdidumm added feature request New feature or request adapters - general Support for functionality general to all adapters labels Jan 10, 2023
@khromov
Copy link

khromov commented Jan 15, 2023

There is an edge case here if you set export const ssr = false; where a user can get a broken page view when returning to a tab that has been unloaded from memory.

Repro steps:

  1. User loads the application on his phone
  2. A new version is deployed by the developer so the JS file names change
  3. Some time passes, the tab gets unloaded from memory
  4. When the user comes back to the tab, it tries to load in again, but the HTML is not refetched, so the JS references are outdated leading to 404 and white screen of death.

I've observed this issue with sleeping tabs on both Firefox/Win11 and Chrome/Android. Browser behavior is a bit fickle especially with tab hibernation that afaik doesn't have a "standard" per se, but it could hopefully be solved by setting meta tags.
https://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/

Since I've set ssr = false for my whole application, I could add these meta tags in app.html so that they work across the whole application, but having it on a per page level would be ideal.

@itssumitrai
Copy link

Hi, any updates on this issue ? This is a real problem for production applications, no caching for static assets is just detrimental for performance.

@solvingproblemswithtechnology

I'm also interested. Browsing the internet, I found this was a thing:

function serve(path, max_age) {
. I would love to have this instead of relying on a proxy to set it.

@djdembeck
Copy link

I came here due to Lighthouse reporting this problem for fonts. I would love to see it implemented.

@fayez-nazzal
Copy link

I came here due to Lighthouse reporting this problem for fonts. I would love to see it implemented.

Same here, not having this feature impacts the lighthouse performance score negatively. It would be too lovely to see this feature implemented.

@eltigerchino
Copy link
Member

As a workaround for now, it's recommended to have your assets processed by Vite so they get cached.
https://vitejs.dev/guide/assets.html#importing-asset-as-url

For example:
src/routes/your-page/+page.svelte

<script>
  // The image and font are both cached.
  import Image1 from './your-image.jpg';
</script>

<img src={Image1} />

<style>
	@font-face {
		font-family: 'Work Sans';
		font-style: normal;
		font-weight: 600;
		/* src/routes/your-page/font.woff2 */
		src: url('./font.woff2') format('woff2');
	}
</style>

@Shekhar-Zealous
Copy link

A much required thing to solve the Caching issue on production for static assets.
What's the update on this bug, btw?

@hyunbinseo
Copy link
Contributor

hyunbinseo commented Feb 20, 2024

If the assets in the /static directory cannot be cached, why not discourage its usage?

Users are most-likely using this directory because favicon.png is included in the default template.

A root +layout.svelte file with an favicon import would be a workaround.

<!-- src/routes/+layout.svelte -->

<script>
  import favicon from '$lib/static/favicon.png';
</script>

<svelte:head>
  <link rel="icon" href={favicon} />
</svelte:head>

<slot />

It would also handle tackle these issues:

@mjdNjhNJ

This comment was marked as off-topic.

@eltigerchino

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adapters - general Support for functionality general to all adapters feature request New feature or request
Projects
None yet
Development

No branches or pull requests