Cache busting images which are linked inside SASS files
Asked Answered
R

3

12

I'm fairly new to Laravel 5.0, but not to PHP. I've been playing around with Elixir to compile my SASS, copy images from my resource directory and run them through the mix.version function to prevent caching.

This works great for CSS, images and JavaScript, however; is it possible to have Elixir cache-bust the images linked in my CSS/SASS as well? Sure it's easily enough to version the images but is there a way of adjusting the CSS to reflect the new filenames?

I discovered this: https://github.com/trentearl/gulp-css-url-adjuster which allows you to append a query parameter to the file paths in a CSS file, so that is half of the problem solved. I would be quite happy to use this if it were possible to automatically change the query parameter each time gulp runs.

Any thoughts on how this can be achieved, or if it is even possible?

The reasons I would like to do this is I'm constantly developing my app and I use a large sprite sheet which is often rearranged, cache busting is a requirement, and if it could be automatic when gulp runs that would save me a lot of time and effort.

Thanks

Rexford answered 29/9, 2015 at 9:24 Comment(0)
R
4

Using the answer from @Amo for inspiration, the solution I ended up using was a mixin, which makes use of the unique_id() function to generate a random value. This avoids having to define a custom SASS function, so it's simpler and as @Amelia pointed out, a bit cleaner too.

The mixin

@mixin background-cache-bust($url) {
    background-image: #{'url('} + $url + #{'?v='} + unique_id() + #{')'};
}

Example

.sprite {
    @include background-cache-bust('/build/images/common/sprite.png');
}

Result

.sprite {
    background-image: "url(/build/images/common/sprite.png?v=u95ab40e0)";
}
Rexford answered 9/10, 2015 at 20:7 Comment(3)
It would be better to change the path rather than use a query string, then rewrite the path on the web server.Proficient
How would this be better? Browsers will treat query parameters as a different URL anyway. Changing the path and rewriting via the server produces an extra layer of complication which cannot be achieved with Sass alone.Rexford
The query-string method is not the best accepted practice for cache-busting, and can fail under certain circumstances. Some browsers don't see a different query string as a different file and some software (I've heard: Squid) won't cache files with query string. Also, using the query string method you prevent web servers like IIS from serving ETag headers which allow browsers to check for cache validity rather than relying solely on expiry date/times.Proficient
A
3

As you're using SASS, it's possible to define a custom variable in your SASS files which could be used for cache busting, and then append that variable to any image url paths.

The variable just needs to hold a reference to the current timestamp.

To do this, you'll need to create a new function in SASS to expose a timestamp, which can be done as follows:

module Sass::Script::Functions
    def timestamp()
        return Sass::Script::String.new(Time.now.strftime("%Y%m%d%H%M"))
    end
end

Then you can access the timestamp as follows:

$cacheVersion = timestamp()

.someClass {
    background-image: url('your/path/file.jpg?cacheversion='$cacheVersion);
}

When compiled, this will produce something like:

.someClass {
    background-image: url('your/path/file.jpg?cacheversion=201510091349');
}
Astyanax answered 9/10, 2015 at 12:52 Comment(2)
Probably better to do a mixin here, and return the given link as url($link?v=$timestamp)Blear
This is actually a good idea. I've been approaching this as a problem to solve with elixir or gulp but actually, adding a timestamp would mean it changes every time the SASS is compiled (which would happen a lot during development), but would not really matter once the latest changes are deployed to their environment.Rexford
S
1

I'm using gulp-sass and @AJReading mixin doesn't concantenate string correctly, which compiles to:

background-image: url(+ "$url" + ?v= + u2f58eec1 + );

Here is what works in my case

Mixin

@mixin background-cache-bust($url) {
   background-image: unquote('url(' + $url + '?v=' + unique_id() + ')');
}
Sitsang answered 6/10, 2016 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.