Skip to content

Commit ded1569

Browse files
committed
feat(BRAKING CHANGE): add new stage option and reverted defaults behavior as in v0.8.1
1 parent 2c03ff5 commit ded1569

File tree

26 files changed

+318
-101
lines changed

26 files changed

+318
-101
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
## 1.0.0 (2022-09-12)
2+
- BRAKING CHANGE: reverted defaults behavior as in `v0.8.1` - remove empty scripts before other plugins will be called.
3+
This change is needs for properly work of the vast majority of webpack plugins.
4+
5+
For compatibility with `v0.8.2 - v0.8.4`, if you have an issue, use new `stage` option with the value:
6+
```js
7+
new RemoveEmptyScriptsPlugin({
8+
stage: RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS,
9+
})
10+
```
11+
- feat: added new `stage` option.
12+
Webpack plugins use different stages for their functionality.
13+
For properly work other plugins can be specified the `stage` when should be removed empty scripts: before or after processing of other webpack plugins.\
14+
For example, using `@wordpress/dependency-extraction-webpack-plugin` the empty scripts must be removed `after` processing all plugins.
15+
Using `webpack-manifest-plugin` the empty scripts must be removed `before` processing other plugins.
16+
- chore: update packages
17+
- test: added the test for using with webpack-manifest-plugin
18+
- docs: update readme
19+
120
## 0.8.4 (2022-09-08)
221
- fix: fixed last stable version of ansis in package.json to avoid issues in dependency
322

README.md

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,21 @@
1010
The plugin removes empty `js` scripts generated when using only the styles like `css` `scss` `sass` `less` `stylus` in the webpack entry.
1111

1212
This is improved fork of original plugin [webpack-fix-style-only-entries](https://github.com/fqborges/webpack-fix-style-only-entries) ver. 0.6.0.\
13-
This fork fixes some deprecation messages and some issues in React. See the details in [changelog](https://github.com/webdiscus/webpack-remove-empty-scripts/blob/master/CHANGELOG.md#061-oct-20-2020).
13+
This fork fixes deprecation messages, issues when using React and some specific plugins.
1414

1515
The plugin support only `Webpack 5`.
1616
For `Webpack 4` use original [plugin](https://github.com/fqborges/webpack-fix-style-only-entries).
1717

18+
> **Warning**
19+
>
20+
> The new version `1.0.0` has probable `BRAKING CHANGE`.\
21+
> In this version was reverted defaults behavior as in `v0.8.1` - remove empty scripts `before` processing other plugins.
22+
23+
> **Migration to v1.0.0**
24+
>
25+
> When update from `<= v0.8.1`, nothing needs to be done.\
26+
> When update from `v0.8.2 - v0.8.4`, if you have an issue, try to use new `stage` option with `RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS` value.
27+
1828
## Description of the problem
1929

2030
Webpack generates a js file for each resource defined in a webpack entry.
@@ -132,6 +142,26 @@ Type: `boolean` Default: `true`<br>
132142
Enable / disable the plugin.
133143
**Tip:** Use `disable` for development to improve performance.
134144

145+
### `stage`
146+
Type: `number`<br>
147+
Values:
148+
- `RemoveEmptyScriptsPlugin.STAGE_BEFORE_PROCESS_PLUGINS` (default)\
149+
Remove empty scripts `before` processing other plugins.\
150+
For example, exact this stage needs for properly work of the `webpack-manifest-plugin`.
151+
- `RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS`\
152+
Remove empty scripts `after` processing all other plugins.\
153+
For example, exact this stage needs for properly work of the `@wordpress/dependency-extraction-webpack-plugin`.
154+
155+
Webpack plugins use different stages for their functionality.
156+
For properly work other plugins can be specified the `stage` when should be removed empty scripts: before or after processing of other webpack plugins.
157+
158+
See [usage example](#usage-stage-optoion).
159+
160+
> **Warning**
161+
>
162+
> Because `webpack-manifest-plugin` and `@wordpress/dependency-extraction-webpack-plugin` needs different stages
163+
> both plugins can't be used together with `RemoveEmptyScriptsPlugin` at one configuration.
164+
135165
### `extensions`
136166
Type: `RegExp` Default: `/\.(css|scss|sass|less|styl)([?].*)?$/`
137167
Note: the Regexp should have the query part at end `([?].*)?$` to match assets like `style.css?key=val` <br>
@@ -153,36 +183,71 @@ Show process information.
153183
## Recipes
154184

155185
### Show logs to console by development
156-
```JavaScript
186+
```js
157187
const isProduction = process.env.NODE_ENV === 'production';
158188
new RemoveEmptyScriptsPlugin({ verbose: isProduction !== true })
159189
```
160190

161191
### Disable plugin by development to improve performance
162-
```JavaScript
192+
```js
163193
const isProduction = process.env.NODE_ENV === 'production';
164194
new RemoveEmptyScriptsPlugin({ enabled: isProduction === true })
165195
```
166196

197+
<a id="usage-stage-optoion" name="usage-stage-optoion" href="#usage-stage-optoion"></a>
198+
### Specify stage for properly work some plugins
199+
For example, using `@wordpress/dependency-extraction-webpack-plugin` the empty scripts must be removed `after` processing all plugins.
200+
201+
```js
202+
const path = require('path');
203+
const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin');
204+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
205+
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');
206+
207+
module.exports = {
208+
output: {
209+
path: path.join(__dirname, 'public'),
210+
},
211+
entry: {
212+
'main': './src/sass/main.scss',
213+
},
214+
module: {
215+
rules: [
216+
{
217+
test: /\.scss$/,
218+
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
219+
},
220+
],
221+
},
222+
plugins: [
223+
new MiniCssExtractPlugin(),
224+
new DependencyExtractionWebpackPlugin(),
225+
new RemoveEmptyScriptsPlugin({
226+
stage: RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS, // <- use this option
227+
}),
228+
],
229+
};
230+
```
231+
167232
### Identify only `.foo` and `.bar` extensions as styles
168233

169-
```JavaScript
234+
```js
170235
new RemoveEmptyScriptsPlugin({ extensions: /\.(foo|bar)$/ })
171236
```
172237

173238
### Usage a javascript entry to styles
174239
Give an especial extension to your file, for example `.css.js`:
175-
```JavaScript
240+
```js
176241
new RemoveEmptyScriptsPlugin({ extensions: /\.(css.js)$/ })
177242
```
178243

179244
### Remove generated scripts `*.js` `*.mjs` except `*.rem.js` `*.rem.mjs`
180-
```JavaScript
245+
```js
181246
new RemoveEmptyScriptsPlugin({ remove: /(?<!\.rem)\.(js|mjs)$/ })
182247
```
183248

184249
### Recursive ignore all js files from directory, for example `my-workers/`
185-
```JavaScript
250+
```js
186251
new RemoveEmptyScriptsPlugin({
187252
ignore: [
188253
/my-workers\/.+\.js$/,
@@ -191,7 +256,7 @@ new RemoveEmptyScriptsPlugin({
191256
```
192257

193258
### Usage webpack-hot-middleware
194-
```JavaScript
259+
```js
195260
new RemoveEmptyScriptsPlugin({
196261
ignore: [
197262
'webpack-hot-middleware',
@@ -205,21 +270,13 @@ new RemoveEmptyScriptsPlugin({
205270
`npm run test` will run the unit and integration tests.\
206271
`npm run test:coverage` will run the tests with coverage.
207272

208-
## New experimental version
209-
210-
> The `experimental` version `^1.x.x` has **_new improved and fast algorithm_** to detect generated needless empty js files.\
211-
> Please test your project before using it in production.\
212-
> If you have a problem with the new version, please create a [new issue](https://github.com/webdiscus/webpack-remove-empty-scripts/issues).
213-
214-
> ⚠️ The last stable release is `0.8.x` in the branch [`master`](https://github.com/webdiscus/webpack-remove-empty-scripts/tree/master).
215-
216273

217274
## Also See
218275

219276
- more examples of usages see in [test cases](https://github.com/webdiscus/webpack-remove-empty-scripts/tree/master/test/cases)
220-
- [ansis][ansis] - ANSI color styling of text in terminal
221-
- [pug-plugin][pug-plugin]
222-
- [pug-loader][pug-loader]
277+
- [ansis][ansis] - Formatting text in terminal with ANSI colors & styles.
278+
- [pug-plugin][pug-plugin] - plugin for Webpack compiles Pug files to HTML, extracts CSS and JS from their sources specified in Pug.
279+
- [pug-loader][pug-loader] - loader for Webpack renders Pug to HTML or template function. Optimized for using with Vue.
223280

224281
## License
225282
[ISC](https://github.com/webdiscus/webpack-remove-empty-scripts/blob/master/LICENSE)
@@ -228,4 +285,4 @@ new RemoveEmptyScriptsPlugin({
228285
[ansis]: https://github.com/webdiscus/ansis
229286
[pug-plugin]: https://github.com/webdiscus/pug-plugin
230287
[pug-loader]: https://github.com/webdiscus/pug-loader
231-
<!-- prettier-ignore-end -->
288+
<!-- prettier-ignore-end -->

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "webpack-remove-empty-scripts",
3-
"version": "0.8.4",
4-
"description": "Webpack 5 plugin to remove empty scripts generated by usage only style in webpack entry.",
3+
"version": "1.0.0",
4+
"description": "Plugin for Webpack 5 to remove empty scripts generated by usage only style in webpack entry.",
55
"keywords": [
66
"webpack",
77
"remove",
@@ -56,7 +56,7 @@
5656
"webpack": ">=5.32.0"
5757
},
5858
"dependencies": {
59-
"ansis": "1.4.0"
59+
"ansis": "1.5.2"
6060
},
6161
"devDependencies": {
6262
"@babel/core": "^7.18.13",
@@ -72,6 +72,7 @@
7272
"terser-webpack-plugin": "^5.3.6",
7373
"webpack": "^5.74.0",
7474
"webpack-hot-middleware": "^2.25.2",
75+
"webpack-manifest-plugin": "^5.0.0",
7576
"webpack-merge": "^5.8.0"
7677
}
7778
}

src/index.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ interface IOptions {
55
extensions: Array<string> | RegExp,
66
ignore: string | RegExp | string[] | RegExp[],
77
remove: RegExp,
8+
stage: number,
89
verbose: boolean;
910
}
1011

1112
export type WebpackRemoveEmptyScriptsPluginOptions = Partial<IOptions>;
1213

1314
declare class WebpackRemoveEmptyScriptsPlugin implements WebpackPluginInstance {
15+
[index: string]: any;
16+
17+
public static STAGE_BEFORE_PROCESS_PLUGINS: number;
18+
public static STAGE_AFTER_PROCESS_PLUGINS: number;
19+
1420
constructor(options: WebpackRemoveEmptyScriptsPluginOptions);
21+
1522
apply(compiler: Compiler): void;
1623
}
1724

src/index.js

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,13 @@
33
*/
44

55
const path = require('path');
6-
const ansis = require('ansis');
6+
const { red, green, cyan, cyanBright, yellow, magenta, white, black, gray, blueBright } = require('ansis/colors');
77

88
const { outToConsole } = require('./utils');
99

1010
const pluginName = 'remove-empty-scripts';
11-
const defaultOptions = {
12-
enabled: true,
13-
verbose: false,
14-
extensions: ['css', 'scss', 'sass', 'less', 'styl'],
15-
ignore: [],
16-
remove: /\.(js|mjs)$/,
17-
};
11+
const infoPluginName = `\n${black.bgYellow`[${pluginName}]`}`;
12+
const errorPluginName = `\n${black.bgRed`[${pluginName}]`}`;
1813

1914
// Save unique id in dependency object as marker of 'analysed module'
2015
// to avoid the infinite recursion by collect of resources.
@@ -24,6 +19,9 @@ class WebpackRemoveEmptyScriptsPlugin {
2419
outputPath = '';
2520
trash = [];
2621

22+
static STAGE_BEFORE_PROCESS_PLUGINS = 100;
23+
static STAGE_AFTER_PROCESS_PLUGINS = 200;
24+
2725
constructor (options) {
2826
this.apply = this.apply.bind(this);
2927
this.options = Object.assign({}, defaultOptions, options);
@@ -62,8 +60,7 @@ class WebpackRemoveEmptyScriptsPlugin {
6260
for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
6361
if (!compilation.modules.has(module)) {
6462
throw new Error(
65-
`\n${ansis.black.bgRed(
66-
`[${pluginName}]`)} entry module in chunk but not in compilation ${chunk.debugId} ${module.debugId}`,
63+
`${errorPluginName} Entry module in chunk but not in compilation ${chunk.debugId} ${module.debugId}`,
6764
);
6865
}
6966

@@ -79,14 +76,28 @@ class WebpackRemoveEmptyScriptsPlugin {
7976
resources.every(resource => styleExtensionRegexp.test(resource));
8077

8178
if (isEmptyScript) {
79+
const stage = this.options.stage;
8280
if (this.verbose) {
8381
const outputFile = path.join(this.outputPath, filename);
84-
outToConsole(
85-
`${ansis.black.bgYellow(`[${pluginName}]`)} remove ${ansis.cyan(outputFile)}\n`,
86-
);
82+
outToConsole(`${infoPluginName} remove ${cyan(outputFile)}\n`);
83+
}
84+
85+
switch (stage) {
86+
case WebpackRemoveEmptyScriptsPlugin.STAGE_BEFORE_PROCESS_PLUGINS:
87+
// remove empty script immediately, before other plugins will be called
88+
compilation.deleteAsset(filename);
89+
break;
90+
case WebpackRemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS:
91+
// add file to trash, which at 'afterProcessAssets' wird cleaned
92+
// remove empty script later, after all plugins are called
93+
this.trash.push(filename);
94+
break;
95+
default:
96+
throw new Error(
97+
`${errorPluginName} Invalid value of config option 'stage': ${gray(stage ? stage.toString() : '')}. `+
98+
`See the option description in README.`
99+
);
87100
}
88-
// note: do not delete here compilation empty assets, do it in 'afterProcessAssets' only
89-
this.trash.push(filename);
90101
}
91102
});
92103

@@ -99,6 +110,16 @@ class WebpackRemoveEmptyScriptsPlugin {
99110
}
100111
}
101112

113+
const defaultOptions = {
114+
enabled: true,
115+
verbose: false,
116+
/** @type {Array<string>|RegExp} */
117+
extensions: ['css', 'scss', 'sass', 'less', 'styl'],
118+
ignore: [],
119+
remove: /\.(js|mjs)$/,
120+
stage: WebpackRemoveEmptyScriptsPlugin.STAGE_BEFORE_PROCESS_PLUGINS,
121+
};
122+
102123
function getEntryResources (compilation, module, cache) {
103124
const moduleGraph = compilation.moduleGraph,
104125
index = moduleGraph.getPreOrderIndex(module),
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"style.css": {
3+
"src": "style.css"
4+
}
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
h1 {
2+
color: red;
3+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const path = require('path');
2+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3+
const RemoveEmptyScriptsPlugin = require('../../../src/index.js');
4+
5+
module.exports = {
6+
mode: 'production',
7+
output: {
8+
path: path.join(__dirname, 'public/'),
9+
},
10+
entry: { style: './src/style.css' },
11+
module: {
12+
rules: [
13+
{
14+
test: /\.css$/,
15+
use: [MiniCssExtractPlugin.loader, 'css-loader'],
16+
},
17+
],
18+
},
19+
plugins: [
20+
new RemoveEmptyScriptsPlugin({
21+
verbose: true,
22+
stage: 'INVALID_VALUE'
23+
}),
24+
new MiniCssExtractPlugin({
25+
filename: '[name].css',
26+
}),
27+
],
28+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"style.css": {
3+
"src": "style.css"
4+
}
5+
}

0 commit comments

Comments
 (0)