Skip to content

Commit f8e4c2c

Browse files
authored
fix: Purgecss webpack plugin/only filter fix (#933)
* fix: check if file exists in chunk after only filter * test: update simple-with-exclusion test case of purgecss-webpack-plugin to actually test for purgecss exclusion * docs: only option checks against chunk names instead of entrypoints
1 parent eec045a commit f8e4c2c

File tree

5 files changed

+64
-79
lines changed

5 files changed

+64
-79
lines changed

docs/plugins/webpack.md

+45-46
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ meta:
77
- itemprop: description
88
content: PurgeCSS is a tool for removing CSS that you're not actually using in your project. You can use it with webpack with a plugin.
99
- property: og:url
10-
content: https://purgecss.com/plugins/webpack
10+
content: https://purgecss.com/plugins/webpack
1111
- property: og:site_name
1212
content: purgecss.com
1313
- property: og:type
@@ -39,55 +39,54 @@ npm i purgecss-webpack-plugin -D
3939
### With mini-css-extract-plugin
4040

4141
```js
42-
const path = require('path')
43-
const glob = require('glob')
44-
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
45-
const PurgecssPlugin = require('purgecss-webpack-plugin')
42+
const path = require("path");
43+
const glob = require("glob");
44+
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
45+
const PurgecssPlugin = require("purgecss-webpack-plugin");
4646

4747
const PATHS = {
48-
src: path.join(__dirname, 'src')
49-
}
48+
src: path.join(__dirname, "src"),
49+
};
5050

5151
module.exports = {
52-
entry: './src/index.js',
52+
entry: "./src/index.js",
5353
output: {
54-
filename: 'bundle.js',
55-
path: path.join(__dirname, 'dist')
54+
filename: "bundle.js",
55+
path: path.join(__dirname, "dist"),
5656
},
5757
optimization: {
5858
splitChunks: {
5959
cacheGroups: {
6060
styles: {
61-
name: 'styles',
61+
name: "styles",
6262
test: /\.css$/,
63-
chunks: 'all',
64-
enforce: true
65-
}
66-
}
67-
}
63+
chunks: "all",
64+
enforce: true,
65+
},
66+
},
67+
},
6868
},
6969
module: {
7070
rules: [
7171
{
7272
test: /\.css$/,
73-
use: [
74-
MiniCssExtractPlugin.loader,
75-
"css-loader"
76-
]
77-
}
78-
]
73+
use: [MiniCssExtractPlugin.loader, "css-loader"],
74+
},
75+
],
7976
},
8077
plugins: [
8178
new MiniCssExtractPlugin({
8279
filename: "[name].css",
8380
}),
8481
new PurgecssPlugin({
85-
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
82+
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
8683
}),
87-
]
88-
}
84+
],
85+
};
8986
```
87+
9088
### Multiple paths
89+
9190
If you need multiple paths use the npm package `glob-all` instead of `glob`, then you can use this syntax:
9291

9392
```js
@@ -97,70 +96,70 @@ new PurgecssPlugin({
9796
])
9897
}),
9998
```
99+
100100
to filter out directories see the glob-all documentation [here](https://www.npmjs.com/package/glob-all#filtering-out-directories).
101101

102102
## Options
103103

104104
The options available in purgecss [Configuration](https://www.purgecss.com/configuration.html) are also available in the webpack plugin, with the exception of the `css` and `content` options.
105105

106-
* #### paths
106+
- #### paths
107107

108108
With the webpack plugin, you can specify the content that should be analyzed by purgecss by providing an array of filenames. These can be html, pug, blade, ... files. You can also use a module like `glob` or `glob-all` to easily get a list of files.
109109

110110
> You likely need to pass `{ noDir: true }` as an option to `glob.sync()` as `glob.sync` is matching a dir which the plugin can't operate on.
111111
112112
```js
113-
const PurgecssPlugin = require('purgecss-webpack-plugin')
114-
const glob = require('glob')
113+
const PurgecssPlugin = require("purgecss-webpack-plugin");
114+
const glob = require("glob");
115115
const PATHS = {
116-
src: path.join(__dirname, 'src')
117-
}
116+
src: path.join(__dirname, "src"),
117+
};
118118

119119
// In the webpack configuration
120120
new PurgecssPlugin({
121-
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true })
122-
})
121+
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
122+
});
123123
```
124124

125125
If you want to regenerate the list of paths on every compilation (e.g. when using `--watch`), then you can also pass a function to the `paths` option as in the following example:
126126

127127
```js
128128
new PurgecssPlugin({
129-
paths: () => glob.sync(`${PATHS.src}/**/*`, { nodir: true })
130-
})
129+
paths: () => glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
130+
});
131131
```
132132

133-
* #### only
133+
- #### only
134134

135-
You can specify entrypoints to the purgecss-webpack-plugin with the option `only`:
135+
You can specify chunk names to the purgecss-webpack-plugin with the option `only`:
136136

137137
```js
138138
new PurgecssPlugin({
139139
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
140-
only: ['bundle', 'vendor']
141-
})
140+
only: ["bundle", "vendor"],
141+
});
142142
```
143143

144-
* #### safelist
144+
- #### safelist
145145

146146
Similar as for the `paths` option, you also can define a function for this option:
147147

148148
```js
149149
function collectSafelist() {
150150
return {
151-
standard: ['safelisted', /^safelisted-/],
151+
standard: ["safelisted", /^safelisted-/],
152152
deep: [/^safelisted-deep-/],
153-
greedy: [/^safelisted-greedy/]
154-
}
153+
greedy: [/^safelisted-greedy/],
154+
};
155155
}
156156

157157
// In the webpack configuration
158158
new PurgeCSSPlugin({
159-
safelist: collectSafelist
160-
})
159+
safelist: collectSafelist,
160+
});
161161
```
162162

163-
164-
* #### rejected
163+
- #### rejected
165164

166165
When this option is set to `true` all removed selectors are added to the [Stats Data](https://webpack.js.org/api/stats/) as `purged`.

packages/purgecss-webpack-plugin/__tests__/cases/simple-with-exclusion/expected/styles.css renamed to packages/purgecss-webpack-plugin/__tests__/cases/simple-with-exclusion/expected/bundle.css

-20
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,10 @@
55
color: red;
66
}
77

8-
.unused {
9-
color: blue;
10-
}
11-
128
.safelisted {
139
color: green;
1410
}
1511

1612
md\:w-2\/3 {
1713
color: red;
1814
}
19-
20-
/*!******************************************************************************!*\
21-
!*** css ../../../../../node_modules/css-loader/dist/cjs.js!./src/style.css ***!
22-
\******************************************************************************/
23-
.legacy-unused-class {
24-
color: red;
25-
}
26-
27-
.unused-too {
28-
color: blue;
29-
}
30-
31-
.hello {
32-
color: red;
33-
}
34-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*!******************************************************************************!*\
2+
!*** css ../../../../../node_modules/css-loader/dist/cjs.js!./src/style.css ***!
3+
\******************************************************************************/
4+
.legacy-unused-class {
5+
color: red;
6+
}
7+
8+
.unused-too {
9+
color: blue;
10+
}
11+
12+
.hello {
13+
color: red;
14+
}

packages/purgecss-webpack-plugin/__tests__/cases/simple-with-exclusion/webpack.config.js

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const path = require("path");
22
const glob = require("glob");
33
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
4-
const {PurgeCSSPlugin} = require("../../../src/");
4+
const { PurgeCSSPlugin } = require("../../../src/");
55

66
const customExtractor = (content) => content.match(/[A-z0-9-:/]+/g) || [];
77

@@ -17,17 +17,7 @@ module.exports = {
1717
legacy: "./src/legacy.js",
1818
},
1919
optimization: {
20-
splitChunks: {
21-
cacheGroups: {
22-
styles: {
23-
name: "styles",
24-
type: "css/mini-extract",
25-
test: /\.css$/,
26-
chunks: "all",
27-
enforce: true,
28-
},
29-
},
30-
},
20+
splitChunks: { chunks: "all" },
3121
},
3222
module: {
3323
rules: [

packages/purgecss-webpack-plugin/src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ export class PurgeCSSPlugin {
167167
for (const chunk of compilation.chunks) {
168168
const assetsToPurge = assetsFromCompilation.filter(([name]) => {
169169
if (this.options.only) {
170-
return this.options.only.some((only) => name.includes(only));
170+
if (!(this.options.only.some((only) => name.includes(only)))) {
171+
return false;
172+
}
171173
}
172174

173175
return chunk.files.has(name);

0 commit comments

Comments
 (0)