index.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  6. MIT License http://www.opensource.org/licenses/mit-license.php
  7. Author Tobias Koppers @sokra
  8. */
  9. var _crypto = require('crypto');
  10. var _crypto2 = _interopRequireDefault(_crypto);
  11. var _url = require('url');
  12. var _url2 = _interopRequireDefault(_url);
  13. var _neoAsync = require('neo-async');
  14. var _neoAsync2 = _interopRequireDefault(_neoAsync);
  15. var _RawSource = require('webpack-sources/lib/RawSource');
  16. var _RawSource2 = _interopRequireDefault(_RawSource);
  17. var _ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers');
  18. var _ModuleFilenameHelpers2 = _interopRequireDefault(_ModuleFilenameHelpers);
  19. var _cacache = require('cacache');
  20. var _cacache2 = _interopRequireDefault(_cacache);
  21. var _findCacheDir = require('find-cache-dir');
  22. var _findCacheDir2 = _interopRequireDefault(_findCacheDir);
  23. var _serializeJavascript = require('serialize-javascript');
  24. var _serializeJavascript2 = _interopRequireDefault(_serializeJavascript);
  25. var _package = require('../package.json');
  26. var _package2 = _interopRequireDefault(_package);
  27. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  28. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  29. var CompressionPlugin = function () {
  30. function CompressionPlugin() {
  31. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  32. _classCallCheck(this, CompressionPlugin);
  33. var _options$asset = options.asset,
  34. asset = _options$asset === undefined ? '[path].gz[query]' : _options$asset,
  35. test = options.test,
  36. include = options.include,
  37. exclude = options.exclude,
  38. _options$algorithm = options.algorithm,
  39. algorithm = _options$algorithm === undefined ? 'gzip' : _options$algorithm,
  40. _options$filename = options.filename,
  41. filename = _options$filename === undefined ? false : _options$filename,
  42. _options$compressionO = options.compressionOptions,
  43. compressionOptions = _options$compressionO === undefined ? {} : _options$compressionO,
  44. _options$cache = options.cache,
  45. cache = _options$cache === undefined ? false : _options$cache,
  46. _options$threshold = options.threshold,
  47. threshold = _options$threshold === undefined ? 0 : _options$threshold,
  48. _options$minRatio = options.minRatio,
  49. minRatio = _options$minRatio === undefined ? 0.8 : _options$minRatio,
  50. _options$deleteOrigin = options.deleteOriginalAssets,
  51. deleteOriginalAssets = _options$deleteOrigin === undefined ? false : _options$deleteOrigin;
  52. this.options = {
  53. asset,
  54. test,
  55. include,
  56. exclude,
  57. algorithm,
  58. filename,
  59. compressionOptions,
  60. cache,
  61. threshold,
  62. minRatio,
  63. deleteOriginalAssets
  64. };
  65. if (typeof algorithm === 'string') {
  66. // eslint-disable-next-line global-require
  67. var zlib = require('zlib');
  68. this.options.algorithm = zlib[this.options.algorithm];
  69. if (!this.options.algorithm) {
  70. throw new Error('Algorithm not found in zlib');
  71. }
  72. this.options.compressionOptions = {
  73. level: options.level || 9,
  74. flush: options.flush,
  75. chunkSize: options.chunkSize,
  76. windowBits: options.windowBits,
  77. memLevel: options.memLevel,
  78. strategy: options.strategy,
  79. dictionary: options.dictionary
  80. };
  81. }
  82. }
  83. _createClass(CompressionPlugin, [{
  84. key: 'apply',
  85. value: function apply(compiler) {
  86. var _this = this;
  87. var emit = function emit(compilation, callback) {
  88. var _options = _this.options,
  89. cache = _options.cache,
  90. threshold = _options.threshold,
  91. minRatio = _options.minRatio,
  92. assetName = _options.asset,
  93. filename = _options.filename,
  94. deleteOriginalAssets = _options.deleteOriginalAssets;
  95. var cacheDir = cache === true ? (0, _findCacheDir2.default)({ name: 'compression-webpack-plugin' }) : cache;
  96. var assets = compilation.assets;
  97. // eslint-disable-next-line consistent-return
  98. _neoAsync2.default.forEach(Object.keys(assets), function (file, cb) {
  99. if (!_ModuleFilenameHelpers2.default.matchObject(_this.options, file)) {
  100. return cb();
  101. }
  102. var asset = assets[file];
  103. var input = asset.source();
  104. if (!Buffer.isBuffer(input)) {
  105. input = Buffer.from(input);
  106. }
  107. var originalSize = input.length;
  108. if (originalSize < threshold) {
  109. return cb();
  110. }
  111. return Promise.resolve().then(function () {
  112. if (cache) {
  113. var cacheKey = (0, _serializeJavascript2.default)({
  114. // Invalidate cache after upgrade `zlib` module (build-in in `nodejs`)
  115. node: process.version,
  116. 'compression-webpack-plugin': _package2.default.version,
  117. 'compression-webpack-plugin-options': _this.options,
  118. path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file,
  119. hash: _crypto2.default.createHash('md4').update(input).digest('hex')
  120. });
  121. return _cacache2.default.get(cacheDir, cacheKey).then(function (result) {
  122. return result.data;
  123. }, function () {
  124. return Promise.resolve().then(function () {
  125. return _this.compress(input);
  126. }).then(function (data) {
  127. return _cacache2.default.put(cacheDir, cacheKey, data).then(function () {
  128. return data;
  129. });
  130. });
  131. });
  132. }
  133. return _this.compress(input);
  134. }).then(function (result) {
  135. if (result.length / originalSize > minRatio) {
  136. return cb();
  137. }
  138. var parse = _url2.default.parse(file);
  139. var sub = {
  140. file,
  141. path: parse.pathname,
  142. query: parse.query ? `?${parse.query}` : ''
  143. };
  144. var newAssetName = assetName.replace(/\[(file|path|query)\]/g, function (p0, p1) {
  145. return sub[p1];
  146. });
  147. if (typeof filename === 'function') {
  148. newAssetName = filename(newAssetName);
  149. }
  150. assets[newAssetName] = new _RawSource2.default(result);
  151. if (deleteOriginalAssets) {
  152. delete assets[file];
  153. }
  154. return cb();
  155. }).catch(cb);
  156. }, callback);
  157. };
  158. if (compiler.hooks) {
  159. var plugin = { name: 'CompressionPlugin' };
  160. compiler.hooks.emit.tapAsync(plugin, emit);
  161. } else {
  162. compiler.plugin('emit', emit);
  163. }
  164. }
  165. }, {
  166. key: 'compress',
  167. value: function compress(input) {
  168. var _this2 = this;
  169. return new Promise(function (resolve, reject) {
  170. var _options2 = _this2.options,
  171. algorithm = _options2.algorithm,
  172. compressionOptions = _options2.compressionOptions;
  173. algorithm(input, compressionOptions, function (error, result) {
  174. if (error) {
  175. return reject(error);
  176. }
  177. return resolve(result);
  178. });
  179. });
  180. }
  181. }]);
  182. return CompressionPlugin;
  183. }();
  184. exports.default = CompressionPlugin;