Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: chunkFilter option for filtering chunks #38

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,35 @@ module.exports = {
};
```

### `chunkFilter`

Type: `Function<(chunk) -> boolean>`
Default: `() => true`

Allowing to filter which chunks should be uglified (by default all chunks are uglified).
Return `true` to uglify the chunk, `false` otherwise.

**webpack.config.js**

```js
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
chunkFilter: (chunk) => {
// Exclude uglification for the `vendor` chunk
if (chunk.name === 'vendor') {
return false;
}

return true;
}
}),
],
},
};
```

### `cache`

Type: `Boolean|String`
Expand Down
5 changes: 5 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TerserPlugin {
minify,
terserOptions = {},
test = /\.m?js(\?.*)?$/i,
chunkFilter = () => true,
warningsFilter = () => true,
extractComments = false,
sourceMap = false,
Expand All @@ -35,6 +36,7 @@ class TerserPlugin {

this.options = {
test,
chunkFilter,
warningsFilter,
extractComments,
sourceMap,
Expand Down Expand Up @@ -165,7 +167,10 @@ class TerserPlugin {
const processedAssets = new WeakSet();
const tasks = [];

const { chunkFilter } = this.options;

Array.from(chunks)
.filter((chunk) => chunkFilter && chunkFilter(chunk))
.reduce((acc, chunk) => acc.concat(chunk.files || []), [])
.concat(compilation.additionalChunkAssets || [])
.filter(ModuleFilenameHelpers.matchObject.bind(null, this.options))
Expand Down
3 changes: 3 additions & 0 deletions src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
}
]
},
"chunkFilter": {
"instanceof": "Function"
},
"cache": {
"anyOf": [
{
Expand Down
108 changes: 108 additions & 0 deletions test/__snapshots__/chunkFilter-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`when applied with \`chunkFilter\` option matches snapshot for a single \`chunkFilter\`: entry.ad91bb81010ae4d51b51.js 1`] = `"!function(e){var t={};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}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\\"a\\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\\"\\",n(n.s=1)}([,function(e,t){e.exports=function(){console.log(7)}}]);"`;

exports[`when applied with \`chunkFilter\` option matches snapshot for a single \`chunkFilter\`: errors 1`] = `Array []`;

exports[`when applied with \`chunkFilter\` option matches snapshot for a single \`chunkFilter\`: included.509052cb854cc0a5be63.js 1`] = `
"/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // 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;
/******/ }
/******/
/******/
/******/ // 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, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // 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 = \\"\\";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {

module.exports = function Bar1() {
const b = 2 + 2;
console.log(b + 1 + 2);
};


/***/ })
/******/ ]);"
`;

exports[`when applied with \`chunkFilter\` option matches snapshot for a single \`chunkFilter\`: warnings 1`] = `Array []`;
31 changes: 19 additions & 12 deletions test/__snapshots__/validation.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,27 @@ options.exclude should match some schema in anyOf
exports[`validation 7`] = `
"Terser Plugin Invalid Options

options.chunkFilter should pass \\"instanceof\\" keyword validation
"
`;

exports[`validation 8`] = `
"Terser Plugin Invalid Options

options.cache should be boolean
options.cache should be string
options.cache should match some schema in anyOf
"
`;

exports[`validation 8`] = `
exports[`validation 9`] = `
"Terser Plugin Invalid Options

options.cacheKeys should pass \\"instanceof\\" keyword validation
"
`;

exports[`validation 9`] = `
exports[`validation 10`] = `
"Terser Plugin Invalid Options

options.parallel should be boolean
Expand All @@ -100,7 +107,7 @@ options.parallel should match some schema in anyOf
"
`;

exports[`validation 10`] = `
exports[`validation 11`] = `
"Terser Plugin Invalid Options

options.parallel should be boolean
Expand All @@ -109,28 +116,28 @@ options.parallel should match some schema in anyOf
"
`;

exports[`validation 11`] = `
exports[`validation 12`] = `
"Terser Plugin Invalid Options

options.sourceMap should be boolean
"
`;

exports[`validation 12`] = `
exports[`validation 13`] = `
"Terser Plugin Invalid Options

options.minify should pass \\"instanceof\\" keyword validation
"
`;

exports[`validation 13`] = `
exports[`validation 14`] = `
"Terser Plugin Invalid Options

options.terserOptions should be object
"
`;

exports[`validation 14`] = `
exports[`validation 15`] = `
"Terser Plugin Invalid Options

options.extractComments should be boolean
Expand All @@ -146,7 +153,7 @@ options.extractComments should match some schema in anyOf
"
`;

exports[`validation 15`] = `
exports[`validation 16`] = `
"Terser Plugin Invalid Options

options.extractComments should be boolean
Expand All @@ -160,7 +167,7 @@ options.extractComments should match some schema in anyOf
"
`;

exports[`validation 16`] = `
exports[`validation 17`] = `
"Terser Plugin Invalid Options

options.extractComments should be boolean
Expand All @@ -175,7 +182,7 @@ options.extractComments should match some schema in anyOf
"
`;

exports[`validation 17`] = `
exports[`validation 18`] = `
"Terser Plugin Invalid Options

options.extractComments should be boolean
Expand All @@ -187,14 +194,14 @@ options.extractComments should match some schema in anyOf
"
`;

exports[`validation 18`] = `
exports[`validation 19`] = `
"Terser Plugin Invalid Options

options.warningsFilter should pass \\"instanceof\\" keyword validation
"
`;

exports[`validation 19`] = `
exports[`validation 20`] = `
"Terser Plugin Invalid Options

options should NOT have additional properties
Expand Down
44 changes: 44 additions & 0 deletions test/chunkFilter-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import TerserPlugin from '../src/index';

import { cleanErrorStack, createCompiler, compile } from './helpers';

describe('when applied with `chunkFilter` option', () => {
let compiler;

beforeEach(() => {
compiler = createCompiler({
entry: {
included: `${__dirname}/fixtures/included1.js`,
entry: `${__dirname}/fixtures/entry.js`,
},
});
});

it('matches snapshot for a single `chunkFilter`', () => {
new TerserPlugin({
chunkFilter: (chunk) => {
if (chunk.name === 'included') {
return false;
}

return true;
},
}).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);
}
}
});
});
});
8 changes: 8 additions & 0 deletions test/validation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ it('validation', () => {
new TerserPlugin({ exclude: [true] });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new TerserPlugin({ chunkFilter: () => {} });
}).not.toThrow();

expect(() => {
new TerserPlugin({ chunkFilter: true });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new TerserPlugin({ cache: true });
}).not.toThrow();
Expand Down