Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Commit

Permalink
feat: support minify function option
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Jul 3, 2018
1 parent 249eef3 commit a0656df
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 6 deletions.
87 changes: 87 additions & 0 deletions README.md
Expand Up @@ -50,6 +50,7 @@ module.exports = {
|**`cacheKeys`**|`{Function(defaultCacheKeys, file) -> {Object}}`|`defaultCacheKeys => defaultCacheKeys`|Allows you to override default cache keys|
|**`parallel`**|`{Boolean\|Number}`|`false`|Use multi-process parallel running to improve the build speed|
|**`sourceMap`**|`{Boolean}`|`false`|Use source maps to map error message locations to modules (This slows down the compilation) ⚠️ **`cheap-source-map` options don't work with this plugin**|
|**`minify`**|`{Function}`|`undefined`|Allows you to override default minify function|
|**`uglifyOptions`**|`{Object}`|[`{...defaults}`](https://github.com/webpack-contrib/uglifyjs-webpack-plugin/tree/master#uglifyoptions)|`uglify` [Options](https://github.com/mishoo/UglifyJS2/tree/harmony#minify-options)|
|**`extractComments`**|`{Boolean\|RegExp\|Function<(node, comment) -> {Boolean\|Object}>}`|`false`|Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a) (`webpack >= 2.3.0`)|
|**`warningsFilter`**|`{Function(source) -> {Boolean}}`|`() => true`|Allow to filter uglify warnings|
Expand Down Expand Up @@ -89,6 +90,8 @@ module.exports = {

### `cache`

If you use custom `minify` function please read `minify` option section for cache invalidation correctly.

#### `{Boolean}`

**webpack.config.js**
Expand Down Expand Up @@ -189,6 +192,90 @@ Number of concurrent runs.

> ⚠️ **`cheap-source-map` options don't work with this plugin**
### `minify`

**webpack.config.js**
```js
[
new UglifyJsPlugin({
minify(file) {
const extractedComments = [];

// Custom logic for extract comments

const { error, map, code, warnings } = minify(
file,
{ /* Your options for minification */ },
);

return { error, map, code, warnings, extractedComments };
}
})
]
```

By default plugin use `uglify-es` package.

Examples:

#### `uglify-js`

```bash
npm i -D uglify-js
```

**webpack.config.js**
```js
[
new UglifyJsPlugin({
// Uncomment lines below for cache invalidation correctly
// cache: true,
// cacheKeys(defaultCacheKeys) {
// return Object.assign(
// {},
// defaultCacheKeys,
// { 'uglify-js': require('uglify-js/package.json').version },
// );
// },
minify(file) {
return require('uglify-js').minify(
file,
{ /* `uglify-js` package options */ }
);
}
})
]
```

#### `terser`

```bash
npm i -D terser
```

**webpack.config.js**
```js
[
new UglifyJsPlugin({
// Uncomment lines below for cache invalidation correctly
// cache: true,
// cacheKeys(defaultCacheKeys) {
// return Object.assign(
// {},
// defaultCacheKeys,
// { terser: require('terser/package.json').version },
// );
// },
minify(file) {
return require('terser').minify(
file,
{ /* `terser` package options */ }
);
}
})
]
```

### [`uglifyOptions`](https://github.com/mishoo/UglifyJS2/tree/harmony#minify-options)

|Name|Type|Default|Description|
Expand Down
36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -57,6 +57,8 @@
"nsp": "^3.1.0",
"pre-commit": "^1.2.2",
"standard-version": "^4.3.0",
"terser": "^3.7.6",
"uglify-js": "^3.4.3",
"webpack": "^3.10.0",
"webpack-defaults": "^1.6.0"
},
Expand Down
11 changes: 7 additions & 4 deletions src/index.js
Expand Up @@ -9,7 +9,7 @@ import RequestShortener from 'webpack/lib/RequestShortener';
import ModuleFilenameHelpers from 'webpack/lib/ModuleFilenameHelpers';
import validateOptions from 'schema-utils';
import schema from './options.json';
import Uglify from './uglify';
import Runner from './uglify/Runner';
import versions from './uglify/versions';
import utils from './utils';

Expand All @@ -20,6 +20,7 @@ class UglifyJsPlugin {
validateOptions(schema, options, 'UglifyJs Plugin');

const {
minify,
uglifyOptions = {},
test = /\.js(\?.*)?$/i,
warningsFilter = () => true,
Expand All @@ -42,6 +43,7 @@ class UglifyJsPlugin {
parallel,
include,
exclude,
minify,
uglifyOptions: {
compress: {
inline: 1,
Expand Down Expand Up @@ -114,7 +116,7 @@ class UglifyJsPlugin {
};

const optimizeFn = (compilation, chunks, callback) => {
const uglify = new Uglify({
const runner = new Runner({
cache: this.options.cache,
parallel: this.options.parallel,
});
Expand Down Expand Up @@ -169,6 +171,7 @@ class UglifyJsPlugin {
commentsFile,
extractComments: this.options.extractComments,
uglifyOptions: this.options.uglifyOptions,
minify: this.options.minify,
};

if (this.options.cache) {
Expand Down Expand Up @@ -196,7 +199,7 @@ class UglifyJsPlugin {
}
});

uglify.runTasks(tasks, (tasksError, results) => {
runner.runTasks(tasks, (tasksError, results) => {
if (tasksError) {
compilation.errors.push(tasksError);
return;
Expand Down Expand Up @@ -294,7 +297,7 @@ class UglifyJsPlugin {
}
});

uglify.exit();
runner.exit();

callback();
});
Expand Down
3 changes: 3 additions & 0 deletions src/options.json
Expand Up @@ -24,6 +24,9 @@
"sourceMap": {
"type": "boolean"
},
"minify": {
"instanceof": "Function"
},
"uglifyOptions": {
"additionalProperties": true,
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion src/uglify/index.js → src/uglify/Runner.js
Expand Up @@ -12,7 +12,7 @@ try {
workerFile = require.resolve('../../dist/uglify/worker');
} catch (e) { } // eslint-disable-line no-empty

export default class {
export default class Runner {
constructor(options = {}) {
const { cache, parallel } = options;
this.cacheDir = cache === true ? findCacheDir({ name: 'uglifyjs-webpack-plugin' }) : cache;
Expand Down
7 changes: 6 additions & 1 deletion src/uglify/minify.js
Expand Up @@ -127,7 +127,12 @@ const buildComments = (options, uglifyOptions, extractedComments) => {
};

const minify = (options) => {
const { file, input, inputSourceMap, extractComments } = options;
const { file, input, inputSourceMap, extractComments, minify: minifyFn } = options;

if (minifyFn) {
return minifyFn({ [file]: input });
}

// Copy uglify options
const uglifyOptions = buildUglifyOptions(options.uglifyOptions);

Expand Down
25 changes: 25 additions & 0 deletions test/__snapshots__/minify.test.js.snap
@@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`when applied with minify option matches snapshot for \`terser\` minifier: errors 1`] = `Array []`;

exports[`when applied with minify option matches snapshot for \`terser\` minifier: main.js 1`] = `"webpackJsonp([0],[function(t,e,s){\\"use strict\\";Object.defineProperty(e,\\"__esModule\\",{value:!0});e.default=class{constructor(t,e){this.x=t,this.y=e}static distance(t,e){const s=t.x-e.x,c=t.y-e.y;return Math.hypot(s,c)}}}],[0]);"`;

exports[`when applied with minify option matches snapshot for \`terser\` minifier: manifest.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;

exports[`when applied with minify option matches snapshot for \`terser\` minifier: warnings 1`] = `Array []`;

exports[`when applied with minify option matches snapshot for \`uglify-es\` minifier: errors 1`] = `Array []`;

exports[`when applied with minify option matches snapshot for \`uglify-es\` minifier: main.js 1`] = `"webpackJsonp([0],[function(t,e,s){\\"use strict\\";Object.defineProperty(e,\\"__esModule\\",{value:!0});e.default=class{constructor(t,e){this.x=t,this.y=e}static distance(t,e){const s=t.x-e.x,c=t.y-e.y;return Math.hypot(s,c)}}}],[0]);"`;

exports[`when applied with minify option matches snapshot for \`uglify-es\` minifier: manifest.js 1`] = `"!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={1:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,\\"a\\",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p=\\"\\",t.oe=function(r){throw console.error(r),r}}([]);"`;

exports[`when applied with minify option matches snapshot for \`uglify-es\` minifier: warnings 1`] = `Array []`;

exports[`when applied with minify option matches snapshot for \`uglify-js\` minifier: errors 1`] = `Array []`;

exports[`when applied with minify option matches snapshot for \`uglify-js\` minifier: main.js 1`] = `"webpackJsonp([0],[function(e,n){e.exports=function(){var baz=document.getElementById(\\"root\\").innerHTML;document.getElementById(\\"demo\\").innerHTML=\\"Paragraph changed.\\"+baz}}],[0]);"`;

exports[`when applied with minify option matches snapshot for \`uglify-js\` minifier: manifest.js 1`] = `"!function(i){var p=window.webpackJsonp;window.webpackJsonp=function(r,n,e){for(var o,t,u,c=0,f=[];c<r.length;c++)t=r[c],a[t]&&f.push(a[t][0]),a[t]=0;for(o in n)Object.prototype.hasOwnProperty.call(n,o)&&(i[o]=n[o]);for(p&&p(r,n,e);f.length;)f.shift()();if(e)for(c=0;c<e.length;c++)u=l(l.s=e[c]);return u};var e={},a={1:0};function l(r){if(e[r])return e[r].exports;var n=e[r]={i:r,l:!1,exports:{}};return i[r].call(n.exports,n,n.exports,l),n.l=!0,n.exports}l.m=i,l.c=e,l.d=function(r,n,e){l.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},l.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return l.d(n,\\"a\\",n),n},l.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},l.p=\\"\\",l.oe=function(r){throw console.error(r),r}}([]);"`;

exports[`when applied with minify option matches snapshot for \`uglify-js\` minifier: warnings 1`] = `Array []`;
7 changes: 7 additions & 0 deletions test/fixtures/minify/es5.js
@@ -0,0 +1,7 @@
function myFunction() {
var baz = document.getElementById("root").innerHTML;

document.getElementById("demo").innerHTML = "Paragraph changed." + baz;
}

module.exports = myFunction;
15 changes: 15 additions & 0 deletions test/fixtures/minify/es6.js
@@ -0,0 +1,15 @@
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}

static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;

return Math.hypot(dx, dy);
}
}

export default Point;

0 comments on commit a0656df

Please sign in to comment.