index.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. const { codeFrameColumns } = require("@babel/code-frame");
  2. const Worker = require("jest-worker").default;
  3. const serialize = require("serialize-javascript");
  4. const { createFilter } = require("rollup-pluginutils");
  5. function terser(userOptions = {}) {
  6. if (userOptions.sourceMap != null) {
  7. throw Error("sourceMap option is removed, use sourcemap instead");
  8. }
  9. const filter = createFilter(userOptions.include, userOptions.exclude, {
  10. resolve: false
  11. });
  12. return {
  13. name: "terser",
  14. renderChunk(code, chunk, outputOptions) {
  15. if (!filter(chunk.fileName)) {
  16. return null;
  17. }
  18. if (!this.worker) {
  19. this.worker = new Worker(require.resolve("./transform.js"), {
  20. numWorkers: userOptions.numWorkers
  21. });
  22. this.numOfBundles = 0;
  23. }
  24. this.numOfBundles++;
  25. const defaultOptions = {
  26. sourceMap: userOptions.sourcemap !== false
  27. };
  28. if (outputOptions.format === "es" || outputOptions.format === "esm") {
  29. defaultOptions.module = true;
  30. }
  31. if (outputOptions.format === "cjs") {
  32. defaultOptions.toplevel = true;
  33. }
  34. // TODO rewrite with object spread after dropping node v6
  35. const normalizedOptions = Object.assign({}, defaultOptions, userOptions);
  36. // remove plugin specific options
  37. for (let key of ["include", "exclude", "sourcemap", "numWorkers"]) {
  38. if (normalizedOptions.hasOwnProperty(key)) {
  39. delete normalizedOptions[key];
  40. }
  41. }
  42. const serializedOptions = serialize(normalizedOptions);
  43. const result = this.worker
  44. .transform(code, serializedOptions)
  45. .catch(error => {
  46. const { message, line, col: column } = error;
  47. console.error(
  48. codeFrameColumns(code, { start: { line, column } }, { message })
  49. );
  50. throw error;
  51. });
  52. const handler = () => {
  53. this.numOfBundles--;
  54. if (this.numOfBundles === 0) {
  55. this.worker.end();
  56. this.worker = 0;
  57. }
  58. };
  59. result.then(handler, handler);
  60. return result.then(result => {
  61. if (result.nameCache) {
  62. let { vars, props } = userOptions.nameCache;
  63. // only assign nameCache.vars if it was provided, and if terser produced values:
  64. if (vars) {
  65. const newVars =
  66. result.nameCache.vars && result.nameCache.vars.props;
  67. if (newVars) {
  68. vars.props = vars.props || {};
  69. Object.assign(vars.props, newVars);
  70. }
  71. }
  72. // support populating an empty nameCache object:
  73. if (!props) {
  74. props = userOptions.nameCache.props = {};
  75. }
  76. // merge updated props into original nameCache object:
  77. const newProps =
  78. result.nameCache.props && result.nameCache.props.props;
  79. if (newProps) {
  80. props.props = props.props || {};
  81. Object.assign(props.props, newProps);
  82. }
  83. }
  84. return result.result;
  85. });
  86. }
  87. };
  88. }
  89. exports.terser = terser;