Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache bust background images in my CSS with Gulp without having to edit my SASS?

Tags:

caching

gulp

I want to cache bust background images in my CSS. So if my original style is:

.one {
  background: url(image.png);
}

A string can be added:

.one {
  background: url(image.png?1234);
}

Or the file name could be changed:

.one {
  background: url(image-1234.png);
}

Rather than using a random generator or a timestamp id like to use a hash of the image file so that the cache is only busted when needed (when the file has actually changed).

Im using SASS and Gulp so I could use Gulp Cache Buster and Gulp Hasher:

https://github.com/disintegrator/gulp-hasher

https://github.com/disintegrator/gulp-cache-buster

The issue I have with these is that it looks like you need to modify your SASS. So if you start with this:

.logo {
  background: url(assets/images/logo.svg);
}

You need to change it to this:

.logo {
  background: url(ASSET{assets/images/logo.svg});
}

I want to keep my SASS nice and clean and not modify it in this way. Is this possible?

like image 975
Evanss Avatar asked Feb 18 '16 12:02

Evanss


2 Answers

The way I see it you have two options - both of which would use the hasher and cache busting plugins you listed:

  1. Write a gulp task that would automatically add ASSET{ ... } around all of the URLs in your CSS file. This would happen after concatenation and before hashing/busting. Since you have a bounty on this question, let me know if you would like me to write that task. I suggest you take a stab at it though b/c you might learn some neat things.

  2. Ideal solution: The cache busting plugin has an option for defining the regex to use to find assets. By default, the regex is set to /ASSET{(.*?)}/g, but you could easily update to something to match good ol' vanilla CSS url(...)s. Again, since you have a bounty let me know if you want help on the regex - but I suggest you take a stab at it b/c you might learn something neat (pssst, you want to ignore data: URLs).

    Try this regex in the cache bust config:
    /url\((?!['"]?data:)['"]?([^'"\)]*)['"]?\)/g

    If you want to ignore URLs which start with "http" (meaning they're hosted on another domain), then use the following regex. This assumes that all paths to your assets are relative, which they should be:
    /url\((?!['"]?(?:data|http):)['"]?([^'"\)]*)['"]?\)/g
    http://www.regexpal.com/?fam=94251

    If you want to be able to define the CSS attributes which will have hashed/busted URLs, you can use the following, which will only apply to URLs defined in background, background-image, and list-style CSS attributes. You can add more by adding a pipe | plus the name of the attribute after |list-style:
    /(?:background(?:-image)?|list-style)[\s]*:[^\r\n;]*url\((?!['"]?(?:data|http):)['"]?([^'"\)]*)/g
    http://www.regexpal.com/?fam=94252

like image 113
Ryan Wheale Avatar answered Sep 17 '22 12:09

Ryan Wheale


You can use gulp-rev-all. It will be able to add hash to the files and rewrite them without the need to add any extra markup to your SASS file.

A very basic gulp file for the same would look like -

var gulp = require('gulp');
var sass = require('gulp-sass');
var RevAll = require('gulp-rev-all');

gulp.task('default', function () {

var revAll = new RevAll({dontRenameFile: ['index.html']});

gulp.src(['app.sass'])
.pipe(sass().on('error', sass.logError))
.pipe(revAll.revision())
.pipe(gulp.dest('build'));

gulp.src(['**.jpg','**.png','**.gif'])
.pipe(revAll.revision());

return gulp.src('index.html')
.pipe(revAll.revision())
.pipe(gulp.dest('build'));

});

Note: Used dontRenameFile option to exclude the html file from being revisioned

I have created a working example at https://github.com/pra85/gulp-sass-filerev

like image 28
Prayag Verma Avatar answered Sep 18 '22 12:09

Prayag Verma