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).
*/
export interface ExperimentsCommon {
/**
* Allow module type 'asset' to generate assets.
*/
asset?: boolean;
/**
* Support WebAssembly as asynchronous EcmaScript Module.
*/
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.
*/
@ -2755,7 +2755,7 @@ export interface ExperimentsCommon {
*/
futureDefaults?: boolean;
/**
* Enable module and chunk layers.
* Enable module layers.
*/
layers?: boolean;
/**

View File

@ -63,8 +63,9 @@ let debugId = 1000;
class Chunk {
/**
* @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} */
this.id = null;
/** @type {(number|string)[] | null} */
@ -84,7 +85,7 @@ class Chunk {
/** @type {RuntimeSpec} */
this.runtime = undefined;
/** @type {Set<string>} */
this.files = new ChunkFilesSet();
this.files = backCompat ? new ChunkFilesSet() : new Set();
/** @type {Set<string>} */
this.auxiliaryFiles = new Set();
/** @type {boolean} */

View File

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

View File

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

View File

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

View File

@ -265,15 +265,15 @@ const applyWebpackOptionsDefaults = options => {
* @returns {void}
*/
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, "asyncWebAssembly", false);
D(experiments, "asyncWebAssembly", experiments.futureDefaults);
D(experiments, "outputModule", false);
D(experiments, "asset", false);
D(experiments, "layers", false);
D(experiments, "lazyCompilation", undefined);
D(experiments, "buildHttp", undefined);
D(experiments, "futureDefaults", false);
D(experiments, "cacheUnaffected", experiments.futureDefaults);
if (typeof experiments.buildHttp === "object") {

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

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

16
types.d.ts vendored
View File

@ -691,7 +691,7 @@ declare interface CallbackWebpack<T> {
}
type Cell<T> = undefined | T;
declare class Chunk {
constructor(name?: string);
constructor(name?: string, backCompat?: boolean);
id: null | string | number;
ids: null | (string | number)[];
debugId: number;
@ -1857,7 +1857,7 @@ declare interface CompilationParams {
contextModuleFactory: ContextModuleFactory;
}
declare class Compiler {
constructor(context: string);
constructor(context: string, options?: WebpackOptionsNormalized);
hooks: Readonly<{
initialize: SyncHook<[]>;
shouldEmit: SyncBailHook<[Compilation], boolean>;
@ -3303,16 +3303,16 @@ type Experiments = ExperimentsCommon & ExperimentsExtra;
* Enables/Disables experiments (experimental features with relax SemVer compatibility).
*/
declare interface ExperimentsCommon {
/**
* Allow module type 'asset' to generate assets.
*/
asset?: boolean;
/**
* Support WebAssembly as asynchronous EcmaScript Module.
*/
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.
*/
@ -3324,7 +3324,7 @@ declare interface ExperimentsCommon {
futureDefaults?: boolean;
/**
* Enable module and chunk layers.
* Enable module layers.
*/
layers?: boolean;