gzipCompressor.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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) {
  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. if (gainIsEnough(uncompressedSize, compressedSize)) {
  50. debug('Correctly gziped the minified file, was %d and is now %d bytes', uncompressedSize, compressedSize);
  51. entry.weightCheck.afterOptimizationAndCompression = compressedSize;
  52. } else {
  53. debug('Gzip gain is not enough on minified file, was %d and is now %d bytes', uncompressedSize, compressedSize);
  54. }
  55. deferred.resolve(entry);
  56. }
  57. });
  58. } else {
  59. deferred.resolve(entry);
  60. }
  61. return deferred.promise;
  62. }
  63. // The gain is estimated of enough value if it's over 1KB or over 20%,
  64. // but it's ignored if is below 100 bytes
  65. function gainIsEnough(oldWeight, newWeight) {
  66. var gain = oldWeight - newWeight;
  67. var ratio = gain / oldWeight;
  68. return (gain > 2048 || (ratio > 0.2 && gain > 100));
  69. }
  70. function entryTypeCanBeGzipped(entry) {
  71. return entry.isJS || entry.isCSS || entry.isHTML || entry.isJSON || entry.isSVG || entry.isTTF || entry.isXML || entry.isFavicon;
  72. }
  73. return {
  74. compressFile: compressFile,
  75. entryTypeCanBeGzipped: entryTypeCanBeGzipped
  76. };
  77. };
  78. module.exports = new GzipCompressor();