You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

731 lines
15 KiB

4 years ago
  1. <div align="center">
  2. <a href="https://github.com/webpack/webpack">
  3. <img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
  4. </a>
  5. </div>
  6. [![npm][npm]][npm-url]
  7. [![node][node]][node-url]
  8. [![deps][deps]][deps-url]
  9. [![tests][tests]][tests-url]
  10. [![cover][cover]][cover-url]
  11. [![chat][chat]][chat-url]
  12. [![size][size]][size-url]
  13. # terser-webpack-plugin
  14. This plugin uses [terser](https://github.com/terser-js/terser) to minify your JavaScript.
  15. > ℹ️ For `webpack@3` use [terser-webpack-plugin-legacy](https://www.npmjs.com/package/terser-webpack-plugin-legacy) package
  16. ## Getting Started
  17. To begin, you'll need to install `terser-webpack-plugin`:
  18. ```console
  19. $ npm install terser-webpack-plugin --save-dev
  20. ```
  21. Then add the plugin to your `webpack` config. For example:
  22. **webpack.config.js**
  23. ```js
  24. const TerserPlugin = require('terser-webpack-plugin');
  25. module.exports = {
  26. optimization: {
  27. minimizer: [new TerserPlugin()],
  28. },
  29. };
  30. ```
  31. And run `webpack` via your preferred method.
  32. ## Options
  33. ### `test`
  34. Type: `String|RegExp|Array<String|RegExp>`
  35. Default: `/\.m?js(\?.*)?$/i`
  36. Test to match files against.
  37. **webpack.config.js**
  38. ```js
  39. module.exports = {
  40. optimization: {
  41. minimizer: [
  42. new TerserPlugin({
  43. test: /\.js(\?.*)?$/i,
  44. }),
  45. ],
  46. },
  47. };
  48. ```
  49. ### `include`
  50. Type: `String|RegExp|Array<String|RegExp>`
  51. Default: `undefined`
  52. Files to include.
  53. **webpack.config.js**
  54. ```js
  55. module.exports = {
  56. optimization: {
  57. minimizer: [
  58. new TerserPlugin({
  59. include: /\/includes/,
  60. }),
  61. ],
  62. },
  63. };
  64. ```
  65. ### `exclude`
  66. Type: `String|RegExp|Array<String|RegExp>`
  67. Default: `undefined`
  68. Files to exclude.
  69. **webpack.config.js**
  70. ```js
  71. module.exports = {
  72. optimization: {
  73. minimizer: [
  74. new TerserPlugin({
  75. exclude: /\/excludes/,
  76. }),
  77. ],
  78. },
  79. };
  80. ```
  81. ### `chunkFilter`
  82. Type: `Function<(chunk) -> boolean>`
  83. Default: `() => true`
  84. Allowing to filter which chunks should be uglified (by default all chunks are uglified).
  85. Return `true` to uglify the chunk, `false` otherwise.
  86. **webpack.config.js**
  87. ```js
  88. module.exports = {
  89. optimization: {
  90. minimizer: [
  91. new TerserPlugin({
  92. chunkFilter: (chunk) => {
  93. // Exclude uglification for the `vendor` chunk
  94. if (chunk.name === 'vendor') {
  95. return false;
  96. }
  97. return true;
  98. },
  99. }),
  100. ],
  101. },
  102. };
  103. ```
  104. ### `cache`
  105. Type: `Boolean|String`
  106. Default: `false`
  107. Enable file caching.
  108. Default path to cache directory: `node_modules/.cache/terser-webpack-plugin`.
  109. > ℹ️ If you use your own `minify` function please read the `minify` section for cache invalidation correctly.
  110. #### `Boolean`
  111. Enable/disable file caching.
  112. **webpack.config.js**
  113. ```js
  114. module.exports = {
  115. optimization: {
  116. minimizer: [
  117. new TerserPlugin({
  118. cache: true,
  119. }),
  120. ],
  121. },
  122. };
  123. ```
  124. #### `String`
  125. Enable file caching and set path to cache directory.
  126. **webpack.config.js**
  127. ```js
  128. module.exports = {
  129. optimization: {
  130. minimizer: [
  131. new TerserPlugin({
  132. cache: 'path/to/cache',
  133. }),
  134. ],
  135. },
  136. };
  137. ```
  138. ### `cacheKeys`
  139. Type: `Function<(defaultCacheKeys, file) -> Object>`
  140. Default: `defaultCacheKeys => defaultCacheKeys`
  141. Allows you to override default cache keys.
  142. Default cache keys:
  143. ```js
  144. ({
  145. terser: require('terser/package.json').version, // terser version
  146. 'terser-webpack-plugin': require('../package.json').version, // plugin version
  147. 'terser-webpack-plugin-options': this.options, // plugin options
  148. path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file, // asset path
  149. hash: crypto
  150. .createHash('md4')
  151. .update(input)
  152. .digest('hex'), // source file hash
  153. });
  154. ```
  155. **webpack.config.js**
  156. ```js
  157. module.exports = {
  158. optimization: {
  159. minimizer: [
  160. new TerserPlugin({
  161. cache: true,
  162. cacheKeys: (defaultCacheKeys, file) => {
  163. defaultCacheKeys.myCacheKey = 'myCacheKeyValue';
  164. return defaultCacheKeys;
  165. },
  166. }),
  167. ],
  168. },
  169. };
  170. ```
  171. ### `parallel`
  172. Type: `Boolean|Number`
  173. Default: `false`
  174. Use multi-process parallel running to improve the build speed.
  175. Default number of concurrent runs: `os.cpus().length - 1`.
  176. > ℹ️ Parallelization can speedup your build significantly and is therefore **highly recommended**.
  177. #### `Boolean`
  178. Enable/disable multi-process parallel running.
  179. **webpack.config.js**
  180. ```js
  181. module.exports = {
  182. optimization: {
  183. minimizer: [
  184. new TerserPlugin({
  185. parallel: true,
  186. }),
  187. ],
  188. },
  189. };
  190. ```
  191. #### `Number`
  192. Enable multi-process parallel running and set number of concurrent runs.
  193. **webpack.config.js**
  194. ```js
  195. module.exports = {
  196. optimization: {
  197. minimizer: [
  198. new TerserPlugin({
  199. parallel: 4,
  200. }),
  201. ],
  202. },
  203. };
  204. ```
  205. ### `sourceMap`
  206. Type: `Boolean`
  207. Default: `false`
  208. Use source maps to map error message locations to modules (this slows down the compilation).
  209. If you use your own `minify` function please read the `minify` section for handling source maps correctly.
  210. > ⚠️ **`cheap-source-map` options don't work with this plugin**.
  211. **webpack.config.js**
  212. ```js
  213. module.exports = {
  214. optimization: {
  215. minimizer: [
  216. new TerserPlugin({
  217. sourceMap: true,
  218. }),
  219. ],
  220. },
  221. };
  222. ```
  223. ### `minify`
  224. Type: `Function`
  225. Default: `undefined`
  226. Allows you to override default minify function.
  227. By default plugin uses [terser](https://github.com/terser-js/terser) package.
  228. Useful for using and testing unpublished versions or forks.
  229. > ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled**.
  230. **webpack.config.js**
  231. ```js
  232. module.exports = {
  233. optimization: {
  234. minimizer: [
  235. new TerserPlugin({
  236. minify: (file, sourceMap) => {
  237. const extractedComments = [];
  238. // Custom logic for extract comments
  239. const { error, map, code, warnings } = require('uglify-module') // Or require('./path/to/uglify-module')
  240. .minify(file, {
  241. /* Your options for minification */
  242. });
  243. return { error, map, code, warnings, extractedComments };
  244. },
  245. }),
  246. ],
  247. },
  248. };
  249. ```
  250. ### `terserOptions`
  251. Type: `Object`
  252. Default: [default](https://github.com/terser-js/terser#minify-options)
  253. Terser minify [options](https://github.com/terser-js/terser#minify-options).
  254. **webpack.config.js**
  255. ```js
  256. module.exports = {
  257. optimization: {
  258. minimizer: [
  259. new TerserPlugin({
  260. terserOptions: {
  261. ecma: undefined,
  262. warnings: false,
  263. parse: {},
  264. compress: {},
  265. mangle: true, // Note `mangle.properties` is `false` by default.
  266. module: false,
  267. output: null,
  268. toplevel: false,
  269. nameCache: null,
  270. ie8: false,
  271. keep_classnames: undefined,
  272. keep_fnames: false,
  273. safari10: false,
  274. },
  275. }),
  276. ],
  277. },
  278. };
  279. ```
  280. ### `extractComments`
  281. Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>|Object`
  282. Default: `false`
  283. Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)).
  284. By default extract only comments using `/^\**!|@preserve|@license|@cc_on/i` regexp condition and remove remaining comments.
  285. If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE`.
  286. The `terserOptions.output.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.
  287. #### `Boolean`
  288. Enable/disable extracting comments.
  289. **webpack.config.js**
  290. ```js
  291. module.exports = {
  292. optimization: {
  293. minimizer: [
  294. new TerserPlugin({
  295. extractComments: true,
  296. }),
  297. ],
  298. },
  299. };
  300. ```
  301. #### `String`
  302. Extract `all` or `some` (use `/^\**!|@preserve|@license|@cc_on/i` RegExp) comments.
  303. **webpack.config.js**
  304. ```js
  305. module.exports = {
  306. optimization: {
  307. minimizer: [
  308. new TerserPlugin({
  309. extractComments: 'all',
  310. }),
  311. ],
  312. },
  313. };
  314. ```
  315. #### `RegExp`
  316. All comments that match the given expression will be extracted to the separate file.
  317. **webpack.config.js**
  318. ```js
  319. module.exports = {
  320. optimization: {
  321. minimizer: [
  322. new TerserPlugin({
  323. extractComments: /@extract/i,
  324. }),
  325. ],
  326. },
  327. };
  328. ```
  329. #### `Function<(node, comment) -> Boolean>`
  330. All comments that match the given expression will be extracted to the separate file.
  331. **webpack.config.js**
  332. ```js
  333. module.exports = {
  334. optimization: {
  335. minimizer: [
  336. new TerserPlugin({
  337. extractComments: (astNode, comment) => {
  338. if (/@extract/i.test(comment.value)) {
  339. return true;
  340. }
  341. return false;
  342. },
  343. }),
  344. ],
  345. },
  346. };
  347. ```
  348. #### `Object`
  349. Allow to customize condition for extract comments, specify extracted file name and banner.
  350. **webpack.config.js**
  351. ```js
  352. module.exports = {
  353. optimization: {
  354. minimizer: [
  355. new TerserPlugin({
  356. extractComments: {
  357. condition: /^\**!|@preserve|@license|@cc_on/i,
  358. filename: (file) => {
  359. return `${file}.LICENSE`;
  360. },
  361. banner: (licenseFile) => {
  362. return `License information can be found in ${licenseFile}`;
  363. },
  364. },
  365. }),
  366. ],
  367. },
  368. };
  369. ```
  370. ##### `condition`
  371. Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>`
  372. Condition what comments you need extract.
  373. **webpack.config.js**
  374. ```js
  375. module.exports = {
  376. optimization: {
  377. minimizer: [
  378. new TerserPlugin({
  379. extractComments: {
  380. condition: 'some',
  381. filename: (file) => {
  382. return `${file}.LICENSE`;
  383. },
  384. banner: (licenseFile) => {
  385. return `License information can be found in ${licenseFile}`;
  386. },
  387. },
  388. }),
  389. ],
  390. },
  391. };
  392. ```
  393. ##### `filename`
  394. Type: `String|Function<(string) -> String>`
  395. Default: `${file}.LICENSE`
  396. The file where the extracted comments will be stored.
  397. Default is to append the suffix `.LICENSE` to the original filename.
  398. **webpack.config.js**
  399. ```js
  400. module.exports = {
  401. optimization: {
  402. minimizer: [
  403. new TerserPlugin({
  404. extractComments: {
  405. condition: /^\**!|@preserve|@license|@cc_on/i,
  406. filename: 'extracted-comments.js',
  407. banner: (licenseFile) => {
  408. return `License information can be found in ${licenseFile}`;
  409. },
  410. },
  411. }),
  412. ],
  413. },
  414. };
  415. ```
  416. ##### `banner`
  417. Type: `Boolean|String|Function<(string) -> String>`
  418. Default: `/*! For license information please see ${commentsFile} */`
  419. The banner text that points to the extracted file and will be added on top of the original file.
  420. 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.
  421. Will be wrapped into comment.
  422. **webpack.config.js**
  423. ```js
  424. module.exports = {
  425. optimization: {
  426. minimizer: [
  427. new TerserPlugin({
  428. extractComments: {
  429. condition: true,
  430. filename: (file) => {
  431. return `${file}.LICENSE`;
  432. },
  433. banner: (commentsFile) => {
  434. return `My custom banner about license information ${commentsFile}`;
  435. },
  436. },
  437. }),
  438. ],
  439. },
  440. };
  441. ```
  442. ### `warningsFilter`
  443. Type: `Function<(warning, source) -> Boolean>`
  444. Default: `() => true`
  445. Allow to filter [terser](https://github.com/terser-js/terser) warnings.
  446. Return `true` to keep the warning, `false` otherwise.
  447. **webpack.config.js**
  448. ```js
  449. module.exports = {
  450. optimization: {
  451. minimizer: [
  452. new TerserPlugin({
  453. warningsFilter: (warning, source) => {
  454. if (/Dropping unreachable code/i.test(warning)) {
  455. return true;
  456. }
  457. if (/filename\.js/i.test(source)) {
  458. return true;
  459. }
  460. return false;
  461. },
  462. }),
  463. ],
  464. },
  465. };
  466. ```
  467. ## Examples
  468. ### Cache And Parallel
  469. Enable cache and multi-process parallel running.
  470. **webpack.config.js**
  471. ```js
  472. module.exports = {
  473. optimization: {
  474. minimizer: [
  475. new TerserPlugin({
  476. cache: true,
  477. parallel: true,
  478. }),
  479. ],
  480. },
  481. };
  482. ```
  483. ### Preserve Comments
  484. Extract all legal comments (i.e. `/^\**!|@preserve|@license|@cc_on/i`) and preserve `/@license/i` comments.
  485. **webpack.config.js**
  486. ```js
  487. module.exports = {
  488. optimization: {
  489. minimizer: [
  490. new TerserPlugin({
  491. terserOptions: {
  492. output: {
  493. comments: /@license/i,
  494. },
  495. },
  496. extractComments: true,
  497. }),
  498. ],
  499. },
  500. };
  501. ```
  502. ### Remove Comments
  503. If you avoid building with comments, set **terserOptions.output.comments** to **false** as in this config:
  504. **webpack.config.js**
  505. ```js
  506. module.exports = {
  507. optimization: {
  508. minimizer: [
  509. new TerserPlugin({
  510. terserOptions: {
  511. output: {
  512. comments: false,
  513. },
  514. },
  515. }),
  516. ],
  517. },
  518. };
  519. ```
  520. ### Custom Minify Function
  521. Override default minify function - use `uglify-js` for minification.
  522. **webpack.config.js**
  523. ```js
  524. module.exports = {
  525. optimization: {
  526. minimizer: [
  527. new TerserPlugin({
  528. // Uncomment lines below for cache invalidation correctly
  529. // cache: true,
  530. // cacheKeys: (defaultCacheKeys) => {
  531. // delete defaultCacheKeys.terser;
  532. //
  533. // return Object.assign(
  534. // {},
  535. // defaultCacheKeys,
  536. // { 'uglify-js': require('uglify-js/package.json').version },
  537. // );
  538. // },
  539. minify: (file, sourceMap) => {
  540. // https://github.com/mishoo/UglifyJS2#minify-options
  541. const uglifyJsOptions = {
  542. /* your `uglify-js` package options */
  543. };
  544. if (sourceMap) {
  545. uglifyJsOptions.sourceMap = {
  546. content: sourceMap,
  547. };
  548. }
  549. return require('uglify-js').minify(file, uglifyJsOptions);
  550. },
  551. }),
  552. ],
  553. },
  554. };
  555. ```
  556. ## Contributing
  557. Please take a moment to read our contributing guidelines if you haven't yet done so.
  558. [CONTRIBUTING](./.github/CONTRIBUTING.md)
  559. ## License
  560. [MIT](./LICENSE)
  561. [npm]: https://img.shields.io/npm/v/terser-webpack-plugin.svg
  562. [npm-url]: https://npmjs.com/package/terser-webpack-plugin
  563. [node]: https://img.shields.io/node/v/terser-webpack-plugin.svg
  564. [node-url]: https://nodejs.org
  565. [deps]: https://david-dm.org/webpack-contrib/terser-webpack-plugin.svg
  566. [deps-url]: https://david-dm.org/webpack-contrib/terser-webpack-plugin
  567. [tests]: https://dev.azure.com/webpack-contrib/terser-webpack-plugin/_apis/build/status/webpack-contrib.terser-webpack-plugin?branchName=master
  568. [tests-url]: https://dev.azure.com/webpack-contrib/terser-webpack-plugin/_build/latest?definitionId=7&branchName=master
  569. [cover]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin/branch/master/graph/badge.svg
  570. [cover-url]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin
  571. [chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
  572. [chat-url]: https://gitter.im/webpack/webpack
  573. [size]: https://packagephobia.now.sh/badge?p=terser-webpack-plugin
  574. [size-url]: https://packagephobia.now.sh/result?p=terser-webpack-plugin