sveltejs/sapper-template

Serve hashed image URLs

benmccann opened this issue · 15 comments

Right now images are included simply as:

<img alt='Success Kid' src='successkid.jpg'>

However, this means that images can't be cached, served by a CDN, etc. Both Rollup and Webpack support doing an image import which returns an image name containing a hash:

import successkid from './successkid.jpg';
<img alt='Success Kid' src='successkid'>

https://github.com/rollup/plugins/tree/master/packages/url
https://webpack.js.org/loaders/file-loader/

This seems like a reasonable default setting that's inline with Sapper's focus on performance. What do people think about this?

thgh commented

Did you mean it like this?

import successkid from './successkid.jpg';
<img alt='Success Kid' src={successkid}>

It looks like the rollup plugin does not return a URL?

thgh commented

That looks pretty awesome!

Why does the image have to be exported?
export let successkid = successkidJpg;

pngwn commented

I’m pretty sure you can achieve this just with an import statement.

thgh commented

@benmccan One drawback is that you can't link to a file that might change once in a while. (or do you host both? In that case you get duplicates in ./static and _sapper_/client/static. (not a blocking issue perhaps)

CDNs can cache based on query params, so how about this url structure:
fileName: '[dirname][name][extname]?v=[hash]',

I’m pretty sure you can just achieve this with an import statement.

Yes. Thanks for pointing that out. That's much better!

One drawback is that you can't link to a file that might change once in a while.

I'm assuming you mean a link from an external site. As long as it's a link from within the app it shouldn't present any difficulty

CDNs can cache based on query params, so how about this url structure:
fileName: '[dirname][name][extname]?v=[hash]',

Some or probably most can, but my understanding is that it doesn't work universally. Here's an old, but still popular, article suggesting file names are better. I'm not as worried about that though as avoiding extra serving complication. It'd be nice to be able to take all your static files, output them to a build directory with hash, and tell your server the files are all cacheable forever. It's more complicated to tell your server, these files are cachable forever if they have a query string (in the format of a hash?), but not cachable if there's no query string (or it's in the wrong format?).

Luckily it's configurable, so easy for folks to change if they prefer a different strategy. We're doing all the hard setup work here, so it'd only be changing a couple lines to put in the query string instead of file name for cases where that's preferred. I think the best default is to just use Rollup's default and let folks configure it from there

I found that this will not work in many cases due to a bug in Sapper, so we'll need to wait for sveltejs/sapper#1246 to be merged and a new release including that change before submitting a PR here.

Edit: this was released 0.27.14

hgl commented

@pngwn Is it possible to hash urls in CSS (background, etc) with import statements?

hgl commented

@benmccann didn't know https://github.com/postcss/postcss-url could also do hashing. Thanks for the tip.

So that means hashing in CSS must be done implicitly, but JS explicitly. Still feel quite uneasy.

Implementing this for Webpack requires sveltejs/sapper#1342

Can this be applied to global.css (loaded in src/template.html) too?

I haven't tried. Not sure if Svelte does anything special with that file, but if it's just a standard file I'm not sure why it wouldn't work

I did a brief attempt at it and it claims that the CSS file does not have a default export. I didn't get past that so I dropped it.