Skip to content

Commit

Permalink
feat: exclude stats.warningsFilter matched warnings (#61)
Browse files Browse the repository at this point in the history
* chore: add comment for v2, v3 and v4+ implementation

* test: improve v4 test case

* feat: support stats.warningsFilter config

* docs: update readme

* refactor: combineFilters -> combineIgnores
  • Loading branch information
taehwanno committed Sep 26, 2021
1 parent 959e4d0 commit 07bcf47
Show file tree
Hide file tree
Showing 5 changed files with 364 additions and 98 deletions.
74 changes: 54 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,62 @@ module.exports = {
};
```

- **with [`warningsFilter`](https://webpack.js.org/configuration/stats/#statswarningsfilter) and [`ignoreWarnings`](https://webpack.js.org/configuration/other-options/#ignorewarnings)**

This plugin ignores warnings that are matched by `warningsFilter` or `ignoreWarnings` without recognizing them as errors.

```js
// webpack v5
{
plugins: [
new WarningsToErrorsPlugin(),
],
ignoreWarnings: [
{
message: /compilation warning/,
},
],
}
```

If you use `ignoreWarnings` and `warningsFilter ` options at the same time in webpack v5, the plugin will ignore all matched warnings in both. but recommend using `ignoreWarnings`.

```js
// webpack v5
{
plugins: [
new WarningsToErrorsPlugin(),
],
ignoreWarnings: [
{
message: /compilation warning 1/,
},
],
stats: {
warningsFilter: [
/compilation warning 2/,
],
},
}
```

```js
// webpack v2, v3 and v4
{
plugins: [
new WarningsToErrorsPlugin(),
],
stats: {
warningsFilter: [
/compilation warning/,
],
},
}
```

- **with [`NoEmitOnErrorsPlugin`](https://webpack.js.org/plugins/no-emit-on-errors-plugin/)**

Skip the emitting phase whenever there are warnings while compiling. This ensures that no assets are emitted that include warnings.
Skip the emitting phase whenever there are warnings while compiling. this ensures that no assets are emitted that include warnings.

```js
// webpack >= v4
Expand All @@ -61,25 +114,6 @@ Skip the emitting phase whenever there are warnings while compiling. This ensure
};
```

- **with [`ignoreWarnings`](https://webpack.js.org/configuration/other-options/#ignorewarnings)**

This plugin ignores warnings that match `ignoreWarnings` without recognizing them as errors.

```js
// webpack v5
{
plugins: [
new WarningsToErrorsPlugin(),
],
ignoreWarnings: [
{
message: /compilation warning/,
},
],
}
```


## License

MIT © [Taehwan Noh](https://github.com/taehwanno)
48 changes: 45 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,69 @@
class WarningsToErrorsPlugin {
apply(compiler) {
if ('hooks' in compiler) {
// For webpack v4+
compiler.hooks.shouldEmit.tap('WarningsToErrorsPlugin', (compilation) => this.handleHook(compiler, compilation));
} else {
// For webpack v2, v3
compiler.plugin('should-emit', (compilation) => this.handleHook(compiler, compilation));
}
}

combineIgnores(compiler) {
const ignoreWarnings = compiler.options.ignoreWarnings || [];
const warningsFilter = (compiler.options.stats && compiler.options.stats.warningsFilter) || []
return ignoreWarnings.concat(warningsFilter);
}

/**
* In webpack v5, ignoreWarnings's every value in the config are converted to function with
* "function (WebpackError, Compilation) => boolean" signature when creating webpack plugin.
* but stats.warningsFilter has the same type as the passed value in webpack v2, v3 and v4 because it is not converted.
* it can be string, regular expression and function with "function (WebpackError) => boolean" signature.
*
* As a result, because the function signature of v5 is compatible with v4's function
* we will normalize warningsFilter's every value to function with "function (WebpackError) => boolean" signature.
*
* webpack v4 stats.warningsFilter
* @see https://webpack.js.org/configuration/stats/#statswarningsfilter
* webpack v5 ignoredWarnings
* @see https://webpack.js.org/configuration/other-options/#ignorewarnings
*/
normalizeIgnores(ignores) {
return ignores.map((ignore) => {
switch (typeof ignore) {
case 'function':
return ignore;
case 'string':
return (warning) => warning.message.includes(ignore);
case 'object': {
if (ignore instanceof RegExp) {
return (warning) => ignore.test(warning.message);
}
}
default:
return ignore;
}
});
}

filterIgnoredWarnings(allWarnings, ignoredWarnings, compilation) {
return allWarnings.filter(warning => !ignoredWarnings.some(ignore => ignore(warning, compilation)));
}

handleHook(compiler, compilation) {
const ignoredWarnings = compiler.options.ignoreWarnings || [];
const ignores = this.combineIgnores(compiler);
const normalizedIgnores = this.normalizeIgnores(ignores);

if (compilation.warnings.length > 0) {
const filteredWarnings = this.filterIgnoredWarnings(compilation.warnings, ignoredWarnings, compilation);
const filteredWarnings = this.filterIgnoredWarnings(compilation.warnings, normalizedIgnores, compilation);
compilation.errors = compilation.errors.concat(filteredWarnings);
compilation.warnings = [];
}

compilation.children.forEach((child) => {
if (child.warnings.length > 0) {
const filteredWarnings = this.filterIgnoredWarnings(child.warnings, ignoredWarnings, compilation);
const filteredWarnings = this.filterIgnoredWarnings(child.warnings, normalizedIgnores, compilation);
child.errors = child.errors.concat(filteredWarnings);
child.warnings = [];
}
Expand Down
98 changes: 83 additions & 15 deletions test/v2-3/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const webpack = require('webpack');
const WarningsToErrorsPlugin = require('../../');

const base = path.join(__dirname, '../fixtures');
const { flatten } = require('../utils')

describe('WarningsToErrorsPlugin', () => {
function customOutputFilesystem(c) {
Expand Down Expand Up @@ -38,22 +39,91 @@ describe('WarningsToErrorsPlugin', () => {
callback(
stats.errors,
stats.warnings,
stats.children.map(child => child.errors),
stats.children.map(child => child.warnings),
flatten(stats.children.map(child => child.errors)),
flatten(stats.children.map(child => child.warnings)),
);
});
}

it('should not have errors if there is no warning', (done) => {
getStats({
entry: './file',
plugins: [
new WarningsToErrorsPlugin(),
],
}, (errors, warnings) => {
errors.length.should.be.eql(0);
warnings.length.should.be.eql(0);
done();
describe('should have no errors and no warnings if:', () => {
it('there are no errors and no warnings', (done) => {
getStats({
entry: './file',
plugins: [
new WarningsToErrorsPlugin(),
],
}, (errors, warnings) => {
errors.length.should.be.eql(0);
warnings.length.should.be.eql(0);
done();
});
});


it("there is a warning in top-level compilation, but it's ignored using the 'stats.warningsFilter' config option", (done) => {
getStats({
entry: './file',
plugins: [
{
apply(compiler) {
compiler.plugin('make', (compilation, cb) => {
compilation.warnings.push(new Error('warning for regular expression filter'));
compilation.warnings.push(new Error('warning for string filter'));
compilation.warnings.push(new Error('warning for function filter'));
cb();
});
}
},
new WarningsToErrorsPlugin(),
],
stats: {
children: true,
warningsFilter: [
/regular expression filter/,
'string filter',
(warning) => warning.message.includes('function filter'),
],
},
}, (errors, warnings) => {
errors.length.should.be.eql(0);
warnings.length.should.be.eql(0);
done();
});
});

it("there is a warning in child compilation, but it's ignored using the 'stats.warningsFilter' config option", (done) => {
getStats({
entry: './file',
plugins: [
{
apply(compiler) {
compiler.plugin('make', (compilation, cb) => {
const child = compilation.createChildCompiler('child', {});
child.plugin('compilation', (childCompilation) => {
childCompilation.warnings.push(new Error('warning for regular expression filter in child compilation'));
childCompilation.warnings.push(new Error('warning for string filter in child compilation'));
childCompilation.warnings.push(new Error('warning for function filter in child compilation'));
});
child.runAsChild(cb);
});
}
},
new WarningsToErrorsPlugin(),
],
stats: {
warningsFilter: [
/regular expression filter/,
'string filter',
(warning) => warning.message.includes('function filter'),
],
},
}, (errors, warnings, childrenErrors, childrenWarnings) => {
errors.length.should.be.eql(0);
warnings.length.should.be.eql(0);
childrenErrors.length.should.be.eql(0);
childrenWarnings.length.should.be.eql(0);
done();
});
});
});

Expand Down Expand Up @@ -99,9 +169,7 @@ describe('WarningsToErrorsPlugin', () => {
errors.length.should.be.eql(0);
warnings.length.should.be.eql(0);
childrenErrors.length.should.be.eql(1);
childrenErrors[0].length.should.be.eql(1);
childrenWarnings.length.should.be.eql(1);
childrenWarnings[0].length.should.be.eql(0);
childrenWarnings.length.should.be.eql(0);
done();
});
});
Expand Down

0 comments on commit 07bcf47

Please sign in to comment.