Skip to content

Commit

Permalink
feat: added the ability to pass an array of functions to the minify
Browse files Browse the repository at this point in the history
  • Loading branch information
cap-Bernardito authored Mar 23, 2021
1 parent 35b04ea commit 91f9977
Show file tree
Hide file tree
Showing 13 changed files with 773 additions and 354 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ module.exports = {

### `minify`

Type: `Function`
Type: `Function|Array<Function>`
Default: `undefined`

Allows you to override default minify function.
Expand All @@ -196,6 +196,8 @@ Useful for using and testing unpublished versions or forks.

> ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled**.
#### `Function`

**webpack.config.js**

```js
Expand Down Expand Up @@ -240,13 +242,20 @@ module.exports = {
};
```

#### `Array`

If an array of functions is passed to the `minify` option, the `minimizerOptions` must also be an array.
The function index in the `minify` array corresponds to the options object with the same index in the `minimizerOptions` array.

### `minimizerOptions`

Type: `Object`
Type: `Object|Array<Object>`
Default: `{ preset: 'default' }`

Cssnano optimisations [options](https://cssnano.co/docs/optimisations).

#### `Object`

```js
module.exports = {
optimization: {
Expand All @@ -267,6 +276,11 @@ module.exports = {
};
```

#### `Array`

If an array of functions is passed to the `minify` option, the `minimizerOptions` must also be an array.
The function index in the `minify` array corresponds to the options object with the same index in the `minimizerOptions` array.

#### `processorOptions`

Type: `Object`
Expand Down
504 changes: 276 additions & 228 deletions package-lock.json

Large diffs are not rendered by default.

71 changes: 48 additions & 23 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import * as cssNanoPackageJson from 'cssnano/package.json';
import pLimit from 'p-limit';
import Worker from 'jest-worker';

import { cssnanoMinify } from './utils';

import * as schema from './options.json';
import { minify as minifyFn } from './minify';

Expand All @@ -20,10 +22,8 @@ class CssMinimizerPlugin {
});

const {
minify,
minimizerOptions = {
preset: 'default',
},
minify = cssnanoMinify,
minimizerOptions,
test = /\.css(\?.*)?$/i,
warningsFilter = () => true,
parallel = true,
Expand Down Expand Up @@ -281,34 +281,57 @@ class CssMinimizerPlugin {
input = input.toString();
}

const minifyFns =
typeof this.options.minify === 'function'
? [this.options.minify]
: this.options.minify;
const minimizerOptions = {
name,
input,
inputSourceMap,
minimizerOptions: this.options.minimizerOptions,
minify: this.options.minify,
};

try {
output = await (getWorker
? getWorker().transform(serialize(minimizerOptions))
: minifyFn(minimizerOptions));
} catch (error) {
compilation.errors.push(
CssMinimizerPlugin.buildError(
error,
name,
compilation.requestShortener,
inputSourceMap &&
CssMinimizerPlugin.isSourceMap(inputSourceMap)
? new SourceMapConsumer(inputSourceMap)
: null
)
);
let warnings = [];

this.options.minimizerOptions = Array.isArray(
this.options.minimizerOptions
)
? this.options.minimizerOptions
: [this.options.minimizerOptions];

for await (const [i, minifyFunc] of minifyFns.entries()) {
minimizerOptions.minify = minifyFunc;
minimizerOptions.minimizerOptions = this.options.minimizerOptions[
i
];

try {
output = await (getWorker
? getWorker().transform(serialize(minimizerOptions))
: minifyFn(minimizerOptions));
} catch (error) {
compilation.errors.push(
CssMinimizerPlugin.buildError(
error,
name,
compilation.requestShortener,
inputSourceMap &&
CssMinimizerPlugin.isSourceMap(inputSourceMap)
? new SourceMapConsumer(inputSourceMap)
: null
)
);

return;
return;
}

minimizerOptions.input = output.code;
minimizerOptions.inputSourceMap = output.map;
warnings = warnings.concat(output.warnings);
}

output.warnings = warnings;

if (output.map) {
output.source = new SourceMapSource(
output.code,
Expand Down Expand Up @@ -426,4 +449,6 @@ class CssMinimizerPlugin {
}
}

CssMinimizerPlugin.cssnano = cssnanoMinify;

export default CssMinimizerPlugin;
100 changes: 9 additions & 91 deletions src/minify.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const cssnano = require('cssnano');
/*
* We bring to the line here, because when passing result from the worker,
* the warning.toString is replaced with native Object.toString
Expand All @@ -7,34 +6,6 @@ function warningsToString(warnings) {
return warnings.map((i) => i.toString());
}

async function load(module) {
let exports;

try {
// eslint-disable-next-line import/no-dynamic-require, global-require
exports = require(module);

return exports;
} catch (requireError) {
let importESM;

try {
// eslint-disable-next-line no-new-func
importESM = new Function('id', 'return import(id);');
} catch (e) {
importESM = null;
}

if (requireError.code === 'ERR_REQUIRE_ESM' && importESM) {
exports = await importESM(module);

return exports.default;
}

throw requireError;
}
}

const minify = async (options) => {
const {
name,
Expand All @@ -44,70 +15,17 @@ const minify = async (options) => {
minify: minifyFn,
} = options;

if (minifyFn) {
const result = await minifyFn(
{ [name]: input },
inputSourceMap,
minimizerOptions
);

return {
// TODO remove `css` in future major release
code: result.code || result.css,
map: result.map,
warnings: warningsToString(result.warnings || []),
};
}

const postcssOptions = {
to: name,
from: name,
...minimizerOptions.processorOptions,
};

if (typeof postcssOptions.parser === 'string') {
try {
postcssOptions.parser = await load(postcssOptions.parser);
} catch (error) {
throw new Error(
`Loading PostCSS "${postcssOptions.parser}" parser failed: ${error.message}\n\n(@${name})`
);
}
}

if (typeof postcssOptions.stringifier === 'string') {
try {
postcssOptions.stringifier = await load(postcssOptions.stringifier);
} catch (error) {
throw new Error(
`Loading PostCSS "${postcssOptions.stringifier}" stringifier failed: ${error.message}\n\n(@${name})`
);
}
}

if (typeof postcssOptions.syntax === 'string') {
try {
postcssOptions.syntax = await load(postcssOptions.syntax);
} catch (error) {
throw new Error(
`Loading PostCSS "${postcssOptions.syntax}" syntax failed: ${error.message}\n\n(@${name})`
);
}
}

if (inputSourceMap) {
postcssOptions.map = {
annotation: false,
prev: inputSourceMap,
};
}

const result = await cssnano.process(input, postcssOptions, minimizerOptions);
const result = await minifyFn(
{ [name]: input },
inputSourceMap,
minimizerOptions
);

return {
code: result.css,
map: result.map && result.map.toString(),
warnings: warningsToString(result.warnings()),
// TODO remove `css` in future major release
code: result.code || result.css,
map: result.map,
warnings: warningsToString(result.warnings || []),
};
};

Expand Down
31 changes: 28 additions & 3 deletions src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"$ref": "#/definitions/Rule"
}
]
},
"MinimizerOptions": {
"additionalProperties": true,
"type": "object"
}
},
"title": "CssMinimizerWebpackPluginOptions",
Expand Down Expand Up @@ -62,8 +66,18 @@
},
"minimizerOptions": {
"description": "Options for `cssMinimizerOptions`.",
"additionalProperties": true,
"type": "object"
"anyOf": [
{
"$ref": "#/definitions/MinimizerOptions"
},
{
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/MinimizerOptions"
}
}
]
},
"parallel": {
"description": "Use multi-process parallel running to improve the build speed.",
Expand All @@ -82,7 +96,18 @@
},
"minify": {
"description": "Allows you to override default minify function.",
"instanceof": "Function"
"anyOf": [
{
"instanceof": "Function"
},
{
"type": "array",
"minItems": 1,
"items": {
"instanceof": "Function"
}
}
]
}
},
"additionalProperties": false
Expand Down
Loading

0 comments on commit 91f9977

Please sign in to comment.