Giter Club home page Giter Club logo

terser-webpack-plugin's Introduction

npm node tests cover discussion size

terser-webpack-plugin

This plugin uses terser to minify/minimize your JavaScript.

Getting Started

Webpack v5 comes with the latest terser-webpack-plugin out of the box. If you are using Webpack v5 or above and wish to customize the options, you will still need to install terser-webpack-plugin. Using Webpack v4, you have to install terser-webpack-plugin v4.

To begin, you'll need to install terser-webpack-plugin:

npm install terser-webpack-plugin --save-dev

or

yarn add -D terser-webpack-plugin

or

pnpm add -D terser-webpack-plugin

Then add the plugin to your webpack config. For example:

webpack.config.js

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
};

And run webpack via your preferred method.

Note about source maps

Works only with source-map, inline-source-map, hidden-source-map and nosources-source-map values for the devtool option.

Why?

  • eval wraps modules in eval("string") and the minimizer does not handle strings.
  • cheap has not column information and minimizer generate only a single line, which leave only a single mapping.

Using supported devtool values enable source map generation.

Options

test

Type:

type test = string | RegExp | Array<string | RegExp>;

Default: /\.m?js(\?.*)?$/i

Test to match files against.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        test: /\.js(\?.*)?$/i,
      }),
    ],
  },
};

include

Type:

type include = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to include.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        include: /\/includes/,
      }),
    ],
  },
};

exclude

Type:

type exclude = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to exclude.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        exclude: /\/excludes/,
      }),
    ],
  },
};

parallel

Type:

type parallel = boolean | number;

Default: true

Use multi-process parallel running to improve the build speed. Default number of concurrent runs: os.cpus().length - 1.

Note

Parallelization can speedup your build significantly and is therefore highly recommended.

Warning

If you use Circle CI or any other environment that doesn't provide real available count of CPUs then you need to setup explicitly number of CPUs to avoid Error: Call retries were exceeded (see #143, #202).

boolean

Enable/disable multi-process parallel running.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
    ],
  },
};

number

Enable multi-process parallel running and set number of concurrent runs.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4,
      }),
    ],
  },
};

minify

Type:

type minify = (
  input: {
    [file: string]: string;
  },
  sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined,
  minifyOptions: {
    module?: boolean | undefined;
    ecma?: import("terser").ECMA | undefined;
  },
  extractComments:
    | boolean
    | "all"
    | "some"
    | RegExp
    | ((
        astNode: any,
        comment: {
          value: string;
          type: "comment1" | "comment2" | "comment3" | "comment4";
          pos: number;
          line: number;
          col: number;
        }
      ) => boolean)
    | {
        condition?:
          | boolean
          | "all"
          | "some"
          | RegExp
          | ((
              astNode: any,
              comment: {
                value: string;
                type: "comment1" | "comment2" | "comment3" | "comment4";
                pos: number;
                line: number;
                col: number;
              }
            ) => boolean)
          | undefined;
        filename?: string | ((fileData: any) => string) | undefined;
        banner?:
          | string
          | boolean
          | ((commentsFile: string) => string)
          | undefined;
      }
    | undefined
) => Promise<{
  code: string;
  map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined;
  errors?: (string | Error)[] | undefined;
  warnings?: (string | Error)[] | undefined;
  extractedComments?: string[] | undefined;
}>;

Default: TerserPlugin.terserMinify

Allows you to override default minify function. By default plugin uses terser package. Useful for using and testing unpublished versions or forks.

Warning

Always use require inside minify function when parallel option enabled.

webpack.config.js

// Can be async
const minify = (input, sourceMap, minimizerOptions, extractsComments) => {
  // The `minimizerOptions` option contains option from the `terserOptions` option
  // You can use `minimizerOptions.myCustomOption`

  // Custom logic for extract comments
  const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
    .minify(input, {
      /* Your options for minification */
    });

  return { map, code, warnings: [], errors: [], extractedComments: [] };
};

// Used to regenerate `fullhash`/`chunkhash` between different implementation
// Example: you fix a bug in custom minimizer/custom function, but unfortunately webpack doesn't know about it, so you will get the same fullhash/chunkhash
// to avoid this you can provide version of your custom minimizer
// You don't need if you use only `contenthash`
minify.getMinimizerVersion = () => {
  let packageJson;

  try {
    // eslint-disable-next-line global-require, import/no-extraneous-dependencies
    packageJson = require("uglify-module/package.json");
  } catch (error) {
    // Ignore
  }

  return packageJson && packageJson.version;
};

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          myCustomOption: true,
        },
        minify,
      }),
    ],
  },
};

terserOptions

Type:

type terserOptions = {
  compress?: boolean | CompressOptions;
  ecma?: ECMA;
  enclose?: boolean | string;
  ie8?: boolean;
  keep_classnames?: boolean | RegExp;
  keep_fnames?: boolean | RegExp;
  mangle?: boolean | MangleOptions;
  module?: boolean;
  nameCache?: object;
  format?: FormatOptions;
  /** @deprecated */
  output?: FormatOptions;
  parse?: ParseOptions;
  safari10?: boolean;
  sourceMap?: boolean | SourceMapOptions;
  toplevel?: boolean;
};

Default: default

Terser options.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          ecma: undefined,
          parse: {},
          compress: {},
          mangle: true, // Note `mangle.properties` is `false` by default.
          module: false,
          // Deprecated
          output: null,
          format: null,
          toplevel: false,
          nameCache: null,
          ie8: false,
          keep_classnames: undefined,
          keep_fnames: false,
          safari10: false,
        },
      }),
    ],
  },
};

extractComments

Type:

type extractComments =
  | boolean
  | string
  | RegExp
  | ((
      astNode: any,
      comment: {
        value: string;
        type: "comment1" | "comment2" | "comment3" | "comment4";
        pos: number;
        line: number;
        col: number;
      }
    ) => boolean)
  | {
      condition?:
        | boolean
        | "all"
        | "some"
        | RegExp
        | ((
            astNode: any,
            comment: {
              value: string;
              type: "comment1" | "comment2" | "comment3" | "comment4";
              pos: number;
              line: number;
              col: number;
            }
          ) => boolean)
        | undefined;
      filename?: string | ((fileData: any) => string) | undefined;
      banner?:
        | string
        | boolean
        | ((commentsFile: string) => string)
        | undefined;
    };

Default: true

Whether comments shall be extracted to a separate file, (see details). By default extract only comments using /^\**!|@preserve|@license|@cc_on/i regexp condition and remove remaining comments. If the original file is named foo.js, then the comments will be stored to foo.js.LICENSE.txt. The terserOptions.format.comments option specifies whether the comment will be preserved, i.e. it is possible to preserve some comments (e.g. annotations) while extracting others or even preserving comments that have been extracted.

boolean

Enable/disable extracting comments.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: true,
      }),
    ],
  },
};

string

Extract all or some (use /^\**!|@preserve|@license|@cc_on/i RegExp) comments.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: "all",
      }),
    ],
  },
};

RegExp

All comments that match the given expression will be extracted to the separate file.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: /@extract/i,
      }),
    ],
  },
};

function

All comments that match the given expression will be extracted to the separate file.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: (astNode, comment) => {
          if (/@extract/i.test(comment.value)) {
            return true;
          }

          return false;
        },
      }),
    ],
  },
};

object

Allow to customize condition for extract comments, specify extracted file name and banner.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: /^\**!|@preserve|@license|@cc_on/i,
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
condition

Type:

type condition =
  | boolean
  | "all"
  | "some"
  | RegExp
  | ((
      astNode: any,
      comment: {
        value: string;
        type: "comment1" | "comment2" | "comment3" | "comment4";
        pos: number;
        line: number;
        col: number;
      }
    ) => boolean)
  | undefined;

Condition what comments you need extract.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: "some",
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
filename

Type:

type filename = string | ((fileData: any) => string) | undefined;

Default: [file].LICENSE.txt[query]

Available placeholders: [file], [query] and [filebase] ([base] for webpack 5).

The file where the extracted comments will be stored. Default is to append the suffix .LICENSE.txt to the original filename.

Warning

We highly recommend using the txt extension. Using js/cjs/mjs extensions may conflict with existing assets which leads to broken code.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: /^\**!|@preserve|@license|@cc_on/i,
          filename: "extracted-comments.js",
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
banner

Type:

type banner = string | boolean | ((commentsFile: string) => string) | undefined;

Default: /*! For license information please see ${commentsFile} */

The banner text that points to the extracted file and will be added on top of the original file. Can be false (no banner), a String, or a Function<(string) -> String> that will be called with the filename where extracted comments have been stored. Will be wrapped into comment.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: true,
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (commentsFile) => {
            return `My custom banner about license information ${commentsFile}`;
          },
        },
      }),
    ],
  },
};

Examples

Preserve Comments

Extract all legal comments (i.e. /^\**!|@preserve|@license|@cc_on/i) and preserve /@license/i comments.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          format: {
            comments: /@license/i,
          },
        },
        extractComments: true,
      }),
    ],
  },
};

Remove Comments

If you avoid building with comments, use this config:

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          format: {
            comments: false,
          },
        },
        extractComments: false,
      }),
    ],
  },
};

UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.uglifyJsMinify,
        // `terserOptions` options will be passed to `uglify-js`
        // Link to options - https://github.com/mishoo/UglifyJS#minify-options
        terserOptions: {},
      }),
    ],
  },
};

swc is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.

Warning

the extractComments option is not supported and all comments will be removed by default, it will be fixed in future

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.swcMinify,
        // `terserOptions` options will be passed to `swc` (`@swc/core`)
        // Link to options - https://swc.rs/docs/config-js-minify
        terserOptions: {},
      }),
    ],
  },
};

esbuild is an extremely fast JavaScript bundler and minifier.

Warning

the extractComments option is not supported and all legal comments (i.e. copyright, licenses and etc) will be preserved

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.esbuildMinify,
        // `terserOptions` options will be passed to `esbuild`
        // Link to options - https://esbuild.github.io/api/#minify
        // Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use:
        // terserOptions: {
        //   minify: false,
        //   minifyWhitespace: true,
        //   minifyIdentifiers: false,
        //   minifySyntax: true,
        // },
        terserOptions: {},
      }),
    ],
  },
};

Custom Minify Function

Override default minify function - use uglify-js for minification.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: (file, sourceMap) => {
          // https://github.com/mishoo/UglifyJS2#minify-options
          const uglifyJsOptions = {
            /* your `uglify-js` package options */
          };

          if (sourceMap) {
            uglifyJsOptions.sourceMap = {
              content: sourceMap,
            };
          }

          return require("uglify-js").minify(file, uglifyJsOptions);
        },
      }),
    ],
  },
};

Typescript

With default terser minify function:

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: true,
        },
      }),
    ],
  },
};

With built-in minify functions:

import type { JsMinifyOptions as SwcOptions } from "@swc/core";
import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
import type { TransformOptions as EsbuildOptions } from "esbuild";
import type { MinifyOptions as TerserOptions } from "terser";

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin<SwcOptions>({
        minify: TerserPlugin.swcMinify,
        terserOptions: {
          // `swc` options
        },
      }),
      new TerserPlugin<UglifyJSOptions>({
        minify: TerserPlugin.uglifyJsMinify,
        terserOptions: {
          // `uglif-js` options
        },
      }),
      new TerserPlugin<EsbuildOptions>({
        minify: TerserPlugin.esbuildMinify,
        terserOptions: {
          // `esbuild` options
        },
      }),

      // Alternative usage:
      new TerserPlugin<TerserOptions>({
        minify: TerserPlugin.terserMinify,
        terserOptions: {
          // `terser` options
        },
      }),
    ],
  },
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

terser-webpack-plugin's People

Contributors

0dp avatar alexander-akait avatar anshumanv avatar antonk52 avatar cap-bernardito avatar cherry avatar chicoxyzzy avatar chris-bateman avatar commanderroot avatar dekkee avatar dependabot[bot] avatar ersachin3112 avatar evilebottnawi avatar fabiosantoscode avatar gaokun avatar harish-sethuraman avatar hinok avatar jackstevenson avatar jamesgeorge007 avatar johnnyreilly avatar joshmccullough avatar koggdal avatar mattjcowan avatar onigoetz avatar ooflorent avatar pustovalov avatar rap2hpoutre avatar smelukov avatar snitin315 avatar sodatea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terser-webpack-plugin's Issues

Terser version not updated?

With Terser being at version 3.13.1 now with some important bugfixes like mangling had some problems, is there a reason terser-webpack-plugin still has terser 3.8.1 as dependency in its package.json?

I tried building a new terser-webpack-plugin dist with an upgrade to the latest terser in the terser-webpack-plugin package.json, but it's missing files to build for some reason. So that doesn't seem to be the right workflow?!

Can we just install the latest terser module in our own projects (so install the latest terser in the root of node_modules) so that terser-webpack-plugin uses that version instead? Or is terser baked in terser-webpack-plugin / needs its own terser module inside its own node_modules folder instead?

Best in my opinion would be if the terser-requirement would be kept up to date in terser-webpack-plugin builds so we can rely on having the latest terser after upgrading terser-webpack-plugin.

When used with Lerna, a cache directory is created in several different locations

  • Operating System: MacOS v10.14.3
  • Node Version: v10.15.0
  • NPM Version:6.7.0
  • Webpack Version:
@angular-devkit/[email protected]
  ├── [email protected] 
  └─┬ [email protected]
    └── [email protected]  deduped

Expected Behavior

When using lerna for hoisted package management in a monorepo, when I do run lerna run build and it runs the build script in each of my packages, the resulting cache directory should be in my root node_modules of my project.

Actual Behavior

When using lerna for hoisted package management, when I do run lerna run build and it runs the build script in each of my packages, ng build runs webpack with terser-webpack-plugin with the cache flag set to true. This generates a new node_modules directory in each of my source directories.

How Do We Reproduce?

You can reproduce fairly easily by cloning: https://github.com/graycoreio/daffodil and then:

npm install -g lerna @angular/cli
lerna run build
look in apps/daffio/ and see a new node_modules folder

terser is undefined?

  • Operating System: Ubuntu 16.04
  • Node Version: v9.10.0
  • NPM Version: v5.6.0
  • webpack Version: v4
  • terser-webpack-plugin Version: v1.1.0

Expected Behavior

This should not happen, the build should work as expected.

Actual Behavior

I try to run the angular build, this set of errors props up, pretty sure it's related to terser. I looked up the dist/minify.js apparantly _terser2 is undefined

screenshot from 2019-02-03 01-51-53

How Do We Reproduce?

babel-loader with regex property on mangle doesn't work correctly

  • Operating System: Windows 7
  • Node Version: v10.13.0
  • NPM Version: 6.4.1
  • webpack Version: 3.10.0
  • terser-webpack-plugin Version: 1.2.1

Expected Behavior

when mangle is set, the codes should be mangled both on declaration and usage part.

Actual Behavior

the code is mangled only on usage part.

Code

  // webpack.config.js
  ...
  module: {
    rules: [{
      exclude: /node_modules/,
      use: {
        loader: "babel-loader",
      },
    }],
  },
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          mangle: {
            properties: {
              regex: /^_/,
            },
          },
        },
      }),
    ],
  },
  ...

What it looks like

image
_setupAndExtendOptions is mangled to this.M, but key: '_setupAndExtendOptions', is not mangled as M so it throws TypeError: this.M is not a function

How Do We Reproduce?

add babel-loader

  module: {
    rules: [{
      exclude: /node_modules/,
      use: {
        loader: "babel-loader",
      },
    }],
  },

Map sourceMap to devtool

  • Operating System: macOS 10.14.2
  • Node Version: 10.15.0
  • NPM Version: 6.4.1
  • webpack Version: 4.29.3
  • terser-webpack-plugin Version: 1.2.2

Feature Proposal

Currently, the sourceMap option must be explicitly defined when it'd be much more convenient for it to rely on the value of Webpack's devtool option.

Feature Use Case

Less verbose config

Implicit globals incorrectly declared as block scope variables after minimisation

  • Operating System: Windows
  • Node Version: 8.10.0
  • NPM Version: 5.6.0
  • webpack Version: 4.2.6
  • terser-webpack-plugin Version: 1.1.0

Expected Behavior

I'm slightly paraphrasing here - hopefully you'll be able to understand the problem from
my example below.

before

import {window} from 'service' // abstraction
window.foo = window.foo || {}, window.foo.bar = foo.section // foo implicitly on window...

after minification

var o; = // webpack window alias...
var foo = o.foo || {}, o.foo.bar = o.foo.section // prefixed with o

Actual Behavior

after minification

var o; = // webpack window alias...
var n; // scope variable declared...!!! UH-OH!
var foo = o.foo || {}, o.foo.bar = n.section 
// TypeError! cannot read section of undefined 
// should be o.foo.section?

How Do We Reproduce?

It appears to be webpack 4's default minification process if in production mode - i.e https://webpack.js.org/configuration/optimization/#optimization-minimize

been trying to tinker with the config to prevent the introduction of this variable.

keep_classnames and keep_fnames missing from TypeScript definition file

  • Operating System: N/A
  • Node Version: N/A
  • NPM Version: N/A
  • webpack Version: 4.28.1
  • terser-webpack-plugin Version: 1.2.1

Expected Behavior

No typescript warnings in webpack.config.js file

keep_classnames and keep_fnames should be defined in typescript definition file but are not:

export interface MinifyOptions {
spidermonkey?: boolean;
outSourceMap?: string;
sourceRoot?: string;
inSourceMap?: string;
fromString?: boolean;
warnings?: boolean;
mangle?: boolean | MangleOptions;
output?: OutputOptions;
compress?: boolean | CompressOptions;
nameCache?: {};
}

Actual Behavior

Typescript squigglies:
image

Code

    optimization: {
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    // https://github.com/webpack-contrib/terser-webpack-plugin/

                    // Without this, parseError() will not recognize user cancelled errors.  Also makes debugging easier in production.
                    keep_classnames: true
                }
            }),
        ],
    },```

### How Do We Reproduce?

<!--
  Remove this section if not reporting a bug.

  If your webpack config is over 50 lines long, please provide a URL to a repo
  for your beefy 🍖 app that we can use to reproduce.
-->

since [email protected] i get TypeError: Cannot read property 'minify' of undefined

looks like since today terser update i get

ERROR in vendor.28ab9f9d78fdd25b0ab0.bundle.js from Terser
TypeError: Cannot read property 'minify' of undefined
at minify (/home/arpu/Work/projects/vrspace/node_modules/terser-webpack-plugin/dist/minify.js:175:23)
at module.exports (/home/arpu/Work/projects/vrspace/node_modules/terser-webpack-plugin/dist/worker.js:13:40)
at handle (/home/arpu/Work/projects/vrspace/node_modules/worker-farm/lib/child/index.js:44:8)
at process. (/home/arpu/Work/projects/vrspace/node_modules/worker-farm/lib/child/index.js:51:3)
at process.emit (events.js:197:13)
at emit (internal/child_process.js:828:12)
at processTicksAndRejections (internal/process/next_tick.js:76:17)

yarn list | grep terser  1 ↵  11235  18:08:06
├─ [email protected]
│ ├─ terser@^3.8.1
├─ [email protected]
│ ├─ terser-webpack-plugin@^1.1.0

Terser v3.16.0 breaks terser-webpack-plugin

The latest terser update (released an hour ago) breaks this plugin.

  • Operating System:
  • Node Version: 10.12.0
  • NPM Version: 6.4.1
  • webpack Version: 4.29.0
  • terser-webpack-plugin Version: 1.2.1

Expected Behavior

Terser to minify my code

Actual Behavior

ERROR in js/main.6e4faa1e7d31caf0fa3b.js from Terser
TypeError: Cannot read property 'minify' of undefined
    at minify (/<path>/node_modules/terser-webpack-plugin/dist/minify.js:175:23)

How Do We Reproduce?

Delete yarn.lock

Install terser-webpack-plugin and try to run a production build where the plugin is called

workaround

As a workaround for now if you use yarn you can add a resolution to a fixed terser version. Delete yarn.lock first and node_modules

Example (in your package.json)

"resolutions": {
  "terser": "3.14.1"
}

For npm try the suggestion by @odedi

ERROR in main.js from Terser

  • Operating System: iMac
  • Node Version: v10.14.2
  • NPM Version: 6.4.1
  • webpack Version: 4.28.2
  • terser-webpack-plugin Version: none

Expected Behavior

success compile

Actual Behavior

[0] ./src/a.js 951 bytes [built]
[1] ./src/index.js 1.01 KiB {0} [built]
[2] ./src/b.js 980 bytes [built]

ERROR in main.js from Terser
Unexpected token punc «(», expected name «from» [main.js:101,9]

Code

  // webpack.config.js
  // If your code blocks are over 20 lines, please paste a link to a gist
  // (https://gist.github.com).
const RemovePlugin = require('./src/plugin');

module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
  },
  plugins: [
    new RemovePlugin()
  ],
  module:{
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: ['@babel/plugin-syntax-dynamic-import']
          }
        }
      }
    ]
  }
};

// index.js

  // additional code, HEY YO remove this block if you don't need it
//  S#RP(account)
import B from "./b";
//  E#RP(account)
export * from "./a";
class Main {
    init() {

    }
    initA() {

    }
}

new Main().init();

// plugin.js

class RemovePlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap("RemovePlugin", (compilation, callback) => {
      compilation.hooks.finishModules.tap(
        this.constructor.name,
        (modules) => {
            modules.forEach(m => {
                m._source._value = m._source._value.replace(/S#RP\(\w+\)/, '99099');
                console.log(m._source._value)
            });
        })

        // callback();
    // })
  })
}}
module.exports = RemovePlugin;

How Do We Reproduce?

Terser vs. UglifyJS - Dramatic Improvements

Perhaps this belongs in the terser repo, but I thought I'd give it a go here.

We're developing a fairly large scale single page application, and we've been experiencing tedious problems with UglifyJS recently - minifying takes up to ~35 minutes, hence we're looking for a better solution.

I just tested out this plugin, and the difference is astonishing. Here are some results:

Without cache:
UglifyJsPlugin took 34 mins, 32.53 secs
UglifyJsPlugin took 32 mins, 7.82 secs
TerserPlugin took 13 mins, 38.86 secs
TerserPlugin took 12 mins, 12.99 secs
TerserPlugin took 5 mins, 33.013 secs 🚀

With cache:
UglifyJsPlugin took 3 mins, 43.85 secs
UglifyJsPlugin took 3 mins, 5.26 secs
TerserPlugin took 1 min, 32.78 secs

So Terser seems to speed it up by 3x and since it took me just about 2 minutes to switch from UglifyJS it seems almost too good to be true.

Is this to be expected? I'm basically looking for some confirmation from others. I haven't been able to find any performance tests elsewhere.

Anyhow, great work, this looks very promising! 💯

minimize bug when same varname at diff context

  • Operating System:
  • Node Version:
  • NPM Version:
  • webpack Version:
  • terser-webpack-plugin Version:

Expected Behavior

Actual Behavior

Code

project
https://github.com/bluelovers/ws-novel-vue

terser config
https://github.com/bluelovers/ws-novel-vue/blob/a4912c6bb8960db0036d06b41a92bc003e220e0a/vue.config.ts#L45-L80

			minimize: production,
			minimizer: [new TerserPlugin({
				sourceMap: development,


				//parallel: true,


				terserOptions: {
					compress: {
						dead_code: false,
						global_defs: {},
						ecma: 8,
						inline: true,
						keep_classnames: true,
						keep_fnames: true,
						keep_infinity: true,
						passes: 2,
						pure_getters: false,
						unused: false,
						warnings: true,
					},
					sourceMap: production ? undefined : {
						url: "includeSources",
						includeSources: true,
					},
					ecma: 8,
					output: {
						beautify: development,
						indent_level: 0,
						indent_start: 0,
						comments: false,
					},
					keep_classnames: true,
					keep_fnames: true,
				},

when var name is a will fail at source = a.join(''); because a is undefined at runtime

when i rename it to aaa, then didn't have error

https://github.com/bluelovers/regexp-parser-literal/blob/39a2ff97d61f80b8f46652b04d3f808180757510/index.js#L118-L169

                    let aaa = ast.elements
                        .reduce(function (a, item) {
                        let s = astToString(item, options);
                        if (do_unique
                            && item.type == 'CharacterClassRange'
                            && item.old_raw
                            && /-/u.test(item.old_raw) && !/-/u.test(s)) {
                            a = a.concat(uni_string_1.default.split(s, ''));
                        }
                        else {
                            a.push(s);
                        }
                        return a;
                    }, []);
                    if (ast.type == 'CharacterClass' && (do_unique || options.sortClass)) {
                        if (do_unique && exports.EMOJI_REGEX.test(ast.raw)) {
                            let last_is_emoji;
                            let last_is_zwj;
                            let EMOJI_SPLIT = new RegExp('(' + exports.EMOJI_REGEX.source + ')', exports.EMOJI_REGEX.flags);
                            aaa = aaa.reduce(function (a, b) {
                                let current_is_zwj = /\u200D/.test(b);
                                let current_is_emoji = EmojiRegex().test(b);
                                if (last_is_emoji) {
                                    let last_i = a.length - 1;
                                    if (current_is_emoji) {
                                        a[last_i] += b;
                                    }
                                    else {
                                        if (options.doUniqueClassEmoji) {
                                            let text = a.pop();
                                            let c = text.split(EMOJI_SPLIT);
                                            a = a.concat(c);
                                        }
                                        a.push(b);
                                    }
                                }
                                else {
                                    a.push(b);
                                }
                                last_is_emoji = current_is_emoji;
                                last_is_zwj = current_is_zwj;
                                return a;
                            }, []);
                        }
                        if (do_unique) {
                            aaa = array_hyper_unique_1.array_unique(aaa);
                        }
                        if (options.sortClass) {
                            aaa.sort();
                        }
                    }
                    source = aaa.join('');
@@ -182,13 +182,13 @@
 				// @ts-ignore
 				if (ast.elements)
 				{
 					let do_unique = !options.noUniqueClass;
 
 					// @ts-ignore
-					let a = ast.elements
+					let aaa = ast.elements
 						.reduce(function (a, item: AST.Node & INodePlus)
 						{
 							let s = astToString(item, options);
 
 							if (do_unique
 								&& item.type == 'CharacterClassRange'
@@ -213,13 +213,13 @@
 						{
 							let last_is_emoji: boolean;
 							let last_is_zwj: boolean;
 
 							let EMOJI_SPLIT = new RegExp('(' + EMOJI_REGEX.source + ')', EMOJI_REGEX.flags);
 
-							a = a.reduce(function (a, b: string)
+							aaa = aaa.reduce(function (a, b: string)
 							{
 								let current_is_zwj = /\u200D/.test(b);
 								let current_is_emoji = EmojiRegex().test(b);
 
 								if (last_is_emoji)
 								{
@@ -252,22 +252,22 @@
 								return a;
 							}, []);
 						}
 
 						if (do_unique)
 						{
-							a = array_unique(a);
+							aaa = array_unique(aaa);
 						}
 
 						if (options.sortClass)
 						{
-							a.sort();
+							aaa.sort();
 						}
 					}
 
-					source = a.join('');
+					source = aaa.join('');
 
 					switch (ast.type)
 					{
 						case 'CapturingGroup':
 							source = '(' + source + ')';
 							break;

How Do We Reproduce?

sourceMap url through terserOptions does not working

  • Operating System: Linux
  • Node Version: 8
  • webpack Version: 4.29.6
  • terser-webpack-plugin Version: 1.2.3

Expected Behavior

I am using the following to generate a customized sourceMappingURL according to terserOptions section

// webpack.config.js
 // ......
  new TerserPlugin({
    sourceMap: true,
    terserOptions: {
      sourceMap: {
        file: '[name].map',
        url: 'https://my-host/[url]'
      }
    }
  }),
//....

I am expecting the source code to have the following at the bottom of the minified source code:

//# sourceMappingURL=https://my-host/app.xxxxxxx.js.map

Actual Behavior

//# sourceMappingURL=app.xxxxxxx.js.map

Does terser-webpack-plugin ever support sourceMap option in terserOptions ?

Thanks!

Error after minification: TypeError: Cannot read property 'match' of undefined

  • Operating System: Win 10
  • Node Version: 8.11.1
  • NPM Version: 5.6.0 (yarn 1.10.1)
  • Yarn Version: 1.10.1
  • webpack Version: 4.27.1
  • terser-webpack-plugin Version: 1.1.0

Expected Behavior

No errors

Actual Behavior

Error in response to identity.launchWebAuthFlow: TypeError: Cannot read property 'match' of undefined

Code

  // webpack.config.js
  // only this part causes the error
  optimization: {
        minimizer: [new TerserPlugin()],
        minimize: !dev  // if dev === true - everything works fine
    }

How Do We Reproduce?

add somewhere in code

const string = 'your-string-here?code=qhf9832hf92h2f3'
string.match(/\?code=(.+)$/i)[1];

and it will cause this error

Cannot mangle after add mangle option

  • Operating System:MacOS 10.13.6
  • Node Version:10.13.0
  • NPM Version: latest
  • webpack Version:4 ( latest )
  • terser-webpack-plugin Version:1( latest )

Expected Behavior

mangled

Actual Behavior

not mangled

Code

optimization: {
    minimizer: process.env.E2E_BUILD
      ? []
      : [
          new TerserPlugin({
            parallel: true,
            sourceMap: false,
            cache: true,
            terserOptions: {
              mangle: true
            }
          }),
          new OptimizeCSSAssetsPlugin({
            cssProcessorOptions: {
              map: {
                inline: false,
                annotation: true
              }
            }
          })
        ]
  },

How Do We Reproduce?

https://github.com/electron-react-boilerplate/electron-react-boilerplate.git
replace the webpack prod configs with code above

impossible to keep the name of a function

I can not save the name of a function, these are my options

new TerserPlugin({
                extractComments: false,
                terserOptions: {
                    compress:{
                        keep_fnames: /gtag_report_conversion/,
                    },
                    mangle: {
                        keep_fnames: /gtag_report_conversion/,
                        reserved: ['gtag_report_conversion']
                    },
                    output: {
                        preamble: banner,
                        comments: false
                    }
                }
            }),

Why don't we have the option reserved in compress?

any idea?

Plugin should update `contenthash` after minification

This is a behavior that was probably in place forever with uglify hence it remains with terser as well.

versions

  • webpack Version: 4.20.1
  • terser-webpack-plugin Version: 1.1.0

config

    output: {
        filename = 'myprefix.[name].[contenthash].js',
        chunkFilename = 'myprefix.[name].[contenthash].js'
    },
    optimization: {
-       minimize: false,
+       minimize: true,
        minimizer: [new TerserPlugin()],
    }

Expected Behavior

  • When minification is on, contenthash of the output files should be different compared to when it is off

Actual Behavior

  • Regardless if minification is on or off, same contenthash is generated. i.e. file names are the same

This is problematic in case of scenario of upgrading the minificator.

  • Since minification has no impact on the final file name, minifying with plugin version N vs plugin version N+1 might yield different content out of the same input file, yet same file name.
  • Problematic in scope of long term caching, particularly in case of a bug in minificator. This can yield weird problems in deployment pipelines, CDNs etc. or lead to situation where different users have file with same name but different contents, depending on when they access the files and how the caching headers are configured.

To sum up, hard to diagnose bugs can happen if you're not aware of this issue.

According to webpack/webpack#7483 (comment)

plugin should regenerate contenthash if they change content of file

Webpack v3 support

First off: I'm a huge fan of the plugin and Terser in general. It's always nice when things run faster and produce better results.

Feature Proposal

I know the issue title is probably going to elicit some groans, but it doesn't seem like much is preventing this plugin from working on Webpack v3. I think it might just involve modifying the index file like so:

if (compiler.hooks) {
  ...
} else {
  compiler.plugin('compilation', (compilation) => {
    if (this.options.sourceMap) {
      compilation.plugin('build-module', buildModuleFn);
    }
    compilation.plugin('optimize-chunk-assets', optimizeFn.bind(this, compilation));
  });
}

We'd lose out on the contenthash regeneration, but I don't think that's breaking for Webpack v3 users (or at least, we're used to the problem).

For those of us stuck with older versions of Webpack, this would significantly improve our build times and give us a sample of the benefits of v4!

I'd be happy to open a PR to make the needed changes if the idea seems appealing.

Feature Use Case

This would be very helpful for developers stuck in the year 2016.

Provide Typings

  • Operating System: Windows
  • Node Version: 9.8.0
  • NPM Version: 6.4.1
  • webpack Version: 4.25.1
  • terser-webpack-plugin Version: 1.1.0

Feature Proposal

Please provide Typescript bindings

Feature Use Case

Use typings when using typescript for configuring webpack.

[Question] how do remove console.log

  • Operating System:
  • Node Version: 11
  • NPM Version: 6
  • webpack Version: 4
  • terser-webpack-plugin Version: master

Feature Proposal

remove console log

Feature Use Case

remove console.log in production like it was possible with uglify webpack plugin

Terser Plugin Invalid Options -- chunkFilter

Documentation Is:

  • Missing
  • Needed
  • Confusing
  • Not Sure?
  • Not Working

Please Explain in Detail...

This Example

module.exports = {
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        chunkFilter: (chunk) => {
          // Exclude uglification for the `vendor` chunk
          if (chunk.name === 'vendor') {
            return false;
          }
          return true;
        }
      }),
    ],
  },
};

produces this output

> webpack --config webpack.prod.js

Terser Plugin Invalid Options

options should NOT have additional properties

ValidationError: Terser Plugin Invalid Options
    at validateOptions (/Users/jtorres/Desktop/experiments/testProy/node_modules/schema-utils/src/validateOptions.js:32:11)
    at new TerserPlugin (/Users/jtorres/Desktop/experiments/testProy/node_modules/terser-webpack-plugin/dist/index.js:48:31)
    at Object.<anonymous> (/Users/jtorres/Desktop/experiments/testProy/webpack.prod.js:10:7)
    at Module._compile (/Users/jtorres/Desktop/experiments/testProy/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:718:10)
    at Module.load (internal/modules/cjs/loader.js:605:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:544:12)
    at Function.Module._load (internal/modules/cjs/loader.js:536:3)
    at Module.require (internal/modules/cjs/loader.js:643:17)
    at require (/Users/jtorres/Desktop/experiments/testProy/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `webpack --config webpack.prod.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/jtorres/.npm/_logs/2018-12-20T22_06_12_647Z-debug.log

Unused tagged template literals produce invalid minified code

  • Operating System: macOS 10.12.6
  • Node Version: v10.14.2
  • NPM Version: 6.8.0
  • webpack Version: 4.29.6 (bug first appeared in 4.26.0 with the switch to terser)
  • terser-webpack-plugin Version: 1.2.3

Expected Behavior

Webpack production mode emits valid javascript that can be executed by a browser. E.g.

(function(e){return e})`one`

Actual Behavior

Webpack production mode is emitting invalid javascript. Specifically it's emitting an unnamed function (i.e. function() {...}) that is not syntactically valid. E.g.

function(e){return e}`one`

Code

webpack.config.js

module.exports = {
  mode: "production",
  entry: `${__dirname}/src/index.js`,
  output: {
    path: `${__dirname}/build`,
    filename: "repro.min.js"
  }
};

src/index.js

function tpl(str) {
  return str;
}

const unused = tpl`one`;

// Uncomment the line below to work around the bug:
// const anotherUnused = tpl`two`;

build/repro.min.js (webpack default wrappers removed for clarity)

function(e){return e}`one`

You can see that a single unused tagged template literal is producing an unnamed function error. It can be worked around by referencing the template literal function multiple times but wasn't a bug before terser was introduced as the minification engine for webpack.

Interestingly enough, I was not able to reproduce the bug in terser (v3.16.1), which leads me to believe the bug exists in this plugin.

How Do We Reproduce?

I've created a really small repo which should help you reproduce the issue (instructions assume you're on a mac since it uses the open command to open the index file in a browser):

git clone [email protected]:jondlm/webpack-template-literal-bug.git
cd webpack-template-literal-bug
npm install
npm start

Make extractComments API more consistent

  • terser-webpack-plugin Version: 1.1.0

Expected Behavior / Situation

passing

new TerserPlugin({
  extractComments: true
})

should behave the same as

new TerserPlugin({
  extractComments: {
    condition: true
  }
})

Actual Behavior / Situation

The first case makes condition equal some and the second case makes condition equal all

Modification Proposal

Modify the second case to also equal some (or vice-versa)

webpack build freezing when using terser

Sorry for not following the template, but I don't have all the information. @StefanSchoof will come and complete the issue and I'll edit in the information.

Expected Behavior

The build should finish.

Actual Behavior

Webpack freezes for at least 60 minutes (the build times out).

Code

switch.js:

"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const msRestAzure = __importStar(require("ms-rest-azure"));
const azure_keyvault_1 = require("azure-keyvault");
async function getConnectionString() {
    const cred = msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' });
    const client = new azure_keyvault_1.KeyVaultClient(await cred);
    const secret = await client.getSecret(process.env.KEYVAULT_URI, 'iotHubConnectionString', '');
    return secret.value;
}
exports.getConnectionString = getConnectionString;

webpack config:

const path = require('path');

module.exports = {
    mode: 'production',
    target: 'node',
    entry: {
        'switch': './switch.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name]/[name].js',
        libraryTarget: 'commonjs2'
    },
    resolve: {
        extensions: ['.ts', '.js', '.json'],
        modules: [
            'node_modules',
            'src'
        ]
    },
}

How Do We Reproduce?

run NODE_ENV=production webpack with the above config and entry file

⛄ original issue link here

Reuses variables causing undefined

  • Operating System: Windows 10
  • Node Version: 10.15.3
  • NPM Version: 6.4.1
  • webpack Version: 4.27.1
  • terser-webpack-plugin Version: 1.2.3

Expected Behavior

We inject a variable using angularJS, and re-use it later in the code. Without minification it works.
Problem is I can't supply too much information. Just taught i might tell you, you have a variable collission issue.

Actual Behavior

The minifier creates a function var n, and then inside the function where it is used a new local var n, which is undefined and assigns n to n, causing it to be undefined if minified.
However if we enable sourcemap-cheap-eval, it does work.

Code

This is var too complex or big with file-loaders etc. But for the terser it's at:

devtool: APP_ENV === 'development'
		? 'cheap-module-eval-source-map'	// Source maps + reference to source map file for development
		: 'hidden-source-map',				// Source maps without reference to source map file in original source for production

How Do We Reproduce?

I have no clue,

all i can tell you is this is our code

AdvertiserMaterialDetailModalController.$inject = [
	'$rootScope',
	'$scope',
	'adId',
	'AdvertiserMaterialDetailModal',
	'campaignId',
	'DataAdvertisersMaterialAds',
	'DataAdvertisersPrograms',
	'ElementsMessagesHelper',
	'PreviewBannerEvent'
];

function AdvertiserMaterialDetailModalController(
	$rootScope,
	$scope,
	adId,
	AdvertiserMaterialDetailModal,
	campaignId,
	DataAdvertisersMaterialAds,
	DataAdvertisersPrograms,
	ElementsMessagesHelper,
	PreviewBannerEvent
) {

	let $ctrl = this;
	let _watches = [];
	let _adId = adId;

	$ctrl.ad = null;
	$ctrl.bannerContentLoaded = false;
	$ctrl.bannerIsExpanded = false;
	$ctrl.campaign = null;
	$ctrl.messageHelper = ElementsMessagesHelper.getInstance('newsMessages');

	$ctrl.close = close;
	$ctrl.getBannerHeight = getBannerHeight;

	$ctrl.$onInit = onInit;

	function onInit() {
		$scope.$on('$destroy', onDestroy);
		addWatches();
		loadData();
	}

	function getBannerHeight(){
		return $ctrl.ad.height + 40 + 'px';
	}

	function loadData() {
		startLoader();
		loadAd(_adId)
			.then(loadCampaign)
			.then(setCampaignData)
			.catch($ctrl.messageHelper.errorFunction)
			.finally(stopLoader);
	}

	function startLoader() {
		$ctrl.showLoading = true;
	}

	function stopLoader() {
		$ctrl.showLoading = false;
	}

	function loadAd( adId ) {
		return DataAdvertisersMaterialAds.getById( adId );
	}

	function loadCampaign( response ) {
		$ctrl.ad = response;
		return DataAdvertisersPrograms.getById( campaignId );
	}

	function setCampaignData( response ) {
		$ctrl.campaign = response;
		return response;
	}

	function close() {
		AdvertiserMaterialDetailModal.hide();
	}

	function expandBanner(event, ad) {
		if (ad.id === $ctrl.ad.id) {
			$ctrl.bannerIsExpanded = true;
		}
	}

	function collapseBanner(event, ad) {
		if (ad.id === $ctrl.ad.id) {
			$ctrl.bannerIsExpanded = false;
		}
	}

	function bannerContentLoaded(event, ad) {
		if ($ctrl.ad && ad.id === $ctrl.ad.id) {
			$ctrl.bannerContentLoaded = true;
		}
	}

	function addWatches() {
		_watches.push($rootScope.$on(PreviewBannerEvent.EVENT_EXPAND, expandBanner));
		_watches.push($rootScope.$on(PreviewBannerEvent.EVENT_COLLAPSE, collapseBanner));
		_watches.push($rootScope.$on(PreviewBannerEvent.EVENT_BANNER_CONTENT_LOADED, bannerContentLoaded));
	}

	function onDestroy() {
		_watches.map( function( watch ) {
			watch();
		} );
		_watches = null;
		ElementsMessagesHelper.destroyInstance($ctrl.messageHelper);
	}

}

and this is the minified result

function a(e, t, n, i, a, s, r, o, l) {
        var c = this
          , d = [];
        function u() {
            c.showLoading = !1
        }
        function p(e) {
            return c.ad = e,
            r.getById(a)
        }
        function m(e) {
            return c.campaign = e,
            e
        }
        function g(e, t) {
            t.id === c.ad.id && (c.bannerIsExpanded = !0)
        }
        function h(e, t) {
            t.id === c.ad.id && (c.bannerIsExpanded = !1)
        }
        function f(e, t) {
            c.ad && t.id === c.ad.id && (c.bannerContentLoaded = !0)
        }
        function v() {
            d.map(function(e) {
                e()
            }),
            d = null,
            o.destroyInstance(c.messageHelper)
        }
        c.ad = null,
        c.bannerContentLoaded = !1,
        c.bannerIsExpanded = !1,
        c.campaign = null,
        c.messageHelper = o.getInstance("newsMessages"),
        c.close = function() {
            i.hide()
        }
        ,
        c.getBannerHeight = function() {
            return c.ad.height + 40 + "px"
        }
        ,
        c.$onInit = function() {
            t.$on("$destroy", v),
            d.push(e.$on(l.EVENT_EXPAND, g)),
            d.push(e.$on(l.EVENT_COLLAPSE, h)),
            d.push(e.$on(l.EVENT_BANNER_CONTENT_LOADED, f)),
            c.showLoading = !0,
            (n = n,
            s.getById(n)).then(p).then(m).catch(c.messageHelper.errorFunction).finally(u);
            var n
        }
    }

As you can see at the top, n is a top function argument
As you can see at the bottom in c.$onInit, loadData is injected here, var n is declared.

sourceMap section should explain which sourceMaps are compatible

Documentation Is:

  • Missing
  • Needed
  • Confusing
  • Not Sure?

Please Explain in Detail...

The sourceMaps section of the README includes the warning:

⚠️ cheap-source-map options don't work with this plugin.

This doesn't include any recommendations for alternatives or reasons why it doesn't work with the plugin.

Your Proposal for Changes

Please include a list of supported source maps or at least the family of source maps that are supported in the docs.

Change 'cache' and 'parallel' defaults to 'true'

  • Operating System: Windows 10
  • Node Version: 10.9.0
  • NPM Version: N/A (yarn)
  • webpack Version: 4.16.5
  • terser-webpack-plugin Version: 1.0.2

Feature Proposal

Currently terser-webpack-plugin has the cache and parallel settings set to false by default. I propose that they be changed to true by default instead.

Feature Use Case

webpack 4 already sets those two settings to true by default for uglifyjs-webpack-plugin (see here). Changing the defaults in terser-webpack-plugin will:

  • reduce the amount of boilerplate required in the webpack repo when it eventually switches over to terser-webpack-plugin
  • make it simpler for people overriding the default webpack optimization.minimizer, since they also will have less boilerplate, but also will be less likely to accidentally forget to enable these two important performance-boosting settings

Changing the defaults for these settings will require a major version bump, but now seems like a better time to do so, than after webpack has already started using it.

Cache filenames can cause "path too long" errors on Windows

  • Operating System: Windows 2012/10
  • Node Version: 10.14.1
  • NPM Version: 6.4.1
  • webpack Version: 4.27.1
  • terser-webpack-plugin Version: 1.1.0

Expected Behavior / Situation

Unfortunately, Windows has a maximum path length of 260 characters. I'd like to see the terser-webpack-plugin cache files with names friendlier to Windows' file system.

Actual Behavior / Situation

Files in the cache directory have file names whose names are 124 characters, using up almost half of the available characters. This causes sporadic problems for us deploying, depending on where/how we're deploying. One of our app packages has a cached file whose path is package\node_modules\.cache\terser-webpack-plugin\content-v2\sha512\6d\4f\92533bbffcef2fd2ad4468c4c440e1c47d7d5a2860db0763fda881a868123115a98406fce6736831807f479dbc0812154b748630029f31c8695e17dd6b4a. Yikes!

In our situation, our deployment tool deploys all our packages into a temp directory that for one app is 70 characters long. It fails to unpack the package when it gets to ``package\node_modules.cache\terser-webpack-plugin\content-v2\sha512\6d\4f\92533bbffcef2fd2ad4468c4c440e1c47d7d5a2860db0763fda881a868123115a98406fce6736831807f479dbc0812154b748630029f31c8695e17dd6b4a` because that is 198 characters long.

Modification Proposal

I'd like to see terser-webpack-plugin use a shorter filename than 92533bbffcef2fd2ad4468c4c440e1c47d7d5a2860db0763fda881a868123115a98406fce6736831807f479dbc0812154b748630029f31c8695e17dd6b4a. Maybe trim to 38 characters? Or use a hashing algorithm that results in shorter hashes?

Migrate on `serialize-to-js` for serializing

  • Operating System: no matter
  • Node Version: no matter
  • NPM Version: no matter
  • webpack Version: no matter
  • terser-webpack-plugin Version: latest

Feature Proposal

Use serialize-to-js for serialize

Feature Use Case

Above

let versus var Treeshaking Issue Caused By Terser

  • Operating System: Ubuntu 16.04.5
  • Node Version: v10.14.2
  • NPM Version: 6.70
  • webpack Version: 4.29
  • terser-webpack-plugin Version: 1.10

I've been advised that a Tree-shaking issue I'm having in Webpack may be being caused by terser:
webpack/webpack#8692 (comment)

If you scroll up from that comment, you can see the entire issue.

I'm I submitting this at the correct place?

Function call disappear if there is a comment above it

  • Operating System: Windows 10
  • Node Version: v10.9.0
  • NPM Version: 6.4.1
  • webpack Version: 4.29.6
  • terser-webpack-plugin Version: 1.2.3

Expected Behavior

The registerCmd function call should not disappear when there is a comment above it

Actual Behavior

The registerCmd function call disappears from the output

Code

/*registerCmd("cal", function(argv) { // Old code
   // ... 142 lines of private code
}, "cal - Shows a calendar")*/

registerCmd("cal", function(argv) { // New code
   // ... 154 lines of private code
}, "cal - Shows a calendar")
const TerserPlugin = require('terser-webpack-plugin');
// ...
new TerserPlugin({
    terserOptions: {
        mangle: true,
        output: {
            comments: /@license/i
        },
        ecma: 8,
        compress: {
            unsafe: true,
            sequences: true,
            passes: 5
        },
        parallel: true
    },
    parallel: true
})

How Do We Reproduce?

Cannot provide a repo because my project is closed source

unexpected errors with extractComments + parallel

I get unexpected errors using extractComments and parallel together.

ERROR  Failed to compile with 33 errors


error

d8a0e40.js from Terser
undefined

error

4f63931.js from Terser
undefined

error

51b0352.js from Terser
undefined
...

I wondering if the issue may come from:

taskRunner.run(tasks, (tasksError, results) => {

results is {"error":{},"extractedComments":[]}

then:

if (error || warnings && warnings.length > 0)

if "error":{} mean no error, the previous test will always pass

  • Operating System: win7
  • Node Version: 10.10
  • webpack Version: 4.23.1
  • terser-webpack-plugin Version: 1.1.0

Publish to npm

Hi,

I know you're probably busy with setting everything up, but is the plugin ready to be published to npm?
Can you estimate, when the first release will be?

Thanks for your great work 💪

Error: Cannot find module 'terser'

  • Operating System: Arch Linux, Travis CI, Ubuntu
  • Node Version: 10.12.0
  • NPM Version: 6.4.1
  • webpack Version: 4.26.0
  • terser-webpack-plugin Version: 1.1.0

Expected Behavior

Webpack builds without problem

Actual Behavior

$ webpack -p --env=staging --progress
/home/dori/Projects/work/company/project/repo/node_modules/webpack-cli/bin/cli.js:244
                                throw err;
                                ^

Error: Cannot find module 'terser'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
    at Function.Module._load (internal/modules/cjs/loader.js:506:25)
    at Module.require (internal/modules/cjs/loader.js:636:17)
    at require (/home/dori/Projects/work/company/project/repo/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at Object.<anonymous> (/home/dori/Projects/work/company/project/repo/node_modules/terser-webpack-plugin/dist/minify.js:7:15)
    at Module._compile 
…
    at require (/home/dori/Projects/work/company/project/repo/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at Object.<anonymous> (/home/dori/Projects/work/company/project/repo/node_modules/terser-webpack-plugin/dist/cjs.js:3:16)
    at Module._compile (/home/dori/Projects/work/company/project/repo/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Code

  // webpack.config.js
import TerserPlugin from "terser-webpack-plugin";


export default {
  optimization: {
    minimizer: isProduction
      ? [
          new TerserPlugin({
            cache: true,
            extractComments: true,
            parallel: true,
            terserOptions: {
              toplevel: true,
              compress: {
                passes: 3,
                pure_getters: true,
                unsafe: false,
              },
            },
          }),
        ]
      : [],
    runtimeChunk: isProduction,
    splitChunks: isProduction ? {chunks: "all", maxSize: 1200000} : false,
  },};

How Do We Reproduce?

What I noticed:

  • only terser-webpack-plugin": "1.1.0", in package.json → fail
  • also install "terser": "3.10.11", next to it → WORKS
  • upgrade terser to 3.10.12 → fails

Checking your package.json, I see a dependency to terser@^3.8.1

That raises 2 questions:

  • Why do I need to install terser next to terser-webpack-plugin if the latter already has a version of terser in its dependencies ?
  • If terser-webpack-plugin was relying on terser 3.8.X and subsequent minor releases added breaking changes, I'd understand, but how come v3.10.11 works and not 3.10.12 ?

Out of memory

  • Operating System: MacOSX 10.12.6
  • Node Version: v11.0.0
  • NPM Version: 6.4.1
  • webpack Version: 4.23.1
  • terser-webpack-plugin Version: 1.1.0

Expected Behavior

Builds finishes

Actual Behavior

Crashes with out of memory

Code

Not applicable

How Do We Reproduce?

Hard to provide, but it happens on big apps.


The app I'm working crashes with out of memory when compiling. If I disable the minification, it finishes. This seems to be related with webpack-contrib/uglifyjs-webpack-plugin#276. Perhaps we can port that fix here?

`keep_classnames` ValidationError: Terser Plugin Invalid Options

webpack 4.26.1
terser-webpack-plugin: 1.1.0

use config:

                new TerserPlugin({
                    cache: true,
                    parallel: true,
                    sourceMap: true,
                    keep_classnames: undefined,
                })

error log:

Terser Plugin Invalid Options

options should NOT have additional properties

ValidationError: Terser Plugin Invalid Options
    at validateOptions (\node_modules\terser-webpack-plugin\node_modules\schema-utils\src\validateOptions.js:32:11)
    at new TerserPlugin (\node_modules\terser-webpack-plugin\dist\index.js:48:31)
    at Object.<anonymous> (\config\webpack.prod.ts:14:17)
    at Module._compile (r\node_modules\v8-compile-cache\v8-compile-cache.js:178:30)
    at Module.m._compile (\node_modules\ts-node\src\index.ts:439:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Object.require.extensions.(anonymous function) [as .ts] (\node_modules\ts-node\src\index.ts:442:12)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (\node_modules\v8-compile-cache\v8-compile-cache.js:159:20)

Excluding directories does not work

I can not exclude directories, I tried the usual regexes that work with webpack e.g. /\/src/ or /.*templates.*/ and or variations. Apart from /*/ which should be equivalent to /\/src/ none of what I tried seems to work.

  • Operating System: Linux
  • Node Version: v11.2.0
  • NPM Version: 6.4.1
  • webpack Version: 4.25.1
  • terser-webpack-plugin Version: 1.1.0

Remove js comments

Seems it's not possible to remove all comments when build but only extract these.

Webpack build hangs with parallel: true

  • Operating System: Windows 10 1810, WSL, Ubuntu 18.04
  • Node Version: 8.12.0
  • NPM Version: 6.4.1
  • webpack Version: 4.19.1
  • terser-webpack-plugin Version: 1.1.0

Expected Behavior

That the webpack build completes

Actual Behavior

The webpack build hangs forever (or at least 30 minutes which is the longest I have lasted) after outputting

Compilation  starting…

However changing parallel: true to parallel: false in terser options will cause the build to complete in normal time (around 40s)

Code

new TerserPlugin({
        terserOptions: {
          parse: {
            // we want terser to parse ecma 8 code. However, we don't want it
            // to apply any minfication steps that turns valid ecma 5 code
            // into invalid ecma 5 code. This is why the 'compress' and 'output'
            // sections only apply transformations that are ecma 5 safe
            // https://github.com/facebook/create-react-app/pull/4234
            ecma: 8
          },
          compress: {
            ecma: 5,
            warnings: false,
            // Disabled because of an issue with Uglify breaking seemingly valid code:
            // https://github.com/facebook/create-react-app/issues/2376
            // Pending further investigation:
            // https://github.com/mishoo/UglifyJS2/issues/2011
            comparisons: false,
            // Disabled because of an issue with Terser breaking valid code:
            // https://github.com/facebook/create-react-app/issues/5250
            // Pending futher investigation:
            // https://github.com/terser-js/terser/issues/120
            inline: 2
          },
          mangle: {
            safari10: true
          },
          output: {
            ecma: 5,
            comments: false,
            // Turned on because emoji and regex is not minified properly using default
            // https://github.com/facebook/create-react-app/issues/2488
            ascii_only: true
          }
        },
        // Use multi-process parallel running to improve the build speed
        // Default number of concurrent runs: os.cpus().length - 1
        parallel: true,
        // Enable file caching
        cache: true,
        sourceMap: shouldUseSourceMap
      })

Full webpack config: https://github.com/Pajn/tscomp/blob/cra2/config/webpack.config.prod.js

How Do We Reproduce?

I suspect this can be related to WSL. If you have some debugging tips I can probably run them.

For the exact same state as I have:

  1. Clone https://github.com/Pajn/tscomp
  2. git checkout terser-bug
  3. Clone https://github.com/Pajn/RAXA
  4. cd RAXA/packages/web
  5. yarn
  6. yarn add --dev path/to/cloned/tscomp/repo
  7. yarn build, or for more information NODE_ENV=production webpack --config node_modules/tscomp/config/webpack.config.prod.js --verbose --info-verbosity verbose --display verbose --profile

fallback for `find-cache-dir`

  • Operating System: no matter
  • Node Version: no matter
  • NPM Version: no matter
  • webpack Version: no matter
  • terser-webpack-plugin Version: latest

Expected Behavior

find-cache-dir can return null so we need fallback for this using os.tmpdir()

Actual Behavior

No fallback

Code

No need

How Do We Reproduce?

It is hard, but in theory can happens

optimized function changes behavour

  • Operating System: Mac OS
  • Node Version: 11.9.0
  • NPM Version: 6.8.0
  • webpack Version: 4.29.5
  • terser-webpack-plugin Version: 1.2.3

Expected Behavior

function should behave like non minimized one.

Actual Behavior

Terser plugin overoptimize function and changes it return params.

Code

module.exports = (function(constructor) {
  return constructor();
})(function() {
  return function(input) {
    var keyToMap = input.key;
    return {
      mappedKey: (function(value) {
        return value || "CONDITIONAL_DEFAULT_VALUE";
      })(keyToMap)
    };
  };
});

How Do We Reproduce?

https://github.com/roblan/webpack_terser_bug/tree/master

Issue with Edge not respecting TerserOptions

I have a piece of code that relies on function.prototype.name like so

public typeIs<TNewType>(newTypeAssertion: new (...args: any[]) => TNewType) {
    this.stringValue = `TypeIs:${newTypeAssertion.name}`
    this.segmentType = 'typeIs'
    return this.finialize<TNewType>()
  }

Initially my terser options didn't set keep_fnames to true and that caused my web application in both chrome and edge to not function properly. Now it looks like this.

minimizer: [
        new TerserPlugin({
          cache: true,
          parallel: true,
          terserOptions: {
            keep_fnames: true // This is so that the typeIs function works in production.
          }
        })
      ],

And now the function name does not get mangle in chrome but still somehow gets mangled in edge even with keep_fnames set to true. I did find a solution by doing this

minimizer: [
        new TerserPlugin({
          cache: true,
          parallel: true,
          terserOptions: {
            keep_fnames: true // This is so that the typeIs function works in production.
            compress: false // Now newTypeAssertion.name does not get mangled in edge as well.
          }
        })
      ],

But I don't want to do that because my bundle would increase quite a bit. Any clue as to why edge still mangles the function name and why setting compress to false works?

feat: keepOriginalAssets

  • Operating System: no matter
  • Node Version: no matter
  • NPM Version: no matter
  • webpack Version: no matter
  • terser-webpack-plugin Version: no matter

Feature Proposal

Allow keep original assets and minimizer, it is simplify usage for libraries

Feature Use Case

Simplest webpack build crash

  • Operating System: Linux Mint 19
  • Node Version: v10.5.0
  • NPM Version: 6.1.0
  • webpack Version: 4.29.0
  • terser-webpack-plugin Version:[email protected]

Expected Behavior

Simplest webpack app should be able to build.

Actual Behavior

Fails with error:

ERROR in main.js from Terser
TypeError: Cannot read property 'minify' of undefined
    at minify (/home/chango/Proyectos/Chango/React/webpack-4-quickstart/node_modules/terser-webpack-plugin/dist/minify.js:176:23)
    at module.exports (/home/chango/Proyectos/Chango/React/webpack-4-quickstart/node_modules/terser-webpack-plugin/dist/worker.js:13:40)
    at handle (/home/chango/Proyectos/Chango/React/webpack-4-quickstart/node_modules/worker-farm/lib/child/index.js:44:8)
    at process.<anonymous> (/home/chango/Proyectos/Chango/React/webpack-4-quickstart/node_modules/worker-farm/lib/child/index.js:51:3)
    at process.emit (events.js:182:13)
    at emit (internal/child_process.js:811:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

Code

  // webpack.config.js
{
  "name": "webpack-4-quickstart",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1"
  }
}

How Do We Reproduce?

On an empty folder run the following:

$ npm init -y
$ npm i webpack --save-dev
$ npm i webpack-cli --save-dev
$ mkdir src && echo "console.log('Entry point');" > src/index.js

Modify package.json:

"scripts": {
    "build": "webpack"
  },

$ npm run build

feat: migrate on jest-worker

  • Operating System: no matter
  • Node Version: no matter
  • NPM Version: no matter
  • webpack Version: no matter
  • terser-webpack-plugin Version: no matter

Feature Proposal

use jest-worker instead worker-farm

Feature Use Case

Better supporting all platforms (include WSL), faster and allow to use native parallel module

Add TERSER_NO_BUNDLE environmental variable to cache keys

  • Operating System: any
  • Node Version: any
  • NPM Version: any
  • webpack Version: any
  • terser-webpack-plugin Version: latest

Feature Proposal

The proposal is to add $TERSER_NO_BUNDLE to the cache keys. When set to 1, it changes the behaviour of terser by reading the source code in lib/ instead of dist/bundle.js

Feature Use Case

If TERSER_NO_BUNDLE is not part of the cache keys, then enabling it wouldn't break the cache, while terser behaviour would change. This variable makes it easy to debug issues with terser when not being used directly.

What are the implications of setting "cache" to true?

Documentation Is:

  • Missing
  • Needed
  • Confusing
  • Not Sure?

Please Explain in Detail...

Please just add a 1 liner explaining what a "cache" is in the context of minification.

In general I know what a cache is - some (local) storage of files/data to reuse for avoiding redundant regeneration of (if no changes exist) for faster build times. But if there were only benefits to adding a cache then why even include it as an option? What are the implications of setting cache to true (for the typical use case where someone isn't using a custom minify - or is that the only reason you might not want to)?

Your Proposal for Changes

Something like this:

Enable file caching. Default path to cache directory: node_modules/.cache/terser-webpack-plugin. Enabling this option will < improve build speed at the cost of...? >

...

Minify `.mjs` files by default

terser-webpack-plugin Version: 1.1.0 (latest)

Expected Behavior / Situation

.mjs should (perhaps?) be minified

Actual Behavior / Situation

.mjs files are not minified by default due to the default regex: https://github.com/webpack-contrib/terser-webpack-plugin/blob/v1.1.0/src/index.js#L25
One can pass test option via config to opt-in though.

Modification Proposal

Adding dozens of lines of config, one at a time, is never fun.
I think it should be safe to minimize .mjs by default and change the regex from /\.js(\?.*)?$/i to /\.m?js(\?.*)?$/i

WDYT?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.