-
Notifications
You must be signed in to change notification settings - Fork 103
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
feat: getHashedStaticPath
, append hashes to URLs for cache busting
#431
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand things correctly, you're building an unbounded Map
of hashes to resolved file paths?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Offhand, do you know why folks seem to go for URLs like /assets/index-deadbeef.css
instead of /assets/index.css?hash=deadbeef
? The latter seems like it'd be a bit easier to work with, since the unhashed and hashed paths would be the same.
await server.register(fastifyStatic, { | ||
root: new URL('./public', import.meta.url).pathname, | ||
prefix: '/assets/', | ||
hash: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to be annoying about names, this is take-it-or-leave-it feedback, but just reading this code without reading the readme, I feel like the option hash: true
could mean a variety of different things. I'd probably guess it means "
"add an e-tag
header", not that it allows fancy path building for CDN busting hashes.
I am seeing this PR in my notifications for days and did not comment on it, because I first did not understand the purpose. Also because I was not requested as reviewer I did not invest time to understand it. But I think that I get it now, despite not knowing what the current state of this PR is. So if you implemented it somehow and I claim something wrong, then dont get sad, because I did not read the code. Somehow I think i saw this technique like 15 years ago, where we did this in php. So basically you reference a file by a hash and expose it via html or so. The browser caches the file very long reducing loading the file again and again. I guess comparable with webpacks bundled files, where it is adding a hash to the filename. Which is actually better than just having a hash, as you still can now what file you are loading. Actually I think this is a neat function, but it is problematic at startup as it has potentially to hash alot of files for potential nothing? If I would implement it, I would write it in a way, that the call to getHashedPath will result in a hashing of the specified file and store it in a lookup or how you implement it. But the issue here is, that you would need to hash the necessary file at server start. Like I said already, I did not read your code, but this is what I think... |
Thanks for the input, @Uzlopak Yeah, I didn't request a review because I know you're busy improving node and undici these days, didn't want to prevent you from doing that ;) And I do apologize for this PR's slow and constantly pingy state, I didn't handle it in the best way since it started with an aha moment 🤣 The premise is very simple: we want to use a very long However, when we modify files, we want that to be reflected and so we append a hash to them (like what other tools do) Because the startup time will increase when this feature is used, I tried adding a way to pregenerate the hashes (which is what took a little while to implement in an acceptable way and kept pinging the watchers) Anyway, I'm doing a few more touches and the PR will be fully ready for review, then I was thinking of requesting one from you as well |
If we don't modify anything, it is actually doable and it LGTM honestly PTAL |
hash
, generate hashed routes for each asset
Applied all your suggestions except changing the name of the option ( |
hash
, generate hashed routes for each assetgetHashedAsset
, append hashes to URLs for cache busting
getHashedAsset
, append hashes to URLs for cache bustinggetHashedStaticPath
, append hashes to URLs for cache busting
@mcollina now incremental adoption is possible as assets are both referenceable by their original paths and with their hash using the decorated method |
Ah I remembered one reason why folks put the hash in the filename instead of as a query param: it convinces CDNs that the resources really are different, as some of them are configured by default to ignore query strings. Cloudflare by default respects the query string, but I can imagine some folks use UTM params and whatnot that they really do want ignored from a caching perspective. Not sure exactly what that means we should do. What do webpack / vite do by default? https://developers.cloudflare.com/cache/how-to/set-caching-levels/ |
Yeah, but normally this should indeed bust the cache in terms of standards behavior:
The URI includes the query parameter, so it should be fine in modern browsers The added benefit of doing it this way is that we can incrementally adopt this option because the URLs of the assets stay the same, just the hashed versions returned by the decorated function are different |
I released https://github.com/gurgunday/hasset, which scans the assets folder and auto replaces the occurrences of the files with their hashed versions I no longer see a raison d'etre for this PR, feel free to continue the work if interested |
That's very close to the path I recommended you to take :). |
This in my opinion can be a killer feature — it essentially lets the user set a very high
maxAge
by decorating the Fastify instance with a method that returns the file's path plus a unique hash that identifies its contentIf an asset's content changes, it will still be referenceable via the same relative path while the client will see a new hash, which means the cache will bust