Repository: webpack-contrib/uglifyjs-webpack-plugin
Pull request #167 (2017-11-17 13:22:57)

feat: add `include` option (`options.include`)
Feature `include` option.



Patch:
diff --git a/README.md b/README.md
index f806875..953974d 100644
--- a/README.md
+++ b/README.md
@@ -209,7 +209,7 @@ All comments that match the given expression (resp. are evaluated to `true` by t
 |Name|Type|Default|Description|
 |:--:|:--:|:-----:|:----------|
 |**`condition`**|`{Regex\|Function}`|``|Regular Expression or function (see previous point)|
-|**`filename`**|`{String\|Function}`|`compilation.assets[file]`|The file where the extracted comments will be stored. Can be either a `{String}` or a `{Function<(string) -> {String}>}`, which will be given the original filename. Default is to append the suffix `.LICENSE` to the original filename|
+|**`filename`**|`{String\|Function}`|`${file}.LICENSE`|The file where the extracted comments will be stored. Can be either a `{String}` or a `{Function<(string) -> {String}>}`, which will be given the original filename. Default is to append the suffix `.LICENSE` to the original filename|
 |**`banner`**|`{Boolean\|String\|Function}`|`/*! For license information please see ${filename}.js.LICENSE */`|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|
 
 ### `warningsFilter`
diff --git a/src/index.js b/src/index.js
index 911e1b4..1dd5879 100644
--- a/src/index.js
+++ b/src/index.js
@@ -31,6 +31,7 @@ class UglifyJsPlugin {
       sourceMap = false,
       cache = false,
       parallel = false,
+      include,
       exclude,
     } = options;
 
@@ -41,6 +42,7 @@ class UglifyJsPlugin {
       sourceMap,
       cache,
       parallel,
+      include,
       exclude,
       uglifyOptions: {
         output: {
diff --git a/src/uglify/minify.js b/src/uglify/minify.js
index 334fb59..aa07996 100644
--- a/src/uglify/minify.js
+++ b/src/uglify/minify.js
@@ -38,12 +38,16 @@ const buildComments = (options, uglifyOptions, extractedComments) => {
   const commentsOpts = uglifyOptions.output.comments;
 
   if (
+    typeof options.extractComments === 'boolean' ||
     typeof options.extractComments === 'string' ||
     options.extractComments instanceof RegExp
   ) {
     // extractComments specifies the extract condition and commentsOpts specifies the preserve condition
     condition.preserve = commentsOpts;
     condition.extract = options.extractComments;
+  } else if (typeof options.extractComments === 'function') {
+    condition.preserve = false;
+    condition.extract = options.extractComments;
   } else if (
     Object.prototype.hasOwnProperty.call(options.extractComments, 'condition')
   ) {


Test patch:
diff --git a/test/__snapshots__/exclude-option.test.js.snap b/test/__snapshots__/exclude-option.test.js.snap
index 5c446b5..9f6181d 100644
--- a/test/__snapshots__/exclude-option.test.js.snap
+++ b/test/__snapshots__/exclude-option.test.js.snap
@@ -1,5 +1,9 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`entry.a3533847fa24ef98733c.js 1`] = `"webpackJsonp([2],{2:function(o,n){o.exports=function(){console.log(7)}}},[2]);"`;
+
+exports[`entry.a3533847fa24ef98733c.js 2`] = `"webpackJsonp([2],{2:function(o,n){o.exports=function(){console.log(7)}}},[2]);"`;
+
 exports[`errors 1`] = `Array []`;
 
 exports[`errors 2`] = `Array []`;
@@ -49,13 +53,9 @@ module.exports = function Bar2() {
 ],[1]);"
 `;
 
-exports[`included.97bcf4abdd9efecc94b3.js 1`] = `"webpackJsonp([2],{2:function(o,n){o.exports=function(){console.log(7)}}},[2]);"`;
-
-exports[`included.97bcf4abdd9efecc94b3.js 2`] = `"webpackJsonp([2],{2:function(o,n){o.exports=function(){console.log(7)}}},[2]);"`;
-
-exports[`manifest.2264c6ca1c158d5cd90e.js 1`] = `"!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var u,i,f,l=0,d=[];l<t.length;l++)i=t[l],o[i]&&d.push(o[i][0]),o[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,a);d.length;)d.shift()();if(a)for(l=0;l<a.length;l++)f=n(n.s=a[l]);return f};var t={},o={3:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(i);var n=o[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute(\\"nonce\\",n.nc),u.src=n.p+\\"\\"+e+\\".\\"+({0:\\"excluded2\\",1:\\"excluded1\\",2:\\"included\\"}[e]||e)+\\".\\"+{0:\\"a96f544a34079b25c7b4\\",1:\\"4d3a1b43eccbc2acc9d6\\",2:\\"97bcf4abdd9efecc94b3\\"}[e]+\\".js\\";var i=setTimeout(r,12e4);return u.onerror=u.onload=r,a.appendChild(u),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,\\"a\\",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p=\\"\\",n.oe=function(e){throw console.error(e),e}}([]);"`;
+exports[`manifest.70d0d238a960e43f4454.js 1`] = `"!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var u,i,f,l=0,s=[];l<t.length;l++)i=t[l],o[i]&&s.push(o[i][0]),o[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,a);s.length;)s.shift()();if(a)for(l=0;l<a.length;l++)f=n(n.s=a[l]);return f};var t={},o={3:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(i);var n=o[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute(\\"nonce\\",n.nc),u.src=n.p+\\"\\"+e+\\".\\"+({0:\\"excluded2\\",1:\\"excluded1\\",2:\\"entry\\"}[e]||e)+\\".\\"+{0:\\"a96f544a34079b25c7b4\\",1:\\"4d3a1b43eccbc2acc9d6\\",2:\\"a3533847fa24ef98733c\\"}[e]+\\".js\\";var i=setTimeout(r,12e4);return u.onerror=u.onload=r,a.appendChild(u),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,\\"a\\",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p=\\"\\",n.oe=function(e){throw console.error(e),e}}([]);"`;
 
-exports[`manifest.2264c6ca1c158d5cd90e.js 2`] = `"!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var u,i,f,l=0,d=[];l<t.length;l++)i=t[l],o[i]&&d.push(o[i][0]),o[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,a);d.length;)d.shift()();if(a)for(l=0;l<a.length;l++)f=n(n.s=a[l]);return f};var t={},o={3:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(i);var n=o[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute(\\"nonce\\",n.nc),u.src=n.p+\\"\\"+e+\\".\\"+({0:\\"excluded2\\",1:\\"excluded1\\",2:\\"included\\"}[e]||e)+\\".\\"+{0:\\"a96f544a34079b25c7b4\\",1:\\"4d3a1b43eccbc2acc9d6\\",2:\\"97bcf4abdd9efecc94b3\\"}[e]+\\".js\\";var i=setTimeout(r,12e4);return u.onerror=u.onload=r,a.appendChild(u),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,\\"a\\",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p=\\"\\",n.oe=function(e){throw console.error(e),e}}([]);"`;
+exports[`manifest.70d0d238a960e43f4454.js 2`] = `"!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var u,i,f,l=0,s=[];l<t.length;l++)i=t[l],o[i]&&s.push(o[i][0]),o[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,a);s.length;)s.shift()();if(a)for(l=0;l<a.length;l++)f=n(n.s=a[l]);return f};var t={},o={3:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(i);var n=o[e];0!==n&&(n&&n[1](new Error(\\"Loading chunk \\"+e+\\" failed.\\")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName(\\"head\\")[0],u=document.createElement(\\"script\\");u.type=\\"text/javascript\\",u.charset=\\"utf-8\\",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute(\\"nonce\\",n.nc),u.src=n.p+\\"\\"+e+\\".\\"+({0:\\"excluded2\\",1:\\"excluded1\\",2:\\"entry\\"}[e]||e)+\\".\\"+{0:\\"a96f544a34079b25c7b4\\",1:\\"4d3a1b43eccbc2acc9d6\\",2:\\"a3533847fa24ef98733c\\"}[e]+\\".js\\";var i=setTimeout(r,12e4);return u.onerror=u.onload=r,a.appendChild(u),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,\\"a\\",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p=\\"\\",n.oe=function(e){throw console.error(e),e}}([]);"`;
 
 exports[`warnings 1`] = `Array []`;
 
diff --git a/test/__snapshots__/extract-comments-options.test.js.snap b/test/__snapshots__/extract-comments-options.test.js.snap
new file mode 100644
index 0000000..111ccb7
--- /dev/null
+++ b/test/__snapshots__/extract-comments-options.test.js.snap
@@ -0,0 +1,98 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`errors 1`] = `Array []`;
+
+exports[`errors 2`] = `Array []`;
+
+exports[`errors 3`] = `Array []`;
+
+exports[`errors 4`] = `Array []`;
+
+exports[`errors 5`] = `Array []`;
+
+exports[`test.js 1`] = `
+"/*! For license information please see test.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test.js 2`] = `"var foo=1;"`;
+
+exports[`test.js 3`] = `
+"/*! For license information please see test.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test.js 4`] = `
+"/*! For license information please see test.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test.js 5`] = `
+"/*! For license information please see test1.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test.js 6`] = `
+"/*! License information can be found in test.license.js */
+var foo=1;"
+`;
+
+exports[`test.js.LICENSE 1`] = `
+"// Comment
+"
+`;
+
+exports[`test.js.LICENSE 2`] = `
+"// Comment
+"
+`;
+
+exports[`test.license.js 1`] = `
+"// Comment
+"
+`;
+
+exports[`test1.js 1`] = `
+"/*! For license information please see test1.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test1.js 2`] = `
+"/*! For license information please see test1.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test1.js 3`] = `
+"/*! For license information please see test1.js.LICENSE */
+var foo=1;"
+`;
+
+exports[`test1.js.LICENSE 1`] = `
+"/* Comment */
+"
+`;
+
+exports[`test1.js.LICENSE 2`] = `
+"// foo
+"
+`;
+
+exports[`test1.js.LICENSE 3`] = `
+"/* Comment */
+"
+`;
+
+exports[`test1.js.LICENSE 4`] = `
+"/* Comment */
+"
+`;
+
+exports[`warnings 1`] = `Array []`;
+
+exports[`warnings 2`] = `Array []`;
+
+exports[`warnings 3`] = `Array []`;
+
+exports[`warnings 4`] = `Array []`;
+
+exports[`warnings 5`] = `Array []`;
diff --git a/test/__snapshots__/include-options.test.js.snap b/test/__snapshots__/include-options.test.js.snap
new file mode 100644
index 0000000..f55e150
--- /dev/null
+++ b/test/__snapshots__/include-options.test.js.snap
@@ -0,0 +1,381 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`entry.a3533847fa24ef98733c.js 1`] = `
+"webpackJsonp([2],{
+
+/***/ 2:
+/***/ (function(module, exports) {
+
+// foo
+/* @preserve*/
+// bar
+const a = 2 + 2;
+
+module.exports = function Foo() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
+
+
+/***/ })
+
+},[2]);"
+`;
+
+exports[`entry.a3533847fa24ef98733c.js 2`] = `
+"webpackJsonp([2],{
+
+/***/ 2:
+/***/ (function(module, exports) {
+
+// foo
+/* @preserve*/
+// bar
+const a = 2 + 2;
+
+module.exports = function Foo() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
+
+
+/***/ })
+
+},[2]);"
+`;
+
+exports[`errors 1`] = `Array []`;
+
+exports[`errors 2`] = `Array []`;
+
+exports[`included1.3c000166b4174c9cb9a0.js 1`] = `"webpackJsonp([1],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
+
+exports[`included1.3c000166b4174c9cb9a0.js 2`] = `"webpackJsonp([1],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`;
+
+exports[`included2.110cfb201ee67fa7a412.js 1`] = `
+"webpackJsonp([0],[
+/* 0 */,
+/* 1 */
+/***/ (function(module, exports) {
+
+module.exports = function Bar2() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
+
+
+/***/ })
+],[1]);"
+`;
+
+exports[`included2.110cfb201ee67fa7a412.js 2`] = `"webpackJsonp([0],[,function(o,n){o.exports=function(){console.log(7)}}],[1]);"`;
+
+exports[`manifest.fb0c1ba6a18ef6f513dc.js 1`] = `
+"/******/ (function(modules) { // webpackBootstrap
+/******/ 	// install a JSONP callback for chunk loading
+/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
+/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+/******/ 		// add \\"moreModules\\" to the modules object,
+/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
+/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
+/******/ 		for(;i < chunkIds.length; i++) {
+/******/ 			chunkId = chunkIds[i];
+/******/ 			if(installedChunks[chunkId]) {
+/******/ 				resolves.push(installedChunks[chunkId][0]);
+/******/ 			}
+/******/ 			installedChunks[chunkId] = 0;
+/******/ 		}
+/******/ 		for(moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				modules[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
+/******/ 		while(resolves.length) {
+/******/ 			resolves.shift()();
+/******/ 		}
+/******/ 		if(executeModules) {
+/******/ 			for(i=0; i < executeModules.length; i++) {
+/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+/******/ 			}
+/******/ 		}
+/******/ 		return result;
+/******/ 	};
+/******/
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// objects to store loaded and loading chunks
+/******/ 	var installedChunks = {
+/******/ 		3: 0
+/******/ 	};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/ 	// This file contains only the entry chunk.
+/******/ 	// The chunk loading function for additional chunks
+/******/ 	__webpack_require__.e = function requireEnsure(chunkId) {
+/******/ 		var installedChunkData = installedChunks[chunkId];
+/******/ 		if(installedChunkData === 0) {
+/******/ 			return new Promise(function(resolve) { resolve(); });
+/******/ 		}
+/******/
+/******/ 		// a Promise means \\"currently loading\\".
+/******/ 		if(installedChunkData) {
+/******/ 			return installedChunkData[2];
+/******/ 		}
+/******/
+/******/ 		// setup Promise in chunk cache
+/******/ 		var promise = new Promise(function(resolve, reject) {
+/******/ 			installedChunkData = installedChunks[chunkId] = [resolve, reject];
+/******/ 		});
+/******/ 		installedChunkData[2] = promise;
+/******/
+/******/ 		// start chunk loading
+/******/ 		var head = document.getElementsByTagName('head')[0];
+/******/ 		var script = document.createElement('script');
+/******/ 		script.type = 'text/javascript';
+/******/ 		script.charset = 'utf-8';
+/******/ 		script.async = true;
+/******/ 		script.timeout = 120000;
+/******/
+/******/ 		if (__webpack_require__.nc) {
+/******/ 			script.setAttribute(\\"nonce\\", __webpack_require__.nc);
+/******/ 		}
+/******/ 		script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({\\"0\\":\\"included2\\",\\"1\\":\\"included1\\",\\"2\\":\\"entry\\"}[chunkId]||chunkId) + \\".\\" + {\\"0\\":\\"110cfb201ee67fa7a412\\",\\"1\\":\\"3c000166b4174c9cb9a0\\",\\"2\\":\\"a3533847fa24ef98733c\\"}[chunkId] + \\".js\\";
+/******/ 		var timeout = setTimeout(onScriptComplete, 120000);
+/******/ 		script.onerror = script.onload = onScriptComplete;
+/******/ 		function onScriptComplete() {
+/******/ 			// avoid mem leaks in IE.
+/******/ 			script.onerror = script.onload = null;
+/******/ 			clearTimeout(timeout);
+/******/ 			var chunk = installedChunks[chunkId];
+/******/ 			if(chunk !== 0) {
+/******/ 				if(chunk) {
+/******/ 					chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
+/******/ 				}
+/******/ 				installedChunks[chunkId] = undefined;
+/******/ 			}
+/******/ 		};
+/******/ 		head.appendChild(script);
+/******/
+/******/ 		return promise;
+/******/ 	};
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = \\"\\";
+/******/
+/******/ 	// on error function for async loading
+/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
+/******/ })
+/************************************************************************/
+/******/ ([]);"
+`;
+
+exports[`manifest.fb0c1ba6a18ef6f513dc.js 2`] = `
+"/******/ (function(modules) { // webpackBootstrap
+/******/ 	// install a JSONP callback for chunk loading
+/******/ 	var parentJsonpFunction = window[\\"webpackJsonp\\"];
+/******/ 	window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+/******/ 		// add \\"moreModules\\" to the modules object,
+/******/ 		// then flag all \\"chunkIds\\" as loaded and fire callback
+/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
+/******/ 		for(;i < chunkIds.length; i++) {
+/******/ 			chunkId = chunkIds[i];
+/******/ 			if(installedChunks[chunkId]) {
+/******/ 				resolves.push(installedChunks[chunkId][0]);
+/******/ 			}
+/******/ 			installedChunks[chunkId] = 0;
+/******/ 		}
+/******/ 		for(moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				modules[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
+/******/ 		while(resolves.length) {
+/******/ 			resolves.shift()();
+/******/ 		}
+/******/ 		if(executeModules) {
+/******/ 			for(i=0; i < executeModules.length; i++) {
+/******/ 				result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+/******/ 			}
+/******/ 		}
+/******/ 		return result;
+/******/ 	};
+/******/
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// objects to store loaded and loading chunks
+/******/ 	var installedChunks = {
+/******/ 		3: 0
+/******/ 	};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/ 	// This file contains only the entry chunk.
+/******/ 	// The chunk loading function for additional chunks
+/******/ 	__webpack_require__.e = function requireEnsure(chunkId) {
+/******/ 		var installedChunkData = installedChunks[chunkId];
+/******/ 		if(installedChunkData === 0) {
+/******/ 			return new Promise(function(resolve) { resolve(); });
+/******/ 		}
+/******/
+/******/ 		// a Promise means \\"currently loading\\".
+/******/ 		if(installedChunkData) {
+/******/ 			return installedChunkData[2];
+/******/ 		}
+/******/
+/******/ 		// setup Promise in chunk cache
+/******/ 		var promise = new Promise(function(resolve, reject) {
+/******/ 			installedChunkData = installedChunks[chunkId] = [resolve, reject];
+/******/ 		});
+/******/ 		installedChunkData[2] = promise;
+/******/
+/******/ 		// start chunk loading
+/******/ 		var head = document.getElementsByTagName('head')[0];
+/******/ 		var script = document.createElement('script');
+/******/ 		script.type = 'text/javascript';
+/******/ 		script.charset = 'utf-8';
+/******/ 		script.async = true;
+/******/ 		script.timeout = 120000;
+/******/
+/******/ 		if (__webpack_require__.nc) {
+/******/ 			script.setAttribute(\\"nonce\\", __webpack_require__.nc);
+/******/ 		}
+/******/ 		script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({\\"0\\":\\"included2\\",\\"1\\":\\"included1\\",\\"2\\":\\"entry\\"}[chunkId]||chunkId) + \\".\\" + {\\"0\\":\\"110cfb201ee67fa7a412\\",\\"1\\":\\"3c000166b4174c9cb9a0\\",\\"2\\":\\"a3533847fa24ef98733c\\"}[chunkId] + \\".js\\";
+/******/ 		var timeout = setTimeout(onScriptComplete, 120000);
+/******/ 		script.onerror = script.onload = onScriptComplete;
+/******/ 		function onScriptComplete() {
+/******/ 			// avoid mem leaks in IE.
+/******/ 			script.onerror = script.onload = null;
+/******/ 			clearTimeout(timeout);
+/******/ 			var chunk = installedChunks[chunkId];
+/******/ 			if(chunk !== 0) {
+/******/ 				if(chunk) {
+/******/ 					chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
+/******/ 				}
+/******/ 				installedChunks[chunkId] = undefined;
+/******/ 			}
+/******/ 		};
+/******/ 		head.appendChild(script);
+/******/
+/******/ 		return promise;
+/******/ 	};
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = \\"\\";
+/******/
+/******/ 	// on error function for async loading
+/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };
+/******/ })
+/************************************************************************/
+/******/ ([]);"
+`;
+
+exports[`warnings 1`] = `Array []`;
+
+exports[`warnings 2`] = `Array []`;
diff --git a/test/exclude-option.test.js b/test/exclude-option.test.js
index 80ec1fd..39bfb1c 100644
--- a/test/exclude-option.test.js
+++ b/test/exclude-option.test.js
@@ -12,7 +12,7 @@ describe('when applied with exclude option', () => {
       entry: {
         excluded1: `${__dirname}/fixtures/excluded1.js`,
         excluded2: `${__dirname}/fixtures/excluded2.js`,
-        included: `${__dirname}/fixtures/entry.js`,
+        entry: `${__dirname}/fixtures/entry.js`,
       },
     });
   });
diff --git a/test/extract-comments-options.test.js b/test/extract-comments-options.test.js
index 18b7231..b13427f 100644
--- a/test/extract-comments-options.test.js
+++ b/test/extract-comments-options.test.js
@@ -71,6 +71,48 @@ describe('when options.extractComments', () => {
     });
   });
 
+  it('normalizes when options.extractComments is boolean', () => {
+    const pluginEnvironment = new PluginEnvironment();
+    const compilerEnv = pluginEnvironment.getEnvironmentStub();
+    compilerEnv.context = '';
+
+    const plugin = new UglifyJsPlugin({
+      uglifyOptions: {
+        output: {
+          comments: false,
+        },
+      },
+      extractComments: true,
+    });
+    plugin.apply(compilerEnv);
+    const [eventBinding] = pluginEnvironment.getEventBindings();
+    const chunkPluginEnvironment = new PluginEnvironment();
+    const compilation2 = chunkPluginEnvironment.getEnvironmentStub();
+    compilation2.assets = {
+      'test.js': {
+        source: () => '// Comment\nvar foo = 1;',
+      },
+      'test1.js': {
+        source: () => '/* Comment */\nvar foo = 1;',
+      },
+    };
+    compilation2.warnings = [];
+    compilation2.errors = [];
+
+    eventBinding.handler(compilation2);
+    [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
+
+    compilationEventBinding.handler([{
+      files: ['test.js', 'test1.js'],
+    }], () => {
+      expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js');
+      expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test1.js');
+      expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE');
+      expect(compilation2.errors).toMatchSnapshot('errors');
+      expect(compilation2.warnings).toMatchSnapshot('warnings');
+    });
+  });
+
   it('normalizes when options.extractComments is regex', () => {
     const pluginEnvironment = new PluginEnvironment();
     const compilerEnv = pluginEnvironment.getEnvironmentStub();
@@ -90,22 +132,116 @@ describe('when options.extractComments', () => {
     const compilation2 = chunkPluginEnvironment.getEnvironmentStub();
     compilation2.assets = {
       'test.js': {
-        source: () => 'var foo = 1;',
+        source: () => '// Comment\nvar foo = 1;',
+      },
+      'test1.js': {
+        source: () => '// foo\nvar foo = 1;',
       },
     };
+    compilation2.warnings = [];
     compilation2.errors = [];
 
     eventBinding.handler(compilation2);
     [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
 
     compilationEventBinding.handler([{
-      files: ['test.js'],
+      files: ['test.js', 'test1.js'],
     }], () => {
-      expect(compilation2.errors.length).toBe(0);
+      expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js');
+      expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test1.js');
+      expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE');
+      expect(compilation2.errors).toMatchSnapshot('errors');
+      expect(compilation2.warnings).toMatchSnapshot('warnings');
     });
   });
 
-  it('converts boolean options.extractComments.condition to function', () => {
+  it('normalizes when options.extractComments is string', () => {
+    const pluginEnvironment = new PluginEnvironment();
+    const compilerEnv = pluginEnvironment.getEnvironmentStub();
+    compilerEnv.context = '';
+
+    const plugin = new UglifyJsPlugin({
+      uglifyOptions: {
+        output: {
+          comments: false,
+        },
+      },
+      extractComments: 'all',
+    });
+    plugin.apply(compilerEnv);
+    const [eventBinding] = pluginEnvironment.getEventBindings();
+    const chunkPluginEnvironment = new PluginEnvironment();
+    const compilation2 = chunkPluginEnvironment.getEnvironmentStub();
+    compilation2.assets = {
+      'test.js': {
+        source: () => '// Comment\nvar foo = 1;',
+      },
+      'test1.js': {
+        source: () => '/* Comment */\nvar foo = 1;',
+      },
+    };
+    compilation2.warnings = [];
+    compilation2.errors = [];
+
+    eventBinding.handler(compilation2);
+    [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
+
+    compilationEventBinding.handler([{
+      files: ['test.js', 'test1.js'],
+    }], () => {
+      expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js');
+      expect(compilation2.assets['test.js.LICENSE'].source()).toMatchSnapshot('test.js.LICENSE');
+      expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test1.js');
+      expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE');
+      expect(compilation2.errors).toMatchSnapshot('errors');
+      expect(compilation2.warnings).toMatchSnapshot('warnings');
+    });
+  });
+
+  it('normalizes when options.extractComments is function', () => {
+    const pluginEnvironment = new PluginEnvironment();
+    const compilerEnv = pluginEnvironment.getEnvironmentStub();
+    compilerEnv.context = '';
+
+    const plugin = new UglifyJsPlugin({
+      uglifyOptions: {
+        output: {
+          comments: false,
+        },
+      },
+      extractComments: () => true,
+    });
+    plugin.apply(compilerEnv);
+    const [eventBinding] = pluginEnvironment.getEventBindings();
+    const chunkPluginEnvironment = new PluginEnvironment();
+    const compilation2 = chunkPluginEnvironment.getEnvironmentStub();
+    compilation2.assets = {
+      'test.js': {
+        source: () => '// Comment\nvar foo = 1;',
+      },
+      'test1.js': {
+        source: () => '/* Comment */\nvar foo = 1;',
+      },
+    };
+    compilation2.warnings = [];
+    compilation2.errors = [];
+
+    eventBinding.handler(compilation2);
+    [compilationEventBinding] = chunkPluginEnvironment.getEventBindings();
+
+    compilationEventBinding.handler([{
+      files: ['test.js', 'test1.js'],
+    }], () => {
+      expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js');
+      expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test.js');
+      expect(compilation2.assets['test.js.LICENSE'].source()).toMatchSnapshot('test.js.LICENSE');
+      expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE');
+      expect(compilation2.errors).toMatchSnapshot('errors');
+      expect(compilation2.warnings).toMatchSnapshot('warnings');
+    });
+  });
+
+  it('normalizes when options.extractComments is object', () => {
     const pluginEnvironment = new PluginEnvironment();
     const compilerEnv = pluginEnvironment.getEnvironmentStub();
     compilerEnv.context = '';
@@ -132,9 +268,10 @@ describe('when options.extractComments', () => {
     const compilation2 = chunkPluginEnvironment.getEnvironmentStub();
     compilation2.assets = {
       'test.js': {
-        source: () => 'var foo = 1;',
+        source: () => '// Comment\nvar foo = 1;',
       },
     };
+    compilation2.warnings = [];
     compilation2.errors = [];
 
     eventBinding.handler(compilation2);
@@ -143,7 +280,10 @@ describe('when options.extractComments', () => {
     compilationEventBinding.handler([{
       files: ['test.js'],
     }], () => {
-      expect(compilation2.errors.length).toBe(0);
+      expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js');
+      expect(compilation2.assets['test.license.js'].source()).toMatchSnapshot('test.license.js');
+      expect(compilation2.errors).toMatchSnapshot('errors');
+      expect(compilation2.warnings).toMatchSnapshot('warnings');
     });
   });
 });
diff --git a/test/fixtures/included1.js b/test/fixtures/included1.js
new file mode 100644
index 0000000..f7bd0e6
--- /dev/null
+++ b/test/fixtures/included1.js
@@ -0,0 +1,4 @@
+module.exports = function Bar1() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
diff --git a/test/fixtures/included2.js b/test/fixtures/included2.js
new file mode 100644
index 0000000..20c9fb3
--- /dev/null
+++ b/test/fixtures/included2.js
@@ -0,0 +1,4 @@
+module.exports = function Bar2() {
+  const b = 2 + 2;
+  console.log(b + 1 + 2);
+};
diff --git a/test/include-options.test.js b/test/include-options.test.js
new file mode 100644
index 0000000..e517002
--- /dev/null
+++ b/test/include-options.test.js
@@ -0,0 +1,64 @@
+import UglifyJsPlugin from '../src/index';
+import {
+  cleanErrorStack,
+  createCompiler,
+  compile,
+} from './helpers';
+
+describe('when applied with include option', () => {
+  let compiler;
+  beforeEach(() => {
+    compiler = createCompiler({
+      entry: {
+        included1: `${__dirname}/fixtures/included1.js`,
+        included2: `${__dirname}/fixtures/included2.js`,
+        entry: `${__dirname}/fixtures/entry.js`,
+      },
+    });
+  });
+
+  it('matches snapshot for a single include', () => {
+    new UglifyJsPlugin({
+      include: /included1/,
+    }).apply(compiler);
+
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
+
+  it('matches snapshot for multiple includes', () => {
+    new UglifyJsPlugin({
+      include: [
+        /included1/,
+        /included2/,
+      ],
+    }).apply(compiler);
+
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
+        }
+      }
+    });
+  });
+});