Senior Software Engineer at HootSuite
Twitter : @theasta
HTTP Headers
Last-Modified / If-Modified-Since
Etag / If-None-Match
HTTP Headers
Cache-Control: max-age=2592000
Expires:Sat, 22 Jun 2013 05:00:00 GMT
No request to the server for the next month !!
/js/base.js?v=1.2.0
(BAD)/1.2.0/js/base.js
/js/base.1.2.0.js
/12345/js/base.js
/12345/css/homepage.css
/12345/images/bg.png
12345 folder = release tag
Continuous deployment + per-release assets versioning = bad match !!
A JavaScript task runner built on top of Node.js
module.exports = function(grunt) {
grunt.initConfig({
uglify: { ... },
cssmin: { ... },
s3: { ... }
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-s3');
grunt.registerTask('deploy', ['uglify', 'cssmin', 's3']);
};
grunt <taskName>
grunt.initConfig({
uglify: {
home: {
files: {
'build/js/home.js': ['js/home.js', 'js/home_utils.js']
}
},
contact: {
files: {
'build/js/contact.js': ['js/contact_form.js']
}
}
}
});
grunt uglify
grunt uglify:home
grunt.initConfig({
cssmin: {
main: {
files: {
'build/css/main.css': ['css/layout.css', 'css/buttons.css']
}
}
}
});
grunt cssmin
grunt.registerTask('deploy', ['uglify', 'cssmin', 's3']);
grunt deploy
assets_versioning: {
home: {
options: {
multitask: 'uglify'
}
}
}
Won't run the cloned task if ever the versioned destination file already exists.
and plenty other options...
/images/loader.gif
-> /images/loader.20130413004500.gif
options.output: generates a json file with both original and versioned filenames.
// images.less
@loader_gif: 'loader.gif';
@buttons_btn-cta_png: 'buttons/btn-cta.png';
.btn-cta {
color: #384602;
background: #accd3d url("@{base-image}@{buttons_btn-cta_png}") 0 center repeat-x;
}
NPM
npm install grunt-assets-versioning
Github
https://github.com/theasta/grunt-assets-versioning