gzipCompressor.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. var debug = require('debug')('ylt:gzipCompressor');
  2. var Q = require('q');
  3. var zlib = require('zlib');
  4. var GzipCompressor = function() {
  5. function compressFile(entry) {
  6. return gzipUncompressedFile(entry)
  7. .then(gzipOptimizedFile);
  8. }
  9. // Gzip a file if it was not already gziped
  10. function gzipUncompressedFile(entry) {
  11. var deferred = Q.defer();
  12. if (entryTypeCanBeGzipped(entry) && entry.weightCheck && !entry.weightCheck.isCompressed && entry.weightCheck.body) {
  13. debug('Compression missing, trying to gzip file %s', entry.url);
  14. var uncompressedSize = entry.weightCheck.uncompressedSize;
  15. zlib.gzip(new Buffer(entry.weightCheck.body, 'utf8'), function(err, buffer) {
  16. if (err) {
  17. debug('Could not compress uncompressed file with gzip');
  18. debug(err);
  19. deferred.reject(err);
  20. } else {
  21. var compressedSize = buffer.length;
  22. if (gainIsEnough(uncompressedSize, compressedSize)) {
  23. debug('File correctly gziped, was %d and is now %d bytes', uncompressedSize, compressedSize);
  24. entry.weightCheck.afterCompression = compressedSize;
  25. } else {
  26. debug('Gzip gain is not enough, was %d and is now %d bytes', uncompressedSize, compressedSize);
  27. }
  28. deferred.resolve(entry);
  29. }
  30. });
  31. } else {
  32. deferred.resolve(entry);
  33. }
  34. return deferred.promise;
  35. }
  36. // Gzip a file after minification or optimization if this step was successful
  37. function gzipOptimizedFile(entry) {
  38. var deferred = Q.defer();
  39. if (entryTypeCanBeGzipped(entry) && entry.weightCheck && entry.weightCheck.isOptimized === false) {
  40. debug('Trying to gzip file after minification: %s', entry.url);
  41. var uncompressedSize = entry.weightCheck.optimized;
  42. zlib.gzip(new Buffer(entry.weightCheck.bodyAfterOptimization, 'utf8'), function(err, buffer) {
  43. if (err) {
  44. debug('Could not compress minified file with gzip');
  45. debug(err);
  46. deferred.reject(err);
  47. } else {
  48. var compressedSize = buffer.length;
  49. debug('Correctly gziped the minified file, was %d and is now %d bytes', uncompressedSize, compressedSize);
  50. entry.weightCheck.afterOptimizationAndCompression = compressedSize;
  51. deferred.resolve(entry);
  52. }
  53. });
  54. } else {
  55. deferred.resolve(entry);
  56. }
  57. return deferred.promise;
  58. }
  59. // The gain is estimated of enough value if it's over 1KB or over 20%,
  60. // but it's ignored if is below 100 bytes
  61. function gainIsEnough(oldWeight, newWeight) {
  62. var gain = oldWeight - newWeight;
  63. var ratio = gain / oldWeight;
  64. return (gain > 2048 || (ratio > 0.2 && gain > 100));
  65. }
  66. function entryTypeCanBeGzipped(entry) {
  67. return entry.isJS || entry.isCSS || entry.isHTML || entry.isJSON || entry.isSVG || entry.isTTF || entry.isXML || entry.isFavicon;
  68. }
  69. return {
  70. compressFile: compressFile,
  71. entryTypeCanBeGzipped: entryTypeCanBeGzipped
  72. };
  73. };
  74. module.exports = new GzipCompressor();