webpack 5.18.0 → 5.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/README.md +10 -47
- package/bin/webpack.js +0 -0
- package/lib/CleanPlugin.js +357 -0
- package/lib/CodeGenerationResults.js +28 -26
- package/lib/Compilation.js +192 -12
- package/lib/Dependency.js +1 -1
- package/lib/FlagDependencyUsagePlugin.js +8 -4
- package/lib/Generator.js +1 -0
- package/lib/ModuleGraph.js +8 -0
- package/lib/ModuleGraphConnection.js +3 -3
- package/lib/ModuleProfile.js +31 -4
- package/lib/NormalModule.js +17 -3
- package/lib/ProgressPlugin.js +12 -10
- package/lib/RuntimeGlobals.js +14 -0
- package/lib/RuntimePlugin.js +8 -0
- package/lib/RuntimeTemplate.js +1 -1
- package/lib/WebpackOptionsApply.js +16 -7
- package/lib/asset/AssetGenerator.js +10 -1
- package/lib/asset/AssetModulesPlugin.js +14 -5
- package/lib/async-modules/AwaitDependenciesInitFragment.js +12 -2
- package/lib/cache/IdleFileCachePlugin.js +9 -3
- package/lib/config/defaults.js +13 -2
- package/lib/config/normalization.js +1 -0
- package/lib/container/ContainerEntryModule.js +4 -1
- package/lib/container/ContainerPlugin.js +4 -2
- package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -4
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +1 -1
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +1 -1
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +13 -5
- package/lib/dependencies/URLDependency.js +9 -4
- package/lib/hmr/LazyCompilationPlugin.js +29 -3
- package/lib/hmr/lazyCompilationBackend.js +2 -3
- package/lib/index.js +4 -0
- package/lib/javascript/JavascriptModulesPlugin.js +2 -2
- package/lib/optimize/InnerGraph.js +28 -0
- package/lib/runtime/AsyncModuleRuntimeModule.js +137 -0
- package/lib/serialization/BinaryMiddleware.js +10 -2
- package/lib/sharing/ShareRuntimeModule.js +1 -1
- package/lib/util/ArrayQueue.js +103 -0
- package/lib/util/AsyncQueue.js +58 -27
- package/lib/util/ParallelismFactorCalculator.js +59 -0
- package/lib/util/fs.js +3 -0
- package/lib/util/runtime.js +135 -24
- package/lib/validateSchema.js +2 -2
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +24 -22
- package/package.json +2 -3
- package/schemas/WebpackOptions.json +65 -0
- package/schemas/_container.json +4 -0
- package/schemas/plugins/container/ContainerPlugin.json +4 -0
- package/schemas/plugins/container/ModuleFederationPlugin.json +4 -0
- package/types.d.ts +111 -19
package/README.md
CHANGED
@@ -111,14 +111,9 @@ within webpack itself use this plugin interface. This makes webpack very
|
|
111
111
|
| :---------------------------------------: | :----------------: | :-----------------: | :-------------------------------------------------------------------------------------- |
|
112
112
|
| [mini-css-extract-plugin][mini-css] | ![mini-css-npm] | ![mini-css-size] | Extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. |
|
113
113
|
| [compression-webpack-plugin][compression] | ![compression-npm] | ![compression-size] | Prepares compressed versions of assets to serve them with Content-Encoding |
|
114
|
-
| [i18n-webpack-plugin][i18n] | ![i18n-npm] | ![i18n-size] | Adds i18n support to your bundles |
|
115
114
|
| [html-webpack-plugin][html-plugin] | ![html-plugin-npm] | ![html-plugin-size] | Simplifies creation of HTML files (`index.html`) to serve your bundles |
|
116
|
-
| [extract-text-webpack-plugin][extract] | ![extract-npm] | ![extract-size] | Extract text from a bundle, or bundles, into a separate file |
|
117
115
|
|
118
116
|
[common-npm]: https://img.shields.io/npm/v/webpack.svg
|
119
|
-
[extract]: https://github.com/webpack-contrib/extract-text-webpack-plugin
|
120
|
-
[extract-npm]: https://img.shields.io/npm/v/extract-text-webpack-plugin.svg
|
121
|
-
[extract-size]: https://packagephobia.com/badge?p=extract-text-webpack-plugin
|
122
117
|
[mini-css]: https://github.com/webpack-contrib/mini-css-extract-plugin
|
123
118
|
[mini-css-npm]: https://img.shields.io/npm/v/mini-css-extract-plugin.svg
|
124
119
|
[mini-css-size]: https://packagephobia.com/badge?p=mini-css-extract-plugin
|
@@ -128,9 +123,6 @@ within webpack itself use this plugin interface. This makes webpack very
|
|
128
123
|
[compression]: https://github.com/webpack-contrib/compression-webpack-plugin
|
129
124
|
[compression-npm]: https://img.shields.io/npm/v/compression-webpack-plugin.svg
|
130
125
|
[compression-size]: https://packagephobia.com/badge?p=compression-webpack-plugin
|
131
|
-
[i18n]: https://github.com/webpack-contrib/i18n-webpack-plugin
|
132
|
-
[i18n-npm]: https://img.shields.io/npm/v/i18n-webpack-plugin.svg
|
133
|
-
[i18n-size]: https://packagephobia.com/badge?p=i18n-webpack-plugin
|
134
126
|
[html-plugin]: https://github.com/jantimon/html-webpack-plugin
|
135
127
|
[html-plugin-npm]: https://img.shields.io/npm/v/html-webpack-plugin.svg
|
136
128
|
[html-plugin-size]: https://packagephobia.com/badge?p=html-webpack-plugin
|
@@ -168,32 +160,22 @@ or are automatically applied via regex from your webpack configuration.
|
|
168
160
|
|
169
161
|
#### JSON
|
170
162
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
| <a href="https://github.com/webpack-contrib/json5-loader"><img width="48" height="10.656" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a> | ![json5-npm] | ![json5-size] | Loads and transpiles a JSON 5 file |
|
175
|
-
| <a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![cson-npm] | ![cson-size] | Loads and transpiles a CSON file |
|
163
|
+
| Name | Status | Install Size | Description |
|
164
|
+
| :---------------------------------------------------------------------------------------------------------------------------------------: | :---------: | :----------: | :------------------------------: |
|
165
|
+
| <a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![cson-npm] | ![cson-size] | Loads and transpiles a CSON file |
|
176
166
|
|
177
|
-
[json-npm]: https://img.shields.io/npm/v/json-loader.svg
|
178
|
-
[json-size]: https://packagephobia.com/badge?p=json-loader
|
179
|
-
[json5-npm]: https://img.shields.io/npm/v/json5-loader.svg
|
180
|
-
[json5-size]: https://packagephobia.com/badge?p=json5-loader
|
181
167
|
[cson-npm]: https://img.shields.io/npm/v/cson-loader.svg
|
182
168
|
[cson-size]: https://packagephobia.com/badge?p=cson-loader
|
183
169
|
|
184
170
|
#### Transpiling
|
185
171
|
|
186
|
-
| Name |
|
187
|
-
| :--------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
193
|
-
| <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
|
194
|
-
|
195
|
-
[script-npm]: https://img.shields.io/npm/v/script-loader.svg
|
196
|
-
[script-size]: https://packagephobia.com/badge?p=script-loader
|
172
|
+
| Name | Status | Install Size | Description |
|
173
|
+
| :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------: | :-------------: | :--------------------------------------------------------------------------------------------------- |
|
174
|
+
| <a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a> | ![babel-npm] | ![babel-size] | Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a> |
|
175
|
+
| <a href="https://github.com/jupl/traceur-loader"><img width="48" height="48" src="https://google.github.com/traceur-compiler/logo/tc.svg"></a> | ![traceur-npm] | ![traceur-size] | Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler) |
|
176
|
+
| <a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a> | ![type-npm] | ![type-size] | Loads TypeScript like JavaScript |
|
177
|
+
| <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
|
178
|
+
|
197
179
|
[babel-npm]: https://img.shields.io/npm/v/babel-loader.svg
|
198
180
|
[babel-size]: https://packagephobia.com/badge?p=babel-loader
|
199
181
|
[traceur-npm]: https://img.shields.io/npm/v/traceur-loader.svg
|
@@ -202,8 +184,6 @@ or are automatically applied via regex from your webpack configuration.
|
|
202
184
|
[coffee-size]: https://packagephobia.com/badge?p=coffee-loader
|
203
185
|
[type-npm]: https://img.shields.io/npm/v/ts-loader.svg
|
204
186
|
[type-size]: https://packagephobia.com/badge?p=ts-loader
|
205
|
-
[awesome-typescript-npm]: https://img.shields.io/npm/v/awesome-typescript-loader.svg
|
206
|
-
[awesome-typescript-size]: https://packagephobia.com/badge?p=awesome-typescript-loader
|
207
187
|
|
208
188
|
#### Templating
|
209
189
|
|
@@ -252,23 +232,6 @@ or are automatically applied via regex from your webpack configuration.
|
|
252
232
|
[postcss-npm]: https://img.shields.io/npm/v/postcss-loader.svg
|
253
233
|
[postcss-size]: https://packagephobia.com/badge?p=postcss-loader
|
254
234
|
|
255
|
-
#### Linting & Testing
|
256
|
-
|
257
|
-
| Name | Status | Install Size | Description |
|
258
|
-
| :--------------------------------------------------------------------------------------------------------------------------------------------: | :-----------: | :------------: | :-------------------------------------- |
|
259
|
-
| <a href="https://github.com/webpack-contrib/mocha-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/mocha.svg"></a> | ![mocha-npm] | ![mocha-size] | Tests with mocha (Browser/NodeJS) |
|
260
|
-
| <a href="https://github.com/webpack-contrib/eslint-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/eslint.svg"></a> | ![eslint-npm] | ![eslint-size] | PreLoader for linting code using ESLint |
|
261
|
-
| <a href="https://github.com/webpack-contrib/jshint-loader"><img width="48" height="20.64" src="https://jshint.com/res/jshint-dark.png"></a> | ![jshint-npm] | ![jshint-size] | PreLoader for linting code using JSHint |
|
262
|
-
|
263
|
-
[mocha-npm]: https://img.shields.io/npm/v/mocha-loader.svg
|
264
|
-
[mocha-size]: https://packagephobia.com/badge?p=mocha-loader
|
265
|
-
[eslint-npm]: https://img.shields.io/npm/v/eslint-loader.svg
|
266
|
-
[eslint-size]: https://packagephobia.com/badge?p=eslint-loader
|
267
|
-
[jshint-npm]: https://img.shields.io/npm/v/jshint-loader.svg
|
268
|
-
[jshint-size]: https://packagephobia.com/badge?p=jshint-loader
|
269
|
-
[jscs-npm]: https://img.shields.io/npm/v/jscs-loader.svg
|
270
|
-
[jscs-size]: https://packagephobia.com/badge?p=jscs-loader
|
271
|
-
|
272
235
|
#### Frameworks
|
273
236
|
|
274
237
|
| Name | Status | Install Size | Description |
|
package/bin/webpack.js
CHANGED
File without changes
|
@@ -0,0 +1,357 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Sergey Melyukov @smelukov
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
const asyncLib = require("neo-async");
|
9
|
+
const { validate } = require("schema-utils");
|
10
|
+
const { SyncBailHook } = require("tapable");
|
11
|
+
const Compilation = require("../lib/Compilation");
|
12
|
+
const { join } = require("./util/fs");
|
13
|
+
const memoize = require("./util/memoize");
|
14
|
+
const processAsyncTree = require("./util/processAsyncTree");
|
15
|
+
|
16
|
+
/** @typedef {import("../declarations/WebpackOptions").CleanOptions} CleanOptions */
|
17
|
+
/** @typedef {import("./Compiler")} Compiler */
|
18
|
+
/** @typedef {import("./logging/Logger").Logger} Logger */
|
19
|
+
/** @typedef {import("./util/fs").OutputFileSystem} OutputFileSystem */
|
20
|
+
|
21
|
+
/** @typedef {(function(string):boolean)|RegExp} IgnoreItem */
|
22
|
+
/** @typedef {function(IgnoreItem): void} AddToIgnoreCallback */
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @typedef {Object} CleanPluginCompilationHooks
|
26
|
+
* @property {SyncBailHook<[string], boolean>} keep when returning true the file/directory will be kept during cleaning, returning false will clean it and ignore the following plugins and config
|
27
|
+
*/
|
28
|
+
|
29
|
+
const getSchema = memoize(() => {
|
30
|
+
const { definitions } = require("../schemas/WebpackOptions.json");
|
31
|
+
return {
|
32
|
+
definitions,
|
33
|
+
oneOf: [{ $ref: "#/definitions/CleanOptions" }]
|
34
|
+
};
|
35
|
+
});
|
36
|
+
|
37
|
+
/**
|
38
|
+
* @param {OutputFileSystem} fs filesystem
|
39
|
+
* @param {string} outputPath output path
|
40
|
+
* @param {Set<string>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
|
41
|
+
* @param {function(Error=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
|
42
|
+
* @returns {void}
|
43
|
+
*/
|
44
|
+
const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
|
45
|
+
const directories = new Set();
|
46
|
+
// get directories of assets
|
47
|
+
for (const asset of currentAssets) {
|
48
|
+
directories.add(asset.replace(/(^|\/)[^/]*$/, ""));
|
49
|
+
}
|
50
|
+
// and all parent directories
|
51
|
+
for (const directory of directories) {
|
52
|
+
directories.add(directory.replace(/(^|\/)[^/]*$/, ""));
|
53
|
+
}
|
54
|
+
const diff = new Set();
|
55
|
+
asyncLib.forEachLimit(
|
56
|
+
directories,
|
57
|
+
10,
|
58
|
+
(directory, callback) => {
|
59
|
+
fs.readdir(join(fs, outputPath, directory), (err, entries) => {
|
60
|
+
if (err) {
|
61
|
+
if (err.code === "ENOENT") return callback();
|
62
|
+
if (err.code === "ENOTDIR") {
|
63
|
+
diff.add(directory);
|
64
|
+
return callback();
|
65
|
+
}
|
66
|
+
return callback(err);
|
67
|
+
}
|
68
|
+
for (const entry of entries) {
|
69
|
+
const file = /** @type {string} */ (entry);
|
70
|
+
const filename = directory ? `${directory}/${file}` : file;
|
71
|
+
if (!directories.has(filename) && !currentAssets.has(filename)) {
|
72
|
+
diff.add(filename);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
callback();
|
76
|
+
});
|
77
|
+
},
|
78
|
+
err => {
|
79
|
+
if (err) return callback(err);
|
80
|
+
|
81
|
+
callback(null, diff);
|
82
|
+
}
|
83
|
+
);
|
84
|
+
};
|
85
|
+
|
86
|
+
/**
|
87
|
+
* @param {Set<string>} currentAssets assets list
|
88
|
+
* @param {Set<string>} oldAssets old assets list
|
89
|
+
* @returns {Set<string>} diff
|
90
|
+
*/
|
91
|
+
const getDiffToOldAssets = (currentAssets, oldAssets) => {
|
92
|
+
const diff = new Set();
|
93
|
+
for (const asset of oldAssets) {
|
94
|
+
if (!currentAssets.has(asset)) diff.add(asset);
|
95
|
+
}
|
96
|
+
return diff;
|
97
|
+
};
|
98
|
+
|
99
|
+
/**
|
100
|
+
* @param {OutputFileSystem} fs filesystem
|
101
|
+
* @param {string} outputPath output path
|
102
|
+
* @param {boolean} dry only log instead of fs modification
|
103
|
+
* @param {Logger} logger logger
|
104
|
+
* @param {Set<string>} diff filenames of the assets that shouldn't be there
|
105
|
+
* @param {function(string): boolean} isKept check if the entry is ignored
|
106
|
+
* @param {function(Error=): void} callback callback
|
107
|
+
* @returns {void}
|
108
|
+
*/
|
109
|
+
const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
|
110
|
+
const log = msg => {
|
111
|
+
if (dry) {
|
112
|
+
logger.info(msg);
|
113
|
+
} else {
|
114
|
+
logger.log(msg);
|
115
|
+
}
|
116
|
+
};
|
117
|
+
/** @typedef {{ type: "check" | "unlink" | "rmdir", filename: string, parent: { remaining: number, job: Job } | undefined }} Job */
|
118
|
+
/** @type {Job[]} */
|
119
|
+
const jobs = Array.from(diff, filename => ({
|
120
|
+
type: "check",
|
121
|
+
filename,
|
122
|
+
parent: undefined
|
123
|
+
}));
|
124
|
+
processAsyncTree(
|
125
|
+
jobs,
|
126
|
+
10,
|
127
|
+
({ type, filename, parent }, push, callback) => {
|
128
|
+
const handleError = err => {
|
129
|
+
if (err.code === "ENOENT") {
|
130
|
+
log(`${filename} was removed during cleaning by something else`);
|
131
|
+
handleParent();
|
132
|
+
return callback();
|
133
|
+
}
|
134
|
+
return callback(err);
|
135
|
+
};
|
136
|
+
const handleParent = () => {
|
137
|
+
if (parent && --parent.remaining === 0) push(parent.job);
|
138
|
+
};
|
139
|
+
const path = join(fs, outputPath, filename);
|
140
|
+
switch (type) {
|
141
|
+
case "check":
|
142
|
+
if (isKept(filename)) {
|
143
|
+
// do not decrement parent entry as we don't want to delete the parent
|
144
|
+
log(`${filename} will be kept`);
|
145
|
+
return process.nextTick(callback);
|
146
|
+
}
|
147
|
+
fs.stat(path, (err, stats) => {
|
148
|
+
if (err) return handleError(err);
|
149
|
+
if (!stats.isDirectory()) {
|
150
|
+
push({
|
151
|
+
type: "unlink",
|
152
|
+
filename,
|
153
|
+
parent
|
154
|
+
});
|
155
|
+
return callback();
|
156
|
+
}
|
157
|
+
fs.readdir(path, (err, entries) => {
|
158
|
+
if (err) return handleError(err);
|
159
|
+
/** @type {Job} */
|
160
|
+
const deleteJob = {
|
161
|
+
type: "rmdir",
|
162
|
+
filename,
|
163
|
+
parent
|
164
|
+
};
|
165
|
+
if (entries.length === 0) {
|
166
|
+
push(deleteJob);
|
167
|
+
} else {
|
168
|
+
const parentToken = {
|
169
|
+
remaining: entries.length,
|
170
|
+
job: deleteJob
|
171
|
+
};
|
172
|
+
for (const entry of entries) {
|
173
|
+
const file = /** @type {string} */ (entry);
|
174
|
+
if (file.startsWith(".")) {
|
175
|
+
log(
|
176
|
+
`${filename} will be kept (dot-files will never be removed)`
|
177
|
+
);
|
178
|
+
continue;
|
179
|
+
}
|
180
|
+
push({
|
181
|
+
type: "check",
|
182
|
+
filename: `${filename}/${file}`,
|
183
|
+
parent: parentToken
|
184
|
+
});
|
185
|
+
}
|
186
|
+
}
|
187
|
+
return callback();
|
188
|
+
});
|
189
|
+
});
|
190
|
+
break;
|
191
|
+
case "rmdir":
|
192
|
+
log(`${filename} will be removed`);
|
193
|
+
if (dry) {
|
194
|
+
handleParent();
|
195
|
+
return process.nextTick(callback);
|
196
|
+
}
|
197
|
+
if (!fs.rmdir) {
|
198
|
+
logger.warn(
|
199
|
+
`${filename} can't be removed because output file system doesn't support removing directories (rmdir)`
|
200
|
+
);
|
201
|
+
return process.nextTick(callback);
|
202
|
+
}
|
203
|
+
fs.rmdir(path, err => {
|
204
|
+
if (err) return handleError(err);
|
205
|
+
handleParent();
|
206
|
+
callback();
|
207
|
+
});
|
208
|
+
break;
|
209
|
+
case "unlink":
|
210
|
+
log(`${filename} will be removed`);
|
211
|
+
if (dry) {
|
212
|
+
handleParent();
|
213
|
+
return process.nextTick(callback);
|
214
|
+
}
|
215
|
+
if (!fs.unlink) {
|
216
|
+
logger.warn(
|
217
|
+
`${filename} can't be removed because output file system doesn't support removing files (rmdir)`
|
218
|
+
);
|
219
|
+
return process.nextTick(callback);
|
220
|
+
}
|
221
|
+
fs.unlink(path, err => {
|
222
|
+
if (err) return handleError(err);
|
223
|
+
handleParent();
|
224
|
+
callback();
|
225
|
+
});
|
226
|
+
break;
|
227
|
+
}
|
228
|
+
},
|
229
|
+
callback
|
230
|
+
);
|
231
|
+
};
|
232
|
+
|
233
|
+
/** @type {WeakMap<Compilation, CleanPluginCompilationHooks>} */
|
234
|
+
const compilationHooksMap = new WeakMap();
|
235
|
+
|
236
|
+
class CleanPlugin {
|
237
|
+
/**
|
238
|
+
* @param {Compilation} compilation the compilation
|
239
|
+
* @returns {CleanPluginCompilationHooks} the attached hooks
|
240
|
+
*/
|
241
|
+
static getCompilationHooks(compilation) {
|
242
|
+
if (!(compilation instanceof Compilation)) {
|
243
|
+
throw new TypeError(
|
244
|
+
"The 'compilation' argument must be an instance of Compilation"
|
245
|
+
);
|
246
|
+
}
|
247
|
+
let hooks = compilationHooksMap.get(compilation);
|
248
|
+
if (hooks === undefined) {
|
249
|
+
hooks = {
|
250
|
+
/** @type {SyncBailHook<[string], boolean>} */
|
251
|
+
keep: new SyncBailHook(["ignore"])
|
252
|
+
};
|
253
|
+
compilationHooksMap.set(compilation, hooks);
|
254
|
+
}
|
255
|
+
return hooks;
|
256
|
+
}
|
257
|
+
|
258
|
+
/** @param {CleanOptions} [options] options */
|
259
|
+
constructor(options = {}) {
|
260
|
+
validate(getSchema(), options, {
|
261
|
+
name: "Clean Plugin",
|
262
|
+
baseDataPath: "options"
|
263
|
+
});
|
264
|
+
|
265
|
+
this.options = { dry: false, ...options };
|
266
|
+
}
|
267
|
+
|
268
|
+
/**
|
269
|
+
* Apply the plugin
|
270
|
+
* @param {Compiler} compiler the compiler instance
|
271
|
+
* @returns {void}
|
272
|
+
*/
|
273
|
+
apply(compiler) {
|
274
|
+
const { dry, keep } = this.options;
|
275
|
+
|
276
|
+
const keepFn =
|
277
|
+
typeof keep === "function"
|
278
|
+
? keep
|
279
|
+
: typeof keep === "string"
|
280
|
+
? path => path.startsWith(keep)
|
281
|
+
: typeof keep === "object" && keep.test
|
282
|
+
? path => keep.test(path)
|
283
|
+
: () => false;
|
284
|
+
|
285
|
+
// We assume that no external modification happens while the compiler is active
|
286
|
+
// So we can store the old assets and only diff to them to avoid fs access on
|
287
|
+
// incremental builds
|
288
|
+
let oldAssets;
|
289
|
+
|
290
|
+
compiler.hooks.emit.tapAsync(
|
291
|
+
{
|
292
|
+
name: "CleanPlugin",
|
293
|
+
stage: 100
|
294
|
+
},
|
295
|
+
(compilation, callback) => {
|
296
|
+
const hooks = CleanPlugin.getCompilationHooks(compilation);
|
297
|
+
const logger = compilation.getLogger("webpack.CleanPlugin");
|
298
|
+
const fs = compiler.outputFileSystem;
|
299
|
+
|
300
|
+
if (!fs.readdir) {
|
301
|
+
return callback(
|
302
|
+
new Error(
|
303
|
+
"CleanPlugin: Output filesystem doesn't support listing directories (readdir)"
|
304
|
+
)
|
305
|
+
);
|
306
|
+
}
|
307
|
+
|
308
|
+
const currentAssets = new Set();
|
309
|
+
for (const asset of Object.keys(compilation.assets)) {
|
310
|
+
if (/^[A-Za-z]:\\|^\/|^\\\\/.test(asset)) continue;
|
311
|
+
let normalizedAsset;
|
312
|
+
let newNormalizedAsset = asset.replace(/\\/g, "/");
|
313
|
+
do {
|
314
|
+
normalizedAsset = newNormalizedAsset;
|
315
|
+
newNormalizedAsset = normalizedAsset.replace(
|
316
|
+
/(^|\/)(?!\.\.)[^/]+\/\.\.\//g,
|
317
|
+
"$1"
|
318
|
+
);
|
319
|
+
} while (newNormalizedAsset !== normalizedAsset);
|
320
|
+
if (normalizedAsset.startsWith("../")) continue;
|
321
|
+
currentAssets.add(normalizedAsset);
|
322
|
+
}
|
323
|
+
|
324
|
+
const outputPath = compilation.getPath(compiler.outputPath, {});
|
325
|
+
|
326
|
+
const isKept = path => {
|
327
|
+
const result = hooks.keep.call(path);
|
328
|
+
if (result !== undefined) return result;
|
329
|
+
return keepFn(path);
|
330
|
+
};
|
331
|
+
|
332
|
+
const diffCallback = (err, diff) => {
|
333
|
+
if (err) {
|
334
|
+
oldAssets = undefined;
|
335
|
+
return callback(err);
|
336
|
+
}
|
337
|
+
applyDiff(fs, outputPath, dry, logger, diff, isKept, err => {
|
338
|
+
if (err) {
|
339
|
+
oldAssets = undefined;
|
340
|
+
} else {
|
341
|
+
oldAssets = currentAssets;
|
342
|
+
}
|
343
|
+
callback(err);
|
344
|
+
});
|
345
|
+
};
|
346
|
+
|
347
|
+
if (oldAssets) {
|
348
|
+
diffCallback(null, getDiffToOldAssets(currentAssets, oldAssets));
|
349
|
+
} else {
|
350
|
+
getDiffToFs(fs, outputPath, currentAssets, diffCallback);
|
351
|
+
}
|
352
|
+
}
|
353
|
+
);
|
354
|
+
}
|
355
|
+
}
|
356
|
+
|
357
|
+
module.exports = CleanPlugin;
|
@@ -18,8 +18,6 @@ class CodeGenerationResults {
|
|
18
18
|
constructor() {
|
19
19
|
/** @type {Map<Module, RuntimeSpecMap<CodeGenerationResult>>} */
|
20
20
|
this.map = new Map();
|
21
|
-
/** @type {Map<Module, RuntimeSpecMap<string>>} */
|
22
|
-
this.hashes = new Map();
|
23
21
|
}
|
24
22
|
|
25
23
|
/**
|
@@ -38,31 +36,33 @@ class CodeGenerationResults {
|
|
38
36
|
);
|
39
37
|
}
|
40
38
|
if (runtime === undefined) {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
entry.
|
46
|
-
|
47
|
-
|
39
|
+
if (entry.size > 1) {
|
40
|
+
const results = new Set(entry.values());
|
41
|
+
if (results.size !== 1) {
|
42
|
+
throw new Error(
|
43
|
+
`No unique code generation entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(
|
44
|
+
entry.keys(),
|
45
|
+
r => runtimeToString(r)
|
46
|
+
).join(", ")}).
|
48
47
|
Caller might not support runtime-dependent code generation (opt-out via optimization.usedExports: "global").`
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
} else {
|
53
|
-
const result = entry.get(runtime);
|
54
|
-
if (result === undefined) {
|
55
|
-
throw new Error(
|
56
|
-
`No code generation entry for runtime ${runtimeToString(
|
57
|
-
runtime
|
58
|
-
)} for ${module.identifier()} (existing runtimes: ${Array.from(
|
59
|
-
entry.keys(),
|
60
|
-
r => runtimeToString(r)
|
61
|
-
).join(", ")})`
|
62
|
-
);
|
48
|
+
);
|
49
|
+
}
|
50
|
+
return results.values().next().value;
|
63
51
|
}
|
64
|
-
return
|
52
|
+
return entry.values().next().value;
|
53
|
+
}
|
54
|
+
const result = entry.get(runtime);
|
55
|
+
if (result === undefined) {
|
56
|
+
throw new Error(
|
57
|
+
`No code generation entry for runtime ${runtimeToString(
|
58
|
+
runtime
|
59
|
+
)} for ${module.identifier()} (existing runtimes: ${Array.from(
|
60
|
+
entry.keys(),
|
61
|
+
r => runtimeToString(r)
|
62
|
+
).join(", ")})`
|
63
|
+
);
|
65
64
|
}
|
65
|
+
return result;
|
66
66
|
}
|
67
67
|
|
68
68
|
/**
|
@@ -75,11 +75,13 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
|
|
75
75
|
if (entry === undefined) {
|
76
76
|
return false;
|
77
77
|
}
|
78
|
-
if (runtime
|
78
|
+
if (runtime !== undefined) {
|
79
|
+
return entry.has(runtime);
|
80
|
+
} else if (entry.size > 1) {
|
79
81
|
const results = new Set(entry.values());
|
80
82
|
return results.size === 1;
|
81
83
|
} else {
|
82
|
-
return entry.
|
84
|
+
return entry.size === 1;
|
83
85
|
}
|
84
86
|
}
|
85
87
|
|