bminer / node-static-asset

Static asset manager for Node.JS and Express
MIT License
48 stars 13 forks source link

it is possible to assetFingerprint() URLs matching a particular pattern without rewriting templates? #15

Closed mikemaccana closed 9 years ago

mikemaccana commented 9 years ago

Sorry if the answer's obvious, but I wasn't sure from reading the docs.

Eg, all my images are underneath /images. I'd like to fingerprint all of them, without having to rewrite all my templates to use the view helpers.

Would making all non-fingerprinted URLs redirect to the fingerprinted version work?

Thanks!

bminer commented 9 years ago

Good question, but sadly, no. The way that static-asset works is by looking at req.url and determining if that request already has a fingerprint. Therefore, the users' web browsers (or user agent) needs to know the URL for the asset in advance.

For example, /images/button.jpg. If the user issues a request to /images/button.jpg, then the resource is served without caching. However, you need the request to be something like /images/button.jpg?v=89df8d8af Then, you can send special caching headers to the browser so that the browser will never request that image again. And, finally, if you happen to change /images/button.jpg in the future, the browser will know to GET /images/button.jpg?v=34829fda, which is technically a different asset.

So, in short, your templates need to know the fingerprinted URL, so that the rendered HTML contains <img> tags that point to fingerprinted URLs.

You can do a couple things to work around this:

Anyway, hope that helps. I'd recommend this article for more info: https://developers.google.com/speed/docs/best-practices/caching

mikemaccana commented 9 years ago

Thanks for answering Blake! I understand what you're saying, but what if:

Would that work?

bminer commented 9 years ago

This defeats the purpose of strong caching, which is to tell the browser not to bother with an HTTP request at all for a given resource. If a GET request for /images/button.jpg results in a 302, then the browser will still continue to request /images/button.jpg. Granted, if the 302 request points to a strongly cached resource, the browser won't bother with an HTTP request for it directly, but... now you essentially have 2 HTTP requests for a resource when it's not in the cache and 1 request when it's in the cache. What we want is 1 HTTP request for a resource, at most and 0 requests if we can help it. Most of the usefulness of node-static-asset is that it provides view templates with the URL fingerprint of a resource so that strong caching headers can be used, allowing browsers and other user agents to cache resources (for up to 1 year) without issuing another HTTP request. When you think about, that can save your server a considerable amount of bandwidth. Even an HTTP request that responds with 304 is fairly expensive (at a large scale), as HTTP is a rather verbose protocol.

But yeah, let me know if you have any other questions on this. Thanks!

mikemaccana commented 9 years ago

Sorry for bothering you, but this isn't quite right:

If a GET request for /images/button.jpg results in a 302, then the browser will still continue to request /images/button.jpg.

The browser would request the URL given in the 302, not the original URL.

Granted, if the 302 request points to a strongly cached resource

Exactly, doing so was my suggestion. But acknowledged re: amount of HTTP requests, and thanks for answering.

bminer commented 9 years ago

Just to clarify...

If a GET request for /images/button.jpg results in a 302, then the browser will still continue to request /images/button.jpg.

What I was trying to say was... the HTML would contain the URL /images/button.jpg, so the browser would issue a GET request for /images/button.jpg. The server responds to this request with 302 and the fingerprint URL. Then, the browser would request /images/button.jpg?v=38d89f8a, for example. That's 2 HTTP requests. If the browser needs to GET /images/button.jpg again, it would again hit the server with an HTTP request, which responds with 302 again. If the asset hasn't changed, the server returns /images/button.jpg?v=38d89f8a again. In this case, the browser knows that it doesn't need to issue another HTTP request.

mikemaccana commented 9 years ago

Thanks Blake!