Installations
npm install terser-webpack-plugin
Score
57.4
Supply Chain
70.8
Quality
80.7
Maintenance
100
Vulnerability
99.6
License
Developer
webpack-contrib
Developer Guide
Module System
CommonJS
Min. Node Version
>= 10.13.0
Typescript Support
Yes
Node Version
16.15.0
NPM Version
8.5.5
Statistics
1,951 Stars
372 Commits
157 Forks
20 Watching
7 Branches
47 Contributors
Updated on 28 Nov 2024
Bundle Size
816.98 kB
Minified
219.97 kB
Minified + Gzipped
Languages
JavaScript (99.93%)
Shell (0.07%)
Total Downloads
Cumulative downloads
Total Downloads
6,426,259,392
Last day
-7.4%
5,111,879
Compared to previous day
Last week
1.5%
29,269,344
Compared to previous week
Last month
9.3%
122,395,838
Compared to previous month
Last year
-12.8%
1,385,124,821
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Peer Dependencies
1
Dev Dependencies
33
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
:
1npm install terser-webpack-plugin --save-dev
or
1yarn add -D terser-webpack-plugin
or
1pnpm add -D terser-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
1const TerserPlugin = require("terser-webpack-plugin"); 2 3module.exports = { 4 optimization: { 5 minimize: true, 6 minimizer: [new TerserPlugin()], 7 }, 8};
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 ineval("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:
1type test = string | RegExp | Array<string | RegExp>;
Default: /\.m?js(\?.*)?$/i
Test to match files against.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 test: /\.js(\?.*)?$/i, 7 }), 8 ], 9 }, 10};
include
Type:
1type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 include: /\/includes/, 7 }), 8 ], 9 }, 10};
exclude
Type:
1type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 exclude: /\/excludes/, 7 }), 8 ], 9 }, 10};
parallel
Type:
1type 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
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 parallel: true, 7 }), 8 ], 9 }, 10};
number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 parallel: 4, 7 }), 8 ], 9 }, 10};
minify
Type:
1type minify = ( 2 input: { 3 [file: string]: string; 4 }, 5 sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined, 6 minifyOptions: { 7 module?: boolean | undefined; 8 ecma?: import("terser").ECMA | undefined; 9 }, 10 extractComments: 11 | boolean 12 | "all" 13 | "some" 14 | RegExp 15 | (( 16 astNode: any, 17 comment: { 18 value: string; 19 type: "comment1" | "comment2" | "comment3" | "comment4"; 20 pos: number; 21 line: number; 22 col: number; 23 } 24 ) => boolean) 25 | { 26 condition?: 27 | boolean 28 | "all" 29 | "some" 30 | RegExp 31 | (( 32 astNode: any, 33 comment: { 34 value: string; 35 type: "comment1" | "comment2" | "comment3" | "comment4"; 36 pos: number; 37 line: number; 38 col: number; 39 } 40 ) => boolean) 41 | undefined; 42 filename?: string | ((fileData: any) => string) | undefined; 43 banner?: 44 | string 45 | boolean 46 | ((commentsFile: string) => string) 47 | undefined; 48 } 49 | undefined 50) => Promise<{ 51 code: string; 52 map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined; 53 errors?: (string | Error)[] | undefined; 54 warnings?: (string | Error)[] | undefined; 55 extractedComments?: string[] | undefined; 56}>;
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
insideminify
function whenparallel
option enabled.
webpack.config.js
1// Can be async 2const minify = (input, sourceMap, minimizerOptions, extractsComments) => { 3 // The `minimizerOptions` option contains option from the `terserOptions` option 4 // You can use `minimizerOptions.myCustomOption` 5 6 // Custom logic for extract comments 7 const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module') 8 .minify(input, { 9 /* Your options for minification */ 10 }); 11 12 return { map, code, warnings: [], errors: [], extractedComments: [] }; 13}; 14 15// Used to regenerate `fullhash`/`chunkhash` between different implementation 16// 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 17// to avoid this you can provide version of your custom minimizer 18// You don't need if you use only `contenthash` 19minify.getMinimizerVersion = () => { 20 let packageJson; 21 22 try { 23 // eslint-disable-next-line global-require, import/no-extraneous-dependencies 24 packageJson = require("uglify-module/package.json"); 25 } catch (error) { 26 // Ignore 27 } 28 29 return packageJson && packageJson.version; 30}; 31 32module.exports = { 33 optimization: { 34 minimize: true, 35 minimizer: [ 36 new TerserPlugin({ 37 terserOptions: { 38 myCustomOption: true, 39 }, 40 minify, 41 }), 42 ], 43 }, 44};
terserOptions
Type:
1type terserOptions = { 2 compress?: boolean | CompressOptions; 3 ecma?: ECMA; 4 enclose?: boolean | string; 5 ie8?: boolean; 6 keep_classnames?: boolean | RegExp; 7 keep_fnames?: boolean | RegExp; 8 mangle?: boolean | MangleOptions; 9 module?: boolean; 10 nameCache?: object; 11 format?: FormatOptions; 12 /** @deprecated */ 13 output?: FormatOptions; 14 parse?: ParseOptions; 15 safari10?: boolean; 16 sourceMap?: boolean | SourceMapOptions; 17 toplevel?: boolean; 18};
Default: default
Terser options.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 terserOptions: { 7 ecma: undefined, 8 parse: {}, 9 compress: {}, 10 mangle: true, // Note `mangle.properties` is `false` by default. 11 module: false, 12 // Deprecated 13 output: null, 14 format: null, 15 toplevel: false, 16 nameCache: null, 17 ie8: false, 18 keep_classnames: undefined, 19 keep_fnames: false, 20 safari10: false, 21 }, 22 }), 23 ], 24 }, 25};
extractComments
Type:
1type extractComments = 2 | boolean 3 | string 4 | RegExp 5 | (( 6 astNode: any, 7 comment: { 8 value: string; 9 type: "comment1" | "comment2" | "comment3" | "comment4"; 10 pos: number; 11 line: number; 12 col: number; 13 } 14 ) => boolean) 15 | { 16 condition?: 17 | boolean 18 | "all" 19 | "some" 20 | RegExp 21 | (( 22 astNode: any, 23 comment: { 24 value: string; 25 type: "comment1" | "comment2" | "comment3" | "comment4"; 26 pos: number; 27 line: number; 28 col: number; 29 } 30 ) => boolean) 31 | undefined; 32 filename?: string | ((fileData: any) => string) | undefined; 33 banner?: 34 | string 35 | boolean 36 | ((commentsFile: string) => string) 37 | undefined; 38 };
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
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: true, 7 }), 8 ], 9 }, 10};
string
Extract all
or some
(use /^\**!|@preserve|@license|@cc_on/i
RegExp) comments.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: "all", 7 }), 8 ], 9 }, 10};
RegExp
All comments that match the given expression will be extracted to the separate file.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: /@extract/i, 7 }), 8 ], 9 }, 10};
function
All comments that match the given expression will be extracted to the separate file.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: (astNode, comment) => { 7 if (/@extract/i.test(comment.value)) { 8 return true; 9 } 10 11 return false; 12 }, 13 }), 14 ], 15 }, 16};
object
Allow to customize condition for extract comments, specify extracted file name and banner.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: { 7 condition: /^\**!|@preserve|@license|@cc_on/i, 8 filename: (fileData) => { 9 // The "fileData" argument contains object with "filename", "basename", "query" and "hash" 10 return `${fileData.filename}.LICENSE.txt${fileData.query}`; 11 }, 12 banner: (licenseFile) => { 13 return `License information can be found in ${licenseFile}`; 14 }, 15 }, 16 }), 17 ], 18 }, 19};
condition
Type:
1type condition = 2 | boolean 3 | "all" 4 | "some" 5 | RegExp 6 | (( 7 astNode: any, 8 comment: { 9 value: string; 10 type: "comment1" | "comment2" | "comment3" | "comment4"; 11 pos: number; 12 line: number; 13 col: number; 14 } 15 ) => boolean) 16 | undefined;
Condition what comments you need extract.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: { 7 condition: "some", 8 filename: (fileData) => { 9 // The "fileData" argument contains object with "filename", "basename", "query" and "hash" 10 return `${fileData.filename}.LICENSE.txt${fileData.query}`; 11 }, 12 banner: (licenseFile) => { 13 return `License information can be found in ${licenseFile}`; 14 }, 15 }, 16 }), 17 ], 18 }, 19};
filename
Type:
1type 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. Usingjs
/cjs
/mjs
extensions may conflict with existing assets which leads to broken code.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: { 7 condition: /^\**!|@preserve|@license|@cc_on/i, 8 filename: "extracted-comments.js", 9 banner: (licenseFile) => { 10 return `License information can be found in ${licenseFile}`; 11 }, 12 }, 13 }), 14 ], 15 }, 16};
banner
Type:
1type 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
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 extractComments: { 7 condition: true, 8 filename: (fileData) => { 9 // The "fileData" argument contains object with "filename", "basename", "query" and "hash" 10 return `${fileData.filename}.LICENSE.txt${fileData.query}`; 11 }, 12 banner: (commentsFile) => { 13 return `My custom banner about license information ${commentsFile}`; 14 }, 15 }, 16 }), 17 ], 18 }, 19};
Examples
Preserve Comments
Extract all legal comments (i.e. /^\**!|@preserve|@license|@cc_on/i
) and preserve /@license/i
comments.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 terserOptions: { 7 format: { 8 comments: /@license/i, 9 }, 10 }, 11 extractComments: true, 12 }), 13 ], 14 }, 15};
Remove Comments
If you avoid building with comments, use this config:
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 terserOptions: { 7 format: { 8 comments: false, 9 }, 10 }, 11 extractComments: false, 12 }), 13 ], 14 }, 15};
uglify-js
UglifyJS
is a JavaScript parser, minifier, compressor and beautifier toolkit.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 minify: TerserPlugin.uglifyJsMinify, 7 // `terserOptions` options will be passed to `uglify-js` 8 // Link to options - https://github.com/mishoo/UglifyJS#minify-options 9 terserOptions: {}, 10 }), 11 ], 12 }, 13};
swc
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
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 minify: TerserPlugin.swcMinify, 7 // `terserOptions` options will be passed to `swc` (`@swc/core`) 8 // Link to options - https://swc.rs/docs/config-js-minify 9 terserOptions: {}, 10 }), 11 ], 12 }, 13};
esbuild
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
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 minify: TerserPlugin.esbuildMinify, 7 // `terserOptions` options will be passed to `esbuild` 8 // Link to options - https://esbuild.github.io/api/#minify 9 // 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: 10 // terserOptions: { 11 // minify: false, 12 // minifyWhitespace: true, 13 // minifyIdentifiers: false, 14 // minifySyntax: true, 15 // }, 16 terserOptions: {}, 17 }), 18 ], 19 }, 20};
Custom Minify Function
Override default minify function - use uglify-js
for minification.
webpack.config.js
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 minify: (file, sourceMap) => { 7 // https://github.com/mishoo/UglifyJS2#minify-options 8 const uglifyJsOptions = { 9 /* your `uglify-js` package options */ 10 }; 11 12 if (sourceMap) { 13 uglifyJsOptions.sourceMap = { 14 content: sourceMap, 15 }; 16 } 17 18 return require("uglify-js").minify(file, uglifyJsOptions); 19 }, 20 }), 21 ], 22 }, 23};
Typescript
With default terser minify function:
1module.exports = { 2 optimization: { 3 minimize: true, 4 minimizer: [ 5 new TerserPlugin({ 6 terserOptions: { 7 compress: true, 8 }, 9 }), 10 ], 11 }, 12};
With built-in minify functions:
1import type { JsMinifyOptions as SwcOptions } from "@swc/core"; 2import type { MinifyOptions as UglifyJSOptions } from "uglify-js"; 3import type { TransformOptions as EsbuildOptions } from "esbuild"; 4import type { MinifyOptions as TerserOptions } from "terser"; 5 6module.exports = { 7 optimization: { 8 minimize: true, 9 minimizer: [ 10 new TerserPlugin<SwcOptions>({ 11 minify: TerserPlugin.swcMinify, 12 terserOptions: { 13 // `swc` options 14 }, 15 }), 16 new TerserPlugin<UglifyJSOptions>({ 17 minify: TerserPlugin.uglifyJsMinify, 18 terserOptions: { 19 // `uglif-js` options 20 }, 21 }), 22 new TerserPlugin<EsbuildOptions>({ 23 minify: TerserPlugin.esbuildMinify, 24 terserOptions: { 25 // `esbuild` options 26 }, 27 }), 28 29 // Alternative usage: 30 new TerserPlugin<TerserOptions>({ 31 minify: TerserPlugin.terserMinify, 32 terserOptions: { 33 // `terser` options 34 }, 35 }), 36 ], 37 }, 38};
Contributing
Please take a moment to read our contributing guidelines if you haven't yet done so.
License
No vulnerabilities found.
Reason
GitHub workflow tokens follow principle of least privilege
Details
- Info: topLevel 'contents' permission set to 'read': .github/workflows/dependency-review.yml:5
- Info: topLevel 'contents' permission set to 'read': .github/workflows/nodejs.yml:14
- Info: no jobLevel write permissions found
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
3 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-4vvj-4cpr-p986
Reason
Found 17/26 approved changesets -- score normalized to 6
Reason
dependency not pinned by hash detected -- score normalized to 3
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dependency-review.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/dependency-review.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dependency-review.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/dependency-review.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/nodejs.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/nodejs.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/nodejs.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:85: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/nodejs.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:96: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/nodejs.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/nodejs.yml:113: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/terser-webpack-plugin/nodejs.yml/master?enable=pin
- Warn: npmCommand not pinned by hash: .github/workflows/nodejs.yml:108
- Info: 0 out of 7 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 1 third-party GitHubAction dependencies pinned
- Info: 2 out of 3 npmCommand dependencies pinned
Reason
1 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 2
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 26 are checked with a SAST tool
Score
5.6
/10
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More