allow to disable some deprecations

add `experiments.backCompat: false` (default in `experiments.futureDefaults`)
remove unused `experiments.asset`
enable `experiments.topLevelAwait` and `experiments.asyncWebAssembly` by default in `experiments.futureDefaults`
This commit is contained in:
Tobias Koppers 2021-11-05 09:53:32 +01:00
parent 95b101fc8e
commit 7afcc5d4ff
13 changed files with 98 additions and 69 deletions

View File

@ -2738,14 +2738,14 @@ export interface EntryStaticNormalized {
* Enables/Disables experiments (experimental features with relax SemVer compatibility). * Enables/Disables experiments (experimental features with relax SemVer compatibility).
*/ */
export interface ExperimentsCommon { export interface ExperimentsCommon {
/**
* Allow module type 'asset' to generate assets.
*/
asset?: boolean;
/** /**
* Support WebAssembly as asynchronous EcmaScript Module. * Support WebAssembly as asynchronous EcmaScript Module.
*/ */
asyncWebAssembly?: boolean; asyncWebAssembly?: boolean;
/**
* Enable backward-compat layer with deprecation warnings for many webpack 4 APIs.
*/
backCompat?: boolean;
/** /**
* Enable additional in memory caching of modules that are unchanged and reference only unchanged modules. * Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.
*/ */
@ -2755,7 +2755,7 @@ export interface ExperimentsCommon {
*/ */
futureDefaults?: boolean; futureDefaults?: boolean;
/** /**
* Enable module and chunk layers. * Enable module layers.
*/ */
layers?: boolean; layers?: boolean;
/** /**

View File

@ -63,8 +63,9 @@ let debugId = 1000;
class Chunk { class Chunk {
/** /**
* @param {string=} name of chunk being created, is optional (for subclasses) * @param {string=} name of chunk being created, is optional (for subclasses)
* @param {boolean} backCompat enable backward-compatibility
*/ */
constructor(name) { constructor(name, backCompat = true) {
/** @type {number | string | null} */ /** @type {number | string | null} */
this.id = null; this.id = null;
/** @type {(number|string)[] | null} */ /** @type {(number|string)[] | null} */
@ -84,7 +85,7 @@ class Chunk {
/** @type {RuntimeSpec} */ /** @type {RuntimeSpec} */
this.runtime = undefined; this.runtime = undefined;
/** @type {Set<string>} */ /** @type {Set<string>} */
this.files = new ChunkFilesSet(); this.files = backCompat ? new ChunkFilesSet() : new Set();
/** @type {Set<string>} */ /** @type {Set<string>} */
this.auxiliaryFiles = new Set(); this.auxiliaryFiles = new Set();
/** @type {boolean} */ /** @type {boolean} */

View File

@ -429,6 +429,8 @@ class Compilation {
* @param {CompilationParams} params the compilation parameters * @param {CompilationParams} params the compilation parameters
*/ */
constructor(compiler, params) { constructor(compiler, params) {
this._backCompat = compiler._backCompat;
const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this); const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);
/** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */ /** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */
/** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */ /** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
@ -559,6 +561,7 @@ class Compilation {
* @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>} fake hook which redirects * @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>} fake hook which redirects
*/ */
const createProcessAssetsHook = (name, stage, getArgs, code) => { const createProcessAssetsHook = (name, stage, getArgs, code) => {
if (!this._backCompat && code) return undefined;
const errorMessage = const errorMessage =
reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}. reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`; BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`;
@ -983,7 +986,6 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
this.asyncEntrypoints = []; this.asyncEntrypoints = [];
/** @type {Set<Chunk>} */ /** @type {Set<Chunk>} */
this.chunks = new Set(); this.chunks = new Set();
arrayToSetDeprecation(this.chunks, "Compilation.chunks");
/** @type {ChunkGroup[]} */ /** @type {ChunkGroup[]} */
this.chunkGroups = []; this.chunkGroups = [];
/** @type {Map<string, ChunkGroup>} */ /** @type {Map<string, ChunkGroup>} */
@ -992,7 +994,10 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
this.namedChunks = new Map(); this.namedChunks = new Map();
/** @type {Set<Module>} */ /** @type {Set<Module>} */
this.modules = new Set(); this.modules = new Set();
if (this._backCompat) {
arrayToSetDeprecation(this.chunks, "Compilation.chunks");
arrayToSetDeprecation(this.modules, "Compilation.modules"); arrayToSetDeprecation(this.modules, "Compilation.modules");
}
/** @private @type {Map<string, Module>} */ /** @private @type {Map<string, Module>} */
this._modules = new Map(); this._modules = new Map();
this.records = null; this.records = null;
@ -1286,6 +1291,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
} }
this._modules.set(identifier, module); this._modules.set(identifier, module);
this.modules.add(module); this.modules.add(module);
if (this._backCompat)
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph); ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
if (currentProfile !== undefined) { if (currentProfile !== undefined) {
currentProfile.markIntegrationEnd(); currentProfile.markIntegrationEnd();
@ -1701,6 +1707,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
this._modules.set(module.identifier(), module); this._modules.set(module.identifier(), module);
this.modules.add(module); this.modules.add(module);
if (this._backCompat)
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph); ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
this._handleModuleBuildAndDependencies( this._handleModuleBuildAndDependencies(
@ -2777,9 +2784,11 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
); );
this.chunkGraph = chunkGraph; this.chunkGraph = chunkGraph;
if (this._backCompat) {
for (const module of this.modules) { for (const module of this.modules) {
ChunkGraph.setChunkGraphForModule(module, chunkGraph); ChunkGraph.setChunkGraphForModule(module, chunkGraph);
} }
}
this.hooks.seal.call(); this.hooks.seal.call();
@ -3045,14 +3054,16 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
} }
this.hooks.afterProcessAssets.call(this.assets); this.hooks.afterProcessAssets.call(this.assets);
this.logger.timeEnd("process assets"); this.logger.timeEnd("process assets");
this.assets = soonFrozenObjectDeprecation( this.assets = this._backCompat
? soonFrozenObjectDeprecation(
this.assets, this.assets,
"Compilation.assets", "Compilation.assets",
"DEP_WEBPACK_COMPILATION_ASSETS", "DEP_WEBPACK_COMPILATION_ASSETS",
`BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation. `BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
Do changes to assets earlier, e. g. in Compilation.hooks.processAssets. Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.` Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.`
); )
: Object.freeze(this.assets);
this.summarizeDependencies(); this.summarizeDependencies();
if (shouldRecord) { if (shouldRecord) {
@ -3453,6 +3464,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
*/ */
addRuntimeModule(chunk, module, chunkGraph = this.chunkGraph) { addRuntimeModule(chunk, module, chunkGraph = this.chunkGraph) {
// Deprecated ModuleGraph association // Deprecated ModuleGraph association
if (this._backCompat)
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph); ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
// add it to the list // add it to the list
@ -3589,8 +3601,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
return chunk; return chunk;
} }
} }
const chunk = new Chunk(name); const chunk = new Chunk(name, this._backCompat);
this.chunks.add(chunk); this.chunks.add(chunk);
if (this._backCompat)
ChunkGraph.setChunkGraphForChunk(chunk, this.chunkGraph); ChunkGraph.setChunkGraphForChunk(chunk, this.chunkGraph);
if (name) { if (name) {
this.namedChunks.set(name, chunk); this.namedChunks.set(name, chunk);
@ -4715,7 +4728,7 @@ This prevents using hashes of each other and should be avoided.`);
this.outputOptions; this.outputOptions;
const runtimeTemplate = this.runtimeTemplate; const runtimeTemplate = this.runtimeTemplate;
const chunk = new Chunk("build time chunk"); const chunk = new Chunk("build time chunk", this._backCompat);
chunk.id = chunk.name; chunk.id = chunk.name;
chunk.ids = [chunk.id]; chunk.ids = [chunk.id];
chunk.runtime = runtime; chunk.runtime = runtime;

View File

@ -119,8 +119,9 @@ const includesHash = (filename, hashes) => {
class Compiler { class Compiler {
/** /**
* @param {string} context the compilation path * @param {string} context the compilation path
* @param {WebpackOptions} options options
*/ */
constructor(context) { constructor(context, options = /** @type {WebpackOptions} */ ({})) {
this.hooks = Object.freeze({ this.hooks = Object.freeze({
/** @type {SyncHook<[]>} */ /** @type {SyncHook<[]>} */
initialize: new SyncHook([]), initialize: new SyncHook([]),
@ -240,8 +241,7 @@ class Compiler {
this.infrastructureLogger = undefined; this.infrastructureLogger = undefined;
/** @type {WebpackOptions} */ this.options = options;
this.options = /** @type {WebpackOptions} */ ({});
this.context = context; this.context = context;
@ -263,6 +263,8 @@ class Compiler {
/** @type {boolean} */ /** @type {boolean} */
this.watchMode = false; this.watchMode = false;
this._backCompat = this.options.experiments.backCompat !== false;
/** @type {Compilation} */ /** @type {Compilation} */
this._lastCompilation = undefined; this._lastCompilation = undefined;
/** @type {NormalModuleFactory} */ /** @type {NormalModuleFactory} */
@ -963,7 +965,13 @@ ${other}`);
outputOptions, outputOptions,
plugins plugins
) { ) {
const childCompiler = new Compiler(this.context); const childCompiler = new Compiler(this.context, {
...this.options,
output: {
...this.options.output,
...outputOptions
}
});
childCompiler.name = compilerName; childCompiler.name = compilerName;
childCompiler.outputPath = this.outputPath; childCompiler.outputPath = this.outputPath;
childCompiler.inputFileSystem = this.inputFileSystem; childCompiler.inputFileSystem = this.inputFileSystem;
@ -976,6 +984,7 @@ ${other}`);
childCompiler.fsStartTime = this.fsStartTime; childCompiler.fsStartTime = this.fsStartTime;
childCompiler.cache = this.cache; childCompiler.cache = this.cache;
childCompiler.compilerPath = `${this.compilerPath}${compilerName}|${compilerIndex}|`; childCompiler.compilerPath = `${this.compilerPath}${compilerName}|${compilerIndex}|`;
childCompiler._backCompat = this._backCompat;
const relativeCompilerName = makePathsRelative( const relativeCompilerName = makePathsRelative(
this.context, this.context,
@ -991,13 +1000,6 @@ ${other}`);
this.records[relativeCompilerName].push((childCompiler.records = {})); this.records[relativeCompilerName].push((childCompiler.records = {}));
} }
childCompiler.options = {
...this.options,
output: {
...this.options.output,
...outputOptions
}
};
childCompiler.parentCompilation = compilation; childCompiler.parentCompilation = compilation;
childCompiler.root = this.root; childCompiler.root = this.root;
if (Array.isArray(plugins)) { if (Array.isArray(plugins)) {

View File

@ -83,6 +83,7 @@ class HotModuleReplacementPlugin {
* @returns {void} * @returns {void}
*/ */
apply(compiler) { apply(compiler) {
const { _backCompat: backCompat } = compiler;
if (compiler.options.output.strictModuleErrorHandling === undefined) if (compiler.options.output.strictModuleErrorHandling === undefined)
compiler.options.output.strictModuleErrorHandling = true; compiler.options.output.strictModuleErrorHandling = true;
const runtimeRequirements = [RuntimeGlobals.module]; const runtimeRequirements = [RuntimeGlobals.module];
@ -597,6 +598,7 @@ class HotModuleReplacementPlugin {
(newRuntimeModules && newRuntimeModules.length > 0) (newRuntimeModules && newRuntimeModules.length > 0)
) { ) {
const hotUpdateChunk = new HotUpdateChunk(); const hotUpdateChunk = new HotUpdateChunk();
if (backCompat)
ChunkGraph.setChunkGraphForChunk(hotUpdateChunk, chunkGraph); ChunkGraph.setChunkGraphForChunk(hotUpdateChunk, chunkGraph);
hotUpdateChunk.id = chunkId; hotUpdateChunk.id = chunkId;
hotUpdateChunk.runtime = newRuntime; hotUpdateChunk.runtime = newRuntime;

View File

@ -265,15 +265,15 @@ const applyWebpackOptionsDefaults = options => {
* @returns {void} * @returns {void}
*/ */
const applyExperimentsDefaults = (experiments, { production, development }) => { const applyExperimentsDefaults = (experiments, { production, development }) => {
D(experiments, "topLevelAwait", false); D(experiments, "futureDefaults", false);
D(experiments, "backCompat", !experiments.futureDefaults);
D(experiments, "topLevelAwait", experiments.futureDefaults);
D(experiments, "syncWebAssembly", false); D(experiments, "syncWebAssembly", false);
D(experiments, "asyncWebAssembly", false); D(experiments, "asyncWebAssembly", experiments.futureDefaults);
D(experiments, "outputModule", false); D(experiments, "outputModule", false);
D(experiments, "asset", false);
D(experiments, "layers", false); D(experiments, "layers", false);
D(experiments, "lazyCompilation", undefined); D(experiments, "lazyCompilation", undefined);
D(experiments, "buildHttp", undefined); D(experiments, "buildHttp", undefined);
D(experiments, "futureDefaults", false);
D(experiments, "cacheUnaffected", experiments.futureDefaults); D(experiments, "cacheUnaffected", experiments.futureDefaults);
if (typeof experiments.buildHttp === "object") { if (typeof experiments.buildHttp === "object") {

View File

@ -56,6 +56,7 @@ class ModuleConcatenationPlugin {
* @returns {void} * @returns {void}
*/ */
apply(compiler) { apply(compiler) {
const { _backCompat: backCompat } = compiler;
compiler.hooks.compilation.tap("ModuleConcatenationPlugin", compilation => { compiler.hooks.compilation.tap("ModuleConcatenationPlugin", compilation => {
const moduleGraph = compilation.moduleGraph; const moduleGraph = compilation.moduleGraph;
const bailoutReasonMap = new Map(); const bailoutReasonMap = new Map();
@ -389,8 +390,10 @@ class ModuleConcatenationPlugin {
}; };
const integrate = () => { const integrate = () => {
if (backCompat) {
ChunkGraph.setChunkGraphForModule(newModule, chunkGraph); ChunkGraph.setChunkGraphForModule(newModule, chunkGraph);
ModuleGraph.setModuleGraphForModule(newModule, moduleGraph); ModuleGraph.setModuleGraphForModule(newModule, moduleGraph);
}
for (const warning of concatConfiguration.getWarningsSorted()) { for (const warning of concatConfiguration.getWarningsSorted()) {
moduleGraph moduleGraph

View File

@ -165,8 +165,16 @@ exports.arrayToSetDeprecation = (set, name) => {
}; };
exports.createArrayToSetDeprecationSet = name => { exports.createArrayToSetDeprecationSet = name => {
class SetDeprecatedArray extends Set {} let initialized = false;
class SetDeprecatedArray extends Set {
constructor(items) {
super(items);
if (!initialized) {
initialized = true;
exports.arrayToSetDeprecation(SetDeprecatedArray.prototype, name); exports.arrayToSetDeprecation(SetDeprecatedArray.prototype, name);
}
}
}
return SetDeprecatedArray; return SetDeprecatedArray;
}; };

View File

@ -61,8 +61,7 @@ const createMultiCompiler = (childOptions, options) => {
const createCompiler = rawOptions => { const createCompiler = rawOptions => {
const options = getNormalizedWebpackOptions(rawOptions); const options = getNormalizedWebpackOptions(rawOptions);
applyWebpackOptionsBaseDefaults(options); applyWebpackOptionsBaseDefaults(options);
const compiler = new Compiler(options.context); const compiler = new Compiler(options.context, options);
compiler.options = options;
new NodeEnvironmentPlugin({ new NodeEnvironmentPlugin({
infrastructureLogging: options.infrastructureLogging infrastructureLogging: options.infrastructureLogging
}).apply(compiler); }).apply(compiler);

File diff suppressed because one or more lines are too long

View File

@ -681,14 +681,14 @@
"implements": ["#/definitions/ExperimentsCommon"], "implements": ["#/definitions/ExperimentsCommon"],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"asset": {
"description": "Allow module type 'asset' to generate assets.",
"type": "boolean"
},
"asyncWebAssembly": { "asyncWebAssembly": {
"description": "Support WebAssembly as asynchronous EcmaScript Module.", "description": "Support WebAssembly as asynchronous EcmaScript Module.",
"type": "boolean" "type": "boolean"
}, },
"backCompat": {
"description": "Enable backward-compat layer with deprecation warnings for many webpack 4 APIs.",
"type": "boolean"
},
"buildHttp": { "buildHttp": {
"description": "Build http(s): urls using a lockfile and resource content cache.", "description": "Build http(s): urls using a lockfile and resource content cache.",
"anyOf": [ "anyOf": [
@ -709,7 +709,7 @@
"type": "boolean" "type": "boolean"
}, },
"layers": { "layers": {
"description": "Enable module and chunk layers.", "description": "Enable module layers.",
"type": "boolean" "type": "boolean"
}, },
"lazyCompilation": { "lazyCompilation": {
@ -742,14 +742,14 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"asset": {
"description": "Allow module type 'asset' to generate assets.",
"type": "boolean"
},
"asyncWebAssembly": { "asyncWebAssembly": {
"description": "Support WebAssembly as asynchronous EcmaScript Module.", "description": "Support WebAssembly as asynchronous EcmaScript Module.",
"type": "boolean" "type": "boolean"
}, },
"backCompat": {
"description": "Enable backward-compat layer with deprecation warnings for many webpack 4 APIs.",
"type": "boolean"
},
"cacheUnaffected": { "cacheUnaffected": {
"description": "Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.", "description": "Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.",
"type": "boolean" "type": "boolean"
@ -759,7 +759,7 @@
"type": "boolean" "type": "boolean"
}, },
"layers": { "layers": {
"description": "Enable module and chunk layers.", "description": "Enable module layers.",
"type": "boolean" "type": "boolean"
}, },
"outputModule": { "outputModule": {
@ -782,14 +782,14 @@
"implements": ["#/definitions/ExperimentsCommon"], "implements": ["#/definitions/ExperimentsCommon"],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"asset": {
"description": "Allow module type 'asset' to generate assets.",
"type": "boolean"
},
"asyncWebAssembly": { "asyncWebAssembly": {
"description": "Support WebAssembly as asynchronous EcmaScript Module.", "description": "Support WebAssembly as asynchronous EcmaScript Module.",
"type": "boolean" "type": "boolean"
}, },
"backCompat": {
"description": "Enable backward-compat layer with deprecation warnings for many webpack 4 APIs.",
"type": "boolean"
},
"buildHttp": { "buildHttp": {
"description": "Build http(s): urls using a lockfile and resource content cache.", "description": "Build http(s): urls using a lockfile and resource content cache.",
"oneOf": [ "oneOf": [
@ -807,7 +807,7 @@
"type": "boolean" "type": "boolean"
}, },
"layers": { "layers": {
"description": "Enable module and chunk layers.", "description": "Enable module layers.",
"type": "boolean" "type": "boolean"
}, },
"lazyCompilation": { "lazyCompilation": {

View File

@ -185,6 +185,7 @@ const describeCases = config => {
experiments: { experiments: {
asyncWebAssembly: true, asyncWebAssembly: true,
topLevelAwait: true, topLevelAwait: true,
backCompat: false,
...(config.module ? { outputModule: true } : {}) ...(config.module ? { outputModule: true } : {})
} }
}; };

16
types.d.ts vendored
View File

@ -691,7 +691,7 @@ declare interface CallbackWebpack<T> {
} }
type Cell<T> = undefined | T; type Cell<T> = undefined | T;
declare class Chunk { declare class Chunk {
constructor(name?: string); constructor(name?: string, backCompat?: boolean);
id: null | string | number; id: null | string | number;
ids: null | (string | number)[]; ids: null | (string | number)[];
debugId: number; debugId: number;
@ -1857,7 +1857,7 @@ declare interface CompilationParams {
contextModuleFactory: ContextModuleFactory; contextModuleFactory: ContextModuleFactory;
} }
declare class Compiler { declare class Compiler {
constructor(context: string); constructor(context: string, options?: WebpackOptionsNormalized);
hooks: Readonly<{ hooks: Readonly<{
initialize: SyncHook<[]>; initialize: SyncHook<[]>;
shouldEmit: SyncBailHook<[Compilation], boolean>; shouldEmit: SyncBailHook<[Compilation], boolean>;
@ -3303,16 +3303,16 @@ type Experiments = ExperimentsCommon & ExperimentsExtra;
* Enables/Disables experiments (experimental features with relax SemVer compatibility). * Enables/Disables experiments (experimental features with relax SemVer compatibility).
*/ */
declare interface ExperimentsCommon { declare interface ExperimentsCommon {
/**
* Allow module type 'asset' to generate assets.
*/
asset?: boolean;
/** /**
* Support WebAssembly as asynchronous EcmaScript Module. * Support WebAssembly as asynchronous EcmaScript Module.
*/ */
asyncWebAssembly?: boolean; asyncWebAssembly?: boolean;
/**
* Enable backward-compat layer with deprecation warnings for many webpack 4 APIs.
*/
backCompat?: boolean;
/** /**
* Enable additional in memory caching of modules that are unchanged and reference only unchanged modules. * Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.
*/ */
@ -3324,7 +3324,7 @@ declare interface ExperimentsCommon {
futureDefaults?: boolean; futureDefaults?: boolean;
/** /**
* Enable module and chunk layers. * Enable module layers.
*/ */
layers?: boolean; layers?: boolean;