index.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // 修改自https://github.com/kryops/rollup-plugin-gzip
  2. // 因为rollup-plugin-gzip不支持vite
  3. // vite对css打包独立的。所以不能在打包的时候顺带打包css
  4. // TODO rc.9会支持 configurBuild 配置项。到时候重新修改
  5. import { readFile, writeFile } from 'fs';
  6. import { basename } from 'path';
  7. import { promisify } from 'util';
  8. import { gzip } from 'zlib';
  9. import { OutputAsset, OutputChunk, OutputOptions, Plugin } from 'rollup';
  10. import { GzipPluginOptions } from './types';
  11. const isFunction = (arg: unknown): arg is (...args: any[]) => any => typeof arg === 'function';
  12. const isRegExp = (arg: unknown): arg is RegExp =>
  13. Object.prototype.toString.call(arg) === '[object RegExp]';
  14. export type StringMappingOption = (originalString: string) => string;
  15. export type CustomCompressionOption = (
  16. content: string | Buffer
  17. ) => string | Buffer | Promise<string | Buffer>;
  18. const readFilePromise = promisify(readFile);
  19. const writeFilePromise = promisify(writeFile);
  20. // functionality partially copied from rollup
  21. /**
  22. * copied from https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L450
  23. */
  24. function isOutputChunk(file: OutputAsset | OutputChunk): file is OutputChunk {
  25. return typeof (file as OutputChunk).code === 'string';
  26. }
  27. /**
  28. * Gets the string/buffer content from a file object.
  29. * Important for adding source map comments
  30. *
  31. * Copied partially from rollup.writeOutputFile
  32. * https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L454
  33. */
  34. function getOutputFileContent(
  35. outputFileName: string,
  36. outputFile: OutputAsset | OutputChunk,
  37. outputOptions: OutputOptions
  38. ): string | Buffer {
  39. if (isOutputChunk(outputFile)) {
  40. let source: string | Buffer;
  41. source = outputFile.code;
  42. if (outputOptions.sourcemap && outputFile.map) {
  43. const url =
  44. outputOptions.sourcemap === 'inline'
  45. ? outputFile.map.toUrl()
  46. : `${basename(outputFileName)}.map`;
  47. // https://github.com/rollup/rollup/blob/master/src/utils/sourceMappingURL.ts#L1
  48. source += `//# source` + `MappingURL=${url}\n`;
  49. }
  50. return source;
  51. } else {
  52. return typeof outputFile.source === 'string'
  53. ? outputFile.source
  54. : // just to be sure, as it is typed string | Uint8Array in rollup 2.0.0
  55. Buffer.from(outputFile.source);
  56. }
  57. }
  58. // actual plugin code
  59. function gzipPlugin(options: GzipPluginOptions = {}): Plugin {
  60. // check for old options
  61. if ('algorithm' in options) {
  62. console.warn(
  63. '[rollup-plugin-gzip] The "algorithm" option is not supported any more! ' +
  64. 'Use "customCompression" instead to specify a different compression algorithm.'
  65. );
  66. }
  67. if ('options' in options) {
  68. console.warn('[rollup-plugin-gzip] The "options" option was renamed to "gzipOptions"!');
  69. }
  70. if ('additional' in options) {
  71. console.warn('[rollup-plugin-gzip] The "additional" option was renamed to "additionalFiles"!');
  72. }
  73. if ('delay' in options) {
  74. console.warn('[rollup-plugin-gzip] The "delay" option was renamed to "additionalFilesDelay"!');
  75. }
  76. const compressGzip: CustomCompressionOption = (fileContent) => {
  77. return new Promise((resolve, reject) => {
  78. gzip(fileContent, options.gzipOptions || {}, (err, result) => {
  79. if (err) {
  80. reject(err);
  81. } else {
  82. resolve(result);
  83. }
  84. });
  85. });
  86. };
  87. const doCompress = options.customCompression || compressGzip;
  88. const mapFileName: StringMappingOption = isFunction(options.fileName)
  89. ? (options.fileName as StringMappingOption)
  90. : (fileName: string) => fileName + (options.fileName || '.gz');
  91. const plugin: Plugin = {
  92. name: 'gzip',
  93. generateBundle(outputOptions, bundle) {
  94. return Promise.all(
  95. Object.keys(bundle)
  96. .map((fileName) => {
  97. const fileEntry = bundle[fileName];
  98. // file name filter option check
  99. const fileNameFilter = options.filter || /\.(js|mjs|json|css|html)$/;
  100. if (isRegExp(fileNameFilter) && !fileName.match(fileNameFilter)) {
  101. return Promise.resolve();
  102. }
  103. if (
  104. isFunction(fileNameFilter) &&
  105. !(fileNameFilter as (x: string) => boolean)(fileName)
  106. ) {
  107. return Promise.resolve();
  108. }
  109. const fileContent = getOutputFileContent(fileName, fileEntry, outputOptions);
  110. // minSize option check
  111. if (options.minSize && options.minSize > fileContent.length) {
  112. return Promise.resolve();
  113. }
  114. return Promise.resolve(doCompress(fileContent))
  115. .then((compressedContent) => {
  116. const compressedFileName = mapFileName(fileName);
  117. bundle[compressedFileName] = {
  118. type: 'asset', // Rollup >= 1.21
  119. name: compressedFileName,
  120. fileName: compressedFileName,
  121. isAsset: true, // Rollup < 1.21
  122. source: compressedContent,
  123. };
  124. })
  125. .catch((err: any) => {
  126. console.error(err);
  127. return Promise.reject('[rollup-plugin-gzip] Error compressing file ' + fileName);
  128. });
  129. })
  130. .concat([
  131. (() => {
  132. if (!options.additionalFiles || !options.additionalFiles.length)
  133. return Promise.resolve();
  134. const compressAdditionalFiles = () =>
  135. Promise.all(
  136. options.additionalFiles!.map((filePath) =>
  137. readFilePromise(filePath)
  138. .then((fileContent) => doCompress(fileContent))
  139. .then((compressedContent) => {
  140. return writeFilePromise(mapFileName(filePath), compressedContent);
  141. })
  142. .catch(() => {
  143. return Promise.reject(
  144. '[rollup-plugin-gzip] Error compressing additional file ' +
  145. filePath +
  146. '. Please check the spelling of your configured additionalFiles. ' +
  147. 'You might also have to increase the value of the additionalFilesDelay option.'
  148. );
  149. })
  150. )
  151. ) as Promise<any>;
  152. // additional files can be processed outside of rollup after a delay
  153. // for older plugins or plugins that write to disk (curcumventing rollup) without awaiting
  154. const additionalFilesDelay = options.additionalFilesDelay || 0;
  155. if (additionalFilesDelay) {
  156. setTimeout(compressAdditionalFiles, additionalFilesDelay);
  157. return Promise.resolve();
  158. } else {
  159. return compressAdditionalFiles();
  160. }
  161. })(),
  162. ])
  163. ) as Promise<any>;
  164. },
  165. };
  166. return plugin;
  167. }
  168. export default gzipPlugin;