This plugin usesterser to minify/minimize your JavaScript.
Webpack v5 comes with the latestterser-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 installterser-webpack-plugin
.Using Webpack v4, you have to installterser-webpack-plugin
v4.
To begin, you'll need to installterser-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 yourwebpack
configuration. For example:
webpack.config.js
const TerserPlugin=require("terser-webpack-plugin");module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin()],},};
Finally, runwebpack
using the method you normally use (e.g., via CLI or an npm script).
Works only withsource-map
,inline-source-map
,hidden-source-map
andnosources-source-map
values for thedevtool
option.
Why?
eval
wraps modules ineval("string")
and the minimizer does not handle strings.cheap
has no column information and the minimizer generates only a single line, which leaves only a single mapping.Using supporteddevtool
values enable source map generation.
test
Type:
typetest=string| RegExp|Array<string| RegExp>;
Default:/\.m?js(\?.*)?$/i
Test to match files against.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ test:/\.js(\?.*)?$/i,}),],},};
include
Type:
typeinclude=string| RegExp|Array<string| RegExp>;
Default:undefined
Files to include.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ include:/\/includes/,}),],},};
exclude
Type:
typeexclude=string| RegExp|Array<string| RegExp>;
Default:undefined
Files to exclude.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ exclude:/\/excludes/,}),],},};
parallel
Type:
typeparallel=boolean|number;
Default:true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs:os.cpus().length - 1
oros.availableParallelism() - 1
(if this function is supported).
Note
Parallelization can speedup your build significantly and is thereforehighly recommended.
Warning
If you useCircle CI or any other environment that doesn't provide the real available count of CPUs then you need to explicitly set up the 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:[newTerserPlugin({ parallel:true,}),],},};
number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ parallel:4,}),],},};
minify
Type:
typeminify=( 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 the default minify function.By default plugin usesterser package.Useful for using and testing unpublished versions or forks.
Warning
Always use
require
insideminify
function whenparallel
option enabled.
webpack.config.js
// Can be asyncconstminify=(input, sourceMap, minimizerOptions, extractsComments)=>{// The `minimizerOptions` option contains option from the `terserOptions` option// You can use `minimizerOptions.myCustomOption`// Custom logic for extract commentsconst{ 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:[newTerserPlugin({ terserOptions:{ myCustomOption:true,}, minify,}),],},};
terserOptions
Type:
typeterserOptions={ 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
Terseroptions.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ 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:
typeextractComments=|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, (seedetails).
By default, extract only comments using/^\**!|@preserve|@license|@cc_on/i
RegExp condition and remove remaining comments.
If the original file is namedfoo.js
, then the comments will be stored tofoo.js.LICENSE.txt
.
TheterserOptions.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 preserve comments that have already been extracted.
boolean
Enable/disable extracting comments.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ extractComments:true,}),],},};
string
Extractall
orsome
(use the/^\**!|@preserve|@license|@cc_on/i
RegExp) comments.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ extractComments:"all",}),],},};
RegExp
All comments that match the given expression will be extracted to a separate file.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ extractComments:/@extract/i,}),],},};
function
All comments that match the given expression will be extracted to a separate file.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({extractComments:(astNode, comment)=>{if(/@extract/i.test(comment.value)){returntrue;}returnfalse;},}),],},};
object
Allows you to customize condition for extracting comments, and specify the extracted file name and banner.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ 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:
typecondition=|boolean|"all"|"some"| RegExp|(( astNode:any, comment:{ value:string;type:"comment1"|"comment2"|"comment3"|"comment4"; pos:number; line:number; col:number;})=>boolean)|undefined;
The condition that determines which comments should be extracted.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ 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:
typefilename=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:[newTerserPlugin({ extractComments:{ condition:/^\**!|@preserve|@license|@cc_on/i, filename:"extracted-comments.js",banner:(licenseFile)=>{return`License information can be found in${licenseFile}`;},},}),],},};
banner
Type:
typebanner=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 at the top of the original file.
It can befalse
(no banner), aString
, or afunction<(string) -> String>
that will be called with the filename where the extracted comments have been stored.
The banner will be wrapped in a comment.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ 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}`;},},}),],},};
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:[newTerserPlugin({ terserOptions:{ format:{ comments:/@license/i,},}, extractComments:true,}),],},};
If you want to build without comments, use this config:
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ terserOptions:{ format:{ comments:false,},}, extractComments:false,}),],},};
uglify-js
UglifyJS
is a JavaScript parser, minifier, compressor and beautifier toolkit.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ minify: TerserPlugin.uglifyJsMinify,// `terserOptions` options will be passed to `uglify-js`// Link to options - https://github.com/mishoo/UglifyJS#minify-options terserOptions:{},}),],},};
swc
swc
is a super-fast compiler written inRust
, producing widely supported JavaScript from modern standards and TypeScript.
Warning
The
extractComments
option is not supported, and all comments will be removed by default. This will be fixed in future
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ minify: TerserPlugin.swcMinify,// `terserOptions` options will be passed to `swc` (`@swc/core`)// Link to options - https://swc.rs/docs/config-js-minify terserOptions:{},}),],},};
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
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ 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:{},}),],},};
Override the default minify function - useuglify-js
for minification.
webpack.config.js
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({minify:(file, sourceMap)=>{// https://github.com/mishoo/UglifyJS2#minify-optionsconst uglifyJsOptions={/* your `uglify-js` package options */};if(sourceMap){ uglifyJsOptions.sourceMap={ content: sourceMap,};}returnrequire("uglify-js").minify(file, uglifyJsOptions);},}),],},};
With default Terser minify function:
module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin({ terserOptions:{ compress:true,},}),],},};
With built-in minify functions:
importtype{ JsMinifyOptionsas SwcOptions}from"@swc/core";importtype{ MinifyOptionsas UglifyJSOptions}from"uglify-js";importtype{ TransformOptionsas EsbuildOptions}from"esbuild";importtype{ MinifyOptionsas TerserOptions}from"terser";module.exports={ optimization:{ minimize:true, minimizer:[newTerserPlugin<SwcOptions>({ minify: TerserPlugin.swcMinify, terserOptions:{// `swc` options},}),newTerserPlugin<UglifyJSOptions>({ minify: TerserPlugin.uglifyJsMinify, terserOptions:{// `uglif-js` options},}),newTerserPlugin<EsbuildOptions>({ minify: TerserPlugin.esbuildMinify, terserOptions:{// `esbuild` options},}),// Alternative usage:newTerserPlugin<TerserOptions>({ minify: TerserPlugin.terserMinify, terserOptions:{// `terser` options},}),],},};
We welcome all contributions!If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.