remix icon indicating copy to clipboard operation
remix copied to clipboard

[Cloudflare Pages] Static assets in public directory are served via functions

Open inssein opened this issue 2 years ago • 1 comments

What version of Remix are you using?

v1.7.5

Steps to Reproduce

  1. Create a new Cloudflare project
  2. Drop a static asset in the public directory (favicon, images, whatever)
  3. Deploy the site
  4. Notice that any request to static assets responds with the cache header cf-cache-status of EXPIRED. All assets in build respond with a cf-cache-status of HIT.

This impacts a couple of things:

  1. Billing (static assets are free)
  2. The response back to the user is not cached for as long as a static asset.

Expected Behavior

All assets should be served statically (not via a function).

Actual Behavior

All assets in public (not in public/build) are served via a function.

inssein avatar Nov 10 '22 20:11 inssein

For a quick win in my own project, I have modified my _routes.json (inside public) to exclude certain extensions, which seems to be working for now.

Example:

{
  "version": 1,
  "include": [
    "/*"
  ],
  "exclude": [
    "/build/*",
    "/*.png",
    "/*.svg",
    "/*.webp",
    "/*.ico"
  ]
}

I tried to see if I could fix this and submit a PR, but I am not sure there is a way to resolve this. Attempting to "exclude": "/*" doesn't run functions at all.

Happy to adjust the readme of the Cloudflare template or if someone else can think of any solutions, I don't mind implementing them.

inssein avatar Nov 10 '22 20:11 inssein

If you place images under a subfolder in public, you can then add this to the include without relying on extensions which seems a bit flakey to me.

This won't catch assets that you want to serve at the root of course, like favicons.

tom-sherman avatar Dec 30 '22 23:12 tom-sherman

@tom-sherman was just taking another look at this and while your idea works, your favicon will still be loaded via the function.

inssein avatar Feb 08 '23 18:02 inssein

You could probably use a redirect for those.

tom-sherman avatar Feb 08 '23 18:02 tom-sherman

The problem for me isn't serving the asset via the worker, but it counts towards your bill and it's not cached the same.

Edit: Ah wait I think you meant https://developers.cloudflare.com/pages/platform/redirects/, which would make sense.

inssein avatar Feb 08 '23 18:02 inssein

Things outside the public/build directory aren't really our responsibility. The CF Pages template gives you direct access to public/_routes.json and public/_headers which are the levers you need to adjust caching behavior for anything else you might add to public. For us to assume caching behavior for any other random thing you drop into public would be assuming too much, and would inevitably lead to a conflict in the future when someone wants to disable that behavior.

Closing this as I don't think there is anything for us to do here.

mjackson avatar Aug 24 '23 00:08 mjackson

@inssein following up in case it's helpful since I also ran into this. I'm surprised that this applies to static assets needed for the app as well, not just files you add to public. I totally get the argument that a rule for anything that ends up in /assets could be troublesome, but this default behavior is not great for prod, maybe a doc would clear this up on the remix side

Here's what I did since I don't have any other assets I care about with my app.

in public/_headers

/assets/*
  Cache-Control: public, max-age=31536000, immutable

Those are the same value that remix-serve uses when i start a remix app in prod mode locally, and that file gets moved over during the build step

jeremypress avatar May 04 '24 22:05 jeremypress