Thanks for both your replies!
In the end I went with imagemin. its very easy to use and is easily put into a middleware.
You may have to change this around and about, but here is how I implemented a caching, minifying middleware:
CDN.use("/cdn", function(req, res, next){
var fname = path.basename(req.url);
var ext = path.extname(fname);
if(ext.substr(1).match(/^(png|jpg|jpeg|gif|svg)$/i)) {
var infile = config.base+"/cdn/"+url.parse(req.url).pathname;
if(
typeof req.headers["if-none-match"] != "undefined"
&& req.headers["if-none-match"]==md5_file(infile)
) {
log.info("Its cached.");
res.statusCode = 304;
return res.end();
}
var dirname = path.dirname(req.url);
mkdirp(config.base+"/cache/cdn/"+dirname, function(err){
if(err) {
console.log("Error",err);
return next();
}
var cacheDir = config.base+"/cache/";
var outdir = config.base+"/cache/cdn/"+path.dirname(req.url);
var outname = md5_file(infile)+"-"+path.basename(infile);
var outfile = path.join(outdir, outname);
var extName = ext.substr(1);
fs.exists(outfile, function(exists){
// One way or another, we're sending something here, so set headers.
var age = 30*24*60*60;
var time = Date.now();
var d = new Date(Date.now() + age*1000);
res.setHeader("Etag", md5_file(infile)); // Outfile wont exist, but we can cheat. :)
res.setHeader("Cache-control", "public, max-age="+age);
res.setHeader("Expires", d.toUTCString());
if(!exists) {
log.info("BIRD3 CDN -> Generating: ",outfile);
var imagemin = new Imagemin()
.src(infile)
.use(Imagemin.jpegtran({ progressive: true }))
.use(Imagemin.gifsicle())
.use(Imagemin.optipng())
.use(Imagemin.pngquant())
.use(Imagemin.svgo());
imagemin.run(function(err, files, stream){
if(err) {
log.error("Imagemin error");
log.error(err);
return next();
}
fs.writeFile(outfile, files[0].contents, function(err){
if(err) {
log.error("Can not write optimized image: "+outfile);
console.error(err);
}
res.setHeader("Content-type", mime.types[extName]);
res.end(files[0].contents);
return;
});
});
} else {
log.info("BIRD3 CDN -> Sending generated: "+outfile);
fs.readFile(outfile, function(err, output){
if(err) {
log.error(err);
return next();
}
res.setHeader("Content-type", mime.types[extName]);
res.end(output);
return;
});
}
});
});
} else return next();
});
This is straight from my code. Feel free to replace parts and reuse, or make a module, or whatever. But I think this is quite a neat thing to have. Because if your images change, then this also will regenerate the images. Otherwise, it tells your browser that the image should be cached as well and should save you some reads.
Kind regards, Ingwie
PS. If you have advice on optimizing this thing, i’d be happy to hear about it. :)