propshaft
propshaft copied to clipboard
ability to specify cache-control header in config
Ability to tell what cache-control header we want the assets loaded with
This will solve the issue https://github.com/rails/propshaft/issues/90
Solution proposed by @dhh in issue 94 :

two things here:
1. no-cache header
no-cache
works but maybe no-store
is more what we want (source)
... I don't mind either
2. this could be simpler?
I'm not sure if I didn't overkill this. Maybe something simpler would be enough eg:
# lib/propshaft/server.rb
{
#...
"cache-control" => Rails.development? ? 'no-store' : "public, max-age=31536000, immutable"
}
...let me know I can simplify it
🤔 wait a minute, now I'm re-reading @brenogazzola comment

...hmm I'm not sure about the prod but this solved the dev isuue 🤔
screen recording 📹 👇 https://user-images.githubusercontent.com/721990/210008614-65a9d72f-f621-4145-b065-22848c9bee3d.mov
Video looks a bit strange to me. The digest of application.css
did not change, which means the @include "my-custom.css"
should still be pointing to 8ffbe1
. So how did the browser know it had to fetch f4b376
after refresh?
@brenogazzola
Ok took me a while to realise what's happening:
- yes application-xxxxxxxx.css digest don't change
- yes I agree theoretically it should (as digest is calculated from content and
@import url('/my-custom.css');
is translated to@import url('/my-custom-mmmmmmm.css');
= application.css content changed so it should be application-yyyyyy.css ... but it's not!)
To see what I mean please watch https://youtu.be/cqQHyJj7few
So because browser don't cache application-xxxxxxxx.css it will load it from server every time and the next time loaded it poins to different @import url('/my-custom-nnnnnnnn.css');
=> no issue like #90
how come the digest of application-xxxxxxxx.css didn't change ? 🤷♂️ my guess is that the digest of application.css is calculated on a file content before content gets digested (before my-custom.css
turns to my-custom-nnnnnn.css
one more thing - during testing the above I've stumbled upon an edegecase:
My PR proposes the no-store header by default for Development env(therefor no such issue as #90) 👍.
If a developer switch the non-cache header to any form of cache header and then switch back to no-store again, his/her browser will be stuck at old cache.
To see this in action pls watch https://youtu.be/3nmCubctHuk
Given on cache header browser will cache the old application-xxxxx.css When I switch to no-store header browser still cache the old application-xxxxx.css Therefore it will not pick up the fact the my-custom.css has a new digest
conclusion:
- My PR works 👍
- My PR solves #90 issue in development (tat means first time users will not have that issue as Development env fixed by default) 👍
- If someone tries to test if cache works, they need to clear the browser cache or do a change in application.css (so new digest appears for application-yyyy.css) 😕
:muscle: I can confirm this fixes the problem. And yes, I had to wipe the cache locally first to get this change effective.
how come the digest of application-xxxxxxxx.css didn't change ? 🤷♂️ my guess is that the digest of application.css is calculated on a file content before content gets digested (before
my-custom.css
turns tomy-custom-nnnnnn.css
I'm a bit worried about this part. Yes, you are right, parent digest is calculated on the original content, not the one that was changed with the digest of the children imports.
This means this solution will give you a false impression that everything is working because in the development you are seeing the changes. But when you push to production, anyone who had already fetched the parent file (eg: your CDN which is sending the files to your users) will not fetch again it again, since its digest did not change and they think it's the same file.
This means that if you are using new classes that were added to the children files, your site is now broken (at least visually).
The only feasible solution I see is one that ensures that parent digest changes when children digest change
We need to fix this at the root. The no-cache setup isn't going to work for production either. Need to invalidate files when their dependencies have changed. There are several open approaches for that, so exploring those.