webpack 4.28.1 → 4.29.0
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.
- package/declarations/WebpackOptions.d.ts +4 -0
- package/lib/Compilation.js +2 -0
- package/lib/Compiler.js +136 -13
- package/lib/IgnorePlugin.js +2 -0
- package/lib/Parser.js +11 -7
- package/lib/Stats.js +4 -1
- package/lib/WebpackOptionsApply.js +1 -1
- package/lib/debug/ProfilingPlugin.js +6 -0
- package/lib/dependencies/AMDRequireDependenciesBlock.js +5 -1
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +7 -3
- package/package.json +3 -3
- package/schemas/WebpackOptions.json +4 -0
@@ -1051,6 +1051,10 @@ export interface OutputOptions {
|
|
1051
1051
|
* Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
|
1052
1052
|
*/
|
1053
1053
|
filename?: string | Function;
|
1054
|
+
/**
|
1055
|
+
* Use the future version of asset emitting logic, which is allows freeing memory of assets after emitting. It could break plugins which assume that assets are still readable after emitting. Will be the new default in the next major version.
|
1056
|
+
*/
|
1057
|
+
futureEmitAssets?: boolean;
|
1054
1058
|
/**
|
1055
1059
|
* An expression which is used to address the global object/scope in runtime code
|
1056
1060
|
*/
|
package/lib/Compilation.js
CHANGED
@@ -491,6 +491,8 @@ class Compilation extends Tapable {
|
|
491
491
|
this._buildingModules = new Map();
|
492
492
|
/** @private @type {Map<Module, Callback[]>} */
|
493
493
|
this._rebuildingModules = new Map();
|
494
|
+
/** @type {Set<string>} */
|
495
|
+
this.emittedAssets = new Set();
|
494
496
|
}
|
495
497
|
|
496
498
|
getStats() {
|
package/lib/Compiler.js
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
const parseJson = require("json-parse-better-errors");
|
8
8
|
const asyncLib = require("neo-async");
|
9
9
|
const path = require("path");
|
10
|
+
const { Source } = require("webpack-sources");
|
10
11
|
const util = require("util");
|
11
12
|
const {
|
12
13
|
Tapable,
|
@@ -188,6 +189,11 @@ class Compiler extends Tapable {
|
|
188
189
|
|
189
190
|
/** @type {boolean} */
|
190
191
|
this.watchMode = false;
|
192
|
+
|
193
|
+
/** @private @type {WeakMap<Source, { sizeOnlySource: SizeOnlySource, writtenTo: Map<string, number> }>} */
|
194
|
+
this._assetEmittingSourceCache = new WeakMap();
|
195
|
+
/** @private @type {Map<string, number>} */
|
196
|
+
this._assetEmittingWrittenFiles = new Map();
|
191
197
|
}
|
192
198
|
|
193
199
|
watch(watchOptions, handler) {
|
@@ -207,6 +213,10 @@ class Compiler extends Tapable {
|
|
207
213
|
const finalCallback = (err, stats) => {
|
208
214
|
this.running = false;
|
209
215
|
|
216
|
+
if (err) {
|
217
|
+
this.hooks.failed.call(err);
|
218
|
+
}
|
219
|
+
|
210
220
|
if (callback !== undefined) return callback(err, stats);
|
211
221
|
};
|
212
222
|
|
@@ -308,8 +318,9 @@ class Compiler extends Tapable {
|
|
308
318
|
const emitFiles = err => {
|
309
319
|
if (err) return callback(err);
|
310
320
|
|
311
|
-
asyncLib.
|
321
|
+
asyncLib.forEachLimit(
|
312
322
|
compilation.assets,
|
323
|
+
15,
|
313
324
|
(source, file, callback) => {
|
314
325
|
let targetFile = file;
|
315
326
|
const queryStringIdx = targetFile.indexOf("?");
|
@@ -323,19 +334,86 @@ class Compiler extends Tapable {
|
|
323
334
|
outputPath,
|
324
335
|
targetFile
|
325
336
|
);
|
326
|
-
|
327
|
-
|
328
|
-
|
337
|
+
// TODO webpack 5 remove futureEmitAssets option and make it on by default
|
338
|
+
if (this.options.output.futureEmitAssets) {
|
339
|
+
// check if the target file has already been written by this Compiler
|
340
|
+
const targetFileGeneration = this._assetEmittingWrittenFiles.get(
|
341
|
+
targetPath
|
342
|
+
);
|
343
|
+
|
344
|
+
// create an cache entry for this Source if not already existing
|
345
|
+
let cacheEntry = this._assetEmittingSourceCache.get(source);
|
346
|
+
if (cacheEntry === undefined) {
|
347
|
+
cacheEntry = {
|
348
|
+
sizeOnlySource: undefined,
|
349
|
+
writtenTo: new Map()
|
350
|
+
};
|
351
|
+
this._assetEmittingSourceCache.set(source, cacheEntry);
|
352
|
+
}
|
353
|
+
|
354
|
+
// if the target file has already been written
|
355
|
+
if (targetFileGeneration !== undefined) {
|
356
|
+
// check if the Source has been written to this target file
|
357
|
+
const writtenGeneration = cacheEntry.writtenTo.get(targetPath);
|
358
|
+
if (writtenGeneration === targetFileGeneration) {
|
359
|
+
// if yes, we skip writing the file
|
360
|
+
// as it's already there
|
361
|
+
// (we assume one doesn't remove files while the Compiler is running)
|
362
|
+
return callback();
|
363
|
+
}
|
364
|
+
}
|
365
|
+
|
366
|
+
// get the binary (Buffer) content from the Source
|
367
|
+
/** @type {Buffer} */
|
368
|
+
let content;
|
369
|
+
if (typeof source.buffer === "function") {
|
370
|
+
content = source.buffer();
|
371
|
+
} else {
|
372
|
+
const bufferOrString = source.source();
|
373
|
+
if (Buffer.isBuffer(bufferOrString)) {
|
374
|
+
content = bufferOrString;
|
375
|
+
} else {
|
376
|
+
content = Buffer.from(bufferOrString, "utf8");
|
377
|
+
}
|
378
|
+
}
|
379
|
+
|
380
|
+
// Create a replacement resource which only allows to ask for size
|
381
|
+
// This allows to GC all memory allocated by the Source
|
382
|
+
// (expect when the Source is stored in any other cache)
|
383
|
+
cacheEntry.sizeOnlySource = new SizeOnlySource(content.length);
|
384
|
+
compilation.assets[file] = cacheEntry.sizeOnlySource;
|
385
|
+
|
386
|
+
// Write the file to output file system
|
387
|
+
this.outputFileSystem.writeFile(targetPath, content, err => {
|
388
|
+
if (err) return callback(err);
|
389
|
+
|
390
|
+
// information marker that the asset has been emitted
|
391
|
+
compilation.emittedAssets.add(file);
|
392
|
+
|
393
|
+
// cache the information that the Source has been written to that location
|
394
|
+
const newGeneration =
|
395
|
+
targetFileGeneration === undefined
|
396
|
+
? 1
|
397
|
+
: targetFileGeneration + 1;
|
398
|
+
cacheEntry.writtenTo.set(targetPath, newGeneration);
|
399
|
+
this._assetEmittingWrittenFiles.set(targetPath, newGeneration);
|
400
|
+
callback();
|
401
|
+
});
|
402
|
+
} else {
|
403
|
+
if (source.existsAt === targetPath) {
|
404
|
+
source.emitted = false;
|
405
|
+
return callback();
|
406
|
+
}
|
407
|
+
let content = source.source();
|
408
|
+
|
409
|
+
if (!Buffer.isBuffer(content)) {
|
410
|
+
content = Buffer.from(content, "utf8");
|
411
|
+
}
|
412
|
+
|
413
|
+
source.existsAt = targetPath;
|
414
|
+
source.emitted = true;
|
415
|
+
this.outputFileSystem.writeFile(targetPath, content, callback);
|
329
416
|
}
|
330
|
-
let content = source.source();
|
331
|
-
|
332
|
-
if (!Buffer.isBuffer(content)) {
|
333
|
-
content = Buffer.from(content, "utf8");
|
334
|
-
}
|
335
|
-
|
336
|
-
source.existsAt = targetPath;
|
337
|
-
source.emitted = true;
|
338
|
-
this.outputFileSystem.writeFile(targetPath, content, callback);
|
339
417
|
};
|
340
418
|
|
341
419
|
if (targetFile.match(/\/|\\/)) {
|
@@ -558,3 +636,48 @@ class Compiler extends Tapable {
|
|
558
636
|
}
|
559
637
|
|
560
638
|
module.exports = Compiler;
|
639
|
+
|
640
|
+
class SizeOnlySource extends Source {
|
641
|
+
constructor(size) {
|
642
|
+
super();
|
643
|
+
this._size = size;
|
644
|
+
}
|
645
|
+
|
646
|
+
_error() {
|
647
|
+
return new Error(
|
648
|
+
"Content and Map of this Source is no longer available (only size() is supported)"
|
649
|
+
);
|
650
|
+
}
|
651
|
+
|
652
|
+
size() {
|
653
|
+
return this._size;
|
654
|
+
}
|
655
|
+
|
656
|
+
/**
|
657
|
+
* @param {any} options options
|
658
|
+
* @returns {string} the source
|
659
|
+
*/
|
660
|
+
source(options) {
|
661
|
+
throw this._error();
|
662
|
+
}
|
663
|
+
|
664
|
+
node() {
|
665
|
+
throw this._error();
|
666
|
+
}
|
667
|
+
|
668
|
+
listMap() {
|
669
|
+
throw this._error();
|
670
|
+
}
|
671
|
+
|
672
|
+
map() {
|
673
|
+
throw this._error();
|
674
|
+
}
|
675
|
+
|
676
|
+
listNode() {
|
677
|
+
throw this._error();
|
678
|
+
}
|
679
|
+
|
680
|
+
updateHash() {
|
681
|
+
throw this._error();
|
682
|
+
}
|
683
|
+
}
|
package/lib/IgnorePlugin.js
CHANGED
package/lib/Parser.js
CHANGED
@@ -6,7 +6,8 @@
|
|
6
6
|
|
7
7
|
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
|
8
8
|
|
9
|
-
const acorn = require("acorn
|
9
|
+
const acorn = require("acorn");
|
10
|
+
const acornDynamicImport = require("acorn-dynamic-import").default;
|
10
11
|
const { Tapable, SyncBailHook, HookMap } = require("tapable");
|
11
12
|
const util = require("util");
|
12
13
|
const vm = require("vm");
|
@@ -14,6 +15,8 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|
14
15
|
const StackedSetMap = require("./util/StackedSetMap");
|
15
16
|
const TrackingSet = require("./util/TrackingSet");
|
16
17
|
|
18
|
+
const acornParser = acorn.Parser.extend(acornDynamicImport);
|
19
|
+
|
17
20
|
const joinRanges = (startRange, endRange) => {
|
18
21
|
if (!endRange) return startRange;
|
19
22
|
if (!startRange) return endRange;
|
@@ -25,10 +28,7 @@ const defaultParserOptions = {
|
|
25
28
|
locations: true,
|
26
29
|
ecmaVersion: 2019,
|
27
30
|
sourceType: "module",
|
28
|
-
onComment: null
|
29
|
-
plugins: {
|
30
|
-
dynamicImport: true
|
31
|
-
}
|
31
|
+
onComment: null
|
32
32
|
};
|
33
33
|
|
34
34
|
// regexp to match at lease one "magic comment"
|
@@ -2133,9 +2133,13 @@ class Parser extends Tapable {
|
|
2133
2133
|
sourceType: this.sourceType,
|
2134
2134
|
locations: false
|
2135
2135
|
});
|
2136
|
+
// TODO(https://github.com/acornjs/acorn/issues/741)
|
2137
|
+
// @ts-ignore
|
2136
2138
|
if (ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") {
|
2137
2139
|
throw new Error("evaluate: Source is not a expression");
|
2138
2140
|
}
|
2141
|
+
// TODO(https://github.com/acornjs/acorn/issues/741)
|
2142
|
+
// @ts-ignore
|
2139
2143
|
return this.evaluateExpression(ast.body[0].expression);
|
2140
2144
|
}
|
2141
2145
|
|
@@ -2226,7 +2230,7 @@ class Parser extends Tapable {
|
|
2226
2230
|
let error;
|
2227
2231
|
let threw = false;
|
2228
2232
|
try {
|
2229
|
-
ast =
|
2233
|
+
ast = acornParser.parse(code, parserOptions);
|
2230
2234
|
} catch (e) {
|
2231
2235
|
error = e;
|
2232
2236
|
threw = true;
|
@@ -2238,7 +2242,7 @@ class Parser extends Tapable {
|
|
2238
2242
|
parserOptions.onComment.length = 0;
|
2239
2243
|
}
|
2240
2244
|
try {
|
2241
|
-
ast =
|
2245
|
+
ast = acornParser.parse(code, parserOptions);
|
2242
2246
|
threw = false;
|
2243
2247
|
} catch (e) {
|
2244
2248
|
threw = true;
|
package/lib/Stats.js
CHANGED
@@ -400,7 +400,10 @@ class Stats {
|
|
400
400
|
size: compilation.assets[asset].size(),
|
401
401
|
chunks: [],
|
402
402
|
chunkNames: [],
|
403
|
-
|
403
|
+
// TODO webpack 5: remove .emitted
|
404
|
+
emitted:
|
405
|
+
compilation.assets[asset].emitted ||
|
406
|
+
compilation.emittedAssets.has(asset)
|
404
407
|
};
|
405
408
|
|
406
409
|
if (showPerformance) {
|
@@ -463,7 +463,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|
463
463
|
if (options.optimization.minimize) {
|
464
464
|
for (const minimizer of options.optimization.minimizer) {
|
465
465
|
if (typeof minimizer === "function") {
|
466
|
-
minimizer.
|
466
|
+
minimizer.call(compiler, compiler);
|
467
467
|
} else {
|
468
468
|
minimizer.apply(compiler);
|
469
469
|
}
|
@@ -1,4 +1,6 @@
|
|
1
1
|
const fs = require("fs");
|
2
|
+
const path = require("path");
|
3
|
+
const mkdirp = require("mkdirp");
|
2
4
|
const { Tracer } = require("chrome-trace-event");
|
3
5
|
const validateOptions = require("schema-utils");
|
4
6
|
const schema = require("../../schemas/plugins/debug/ProfilingPlugin.json");
|
@@ -93,6 +95,10 @@ const createTrace = outputPath => {
|
|
93
95
|
noStream: true
|
94
96
|
});
|
95
97
|
const profiler = new Profiler(inspector);
|
98
|
+
if (/\/|\\/.test(outputPath)) {
|
99
|
+
const dirPath = path.dirname(outputPath);
|
100
|
+
mkdirp.sync(dirPath);
|
101
|
+
}
|
96
102
|
const fsStream = fs.createWriteStream(outputPath);
|
97
103
|
|
98
104
|
let counter = 0;
|
@@ -36,8 +36,12 @@ module.exports = class AMDRequireDependenciesBlock extends AsyncDependenciesBloc
|
|
36
36
|
} else {
|
37
37
|
this.range = expr.range;
|
38
38
|
}
|
39
|
-
const dep =
|
39
|
+
const dep = this.newRequireDependency();
|
40
40
|
dep.loc = loc;
|
41
41
|
this.addDependency(dep);
|
42
42
|
}
|
43
|
+
|
44
|
+
newRequireDependency() {
|
45
|
+
return new AMDRequireDependency(this);
|
46
|
+
}
|
43
47
|
};
|
@@ -13,9 +13,13 @@ module.exports = class HarmonyDetectionParserPlugin {
|
|
13
13
|
const isStrictHarmony = parser.state.module.type === "javascript/esm";
|
14
14
|
const isHarmony =
|
15
15
|
isStrictHarmony ||
|
16
|
-
ast.body.some(
|
17
|
-
|
18
|
-
|
16
|
+
ast.body.some(
|
17
|
+
statement =>
|
18
|
+
statement.type === "ImportDeclaration" ||
|
19
|
+
statement.type === "ExportDefaultDeclaration" ||
|
20
|
+
statement.type === "ExportNamedDeclaration" ||
|
21
|
+
statement.type === "ExportAllDeclaration"
|
22
|
+
);
|
19
23
|
if (isHarmony) {
|
20
24
|
const module = parser.state.module;
|
21
25
|
const compatDep = new HarmonyCompatibilityDependency(module);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webpack",
|
3
|
-
"version": "4.
|
3
|
+
"version": "4.29.0",
|
4
4
|
"author": "Tobias Koppers @sokra",
|
5
5
|
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
|
6
6
|
"license": "MIT",
|
@@ -9,8 +9,8 @@
|
|
9
9
|
"@webassemblyjs/helper-module-context": "1.7.11",
|
10
10
|
"@webassemblyjs/wasm-edit": "1.7.11",
|
11
11
|
"@webassemblyjs/wasm-parser": "1.7.11",
|
12
|
-
"acorn": "^
|
13
|
-
"acorn-dynamic-import": "^
|
12
|
+
"acorn": "^6.0.5",
|
13
|
+
"acorn-dynamic-import": "^4.0.0",
|
14
14
|
"ajv": "^6.1.0",
|
15
15
|
"ajv-keywords": "^3.1.0",
|
16
16
|
"chrome-trace-event": "^1.0.0",
|
@@ -867,6 +867,10 @@
|
|
867
867
|
}
|
868
868
|
]
|
869
869
|
},
|
870
|
+
"futureEmitAssets": {
|
871
|
+
"description": "Use the future version of asset emitting logic, which is allows freeing memory of assets after emitting. It could break plugins which assume that assets are still readable after emitting. Will be the new default in the next major version.",
|
872
|
+
"type": "boolean"
|
873
|
+
},
|
870
874
|
"globalObject": {
|
871
875
|
"description": "An expression which is used to address the global object/scope in runtime code",
|
872
876
|
"type": "string",
|