diff --git a/lib/ChunkGraph.js b/lib/ChunkGraph.js index ba351e17d..853a09d9d 100644 --- a/lib/ChunkGraph.js +++ b/lib/ChunkGraph.js @@ -85,14 +85,17 @@ const getModuleRuntimes = chunks => { }; /** - * @param {SortableSet} set the set - * @returns {Map>} modules by source type + * @param {WeakMap> | undefined} sourceTypesByModule sourceTypesByModule + * @returns {function (SortableSet): Map>} modules by source type */ -const modulesBySourceType = set => { +const modulesBySourceType = sourceTypesByModule => set => { /** @type {Map>} */ const map = new Map(); for (const module of set) { - for (const sourceType of module.getSourceTypes()) { + const sourceTypes = + (sourceTypesByModule && sourceTypesByModule.get(module)) || + module.getSourceTypes(); + for (const sourceType of sourceTypes) { let innerSet = map.get(sourceType); if (innerSet === undefined) { innerSet = new SortableSet(); @@ -110,6 +113,7 @@ const modulesBySourceType = set => { } return map; }; +const defaultModulesBySourceType = modulesBySourceType(undefined); /** @type {WeakMap} */ const createOrderedArrayFunctionMap = new WeakMap(); @@ -201,6 +205,8 @@ class ChunkGraphChunk { constructor() { /** @type {SortableSet} */ this.modules = new SortableSet(); + /** @type {WeakMap> | undefined} */ + this.sourceTypesByModule = undefined; /** @type {Map} */ this.entryModules = new Map(); /** @type {SortableSet} */ @@ -213,6 +219,8 @@ class ChunkGraphChunk { this.runtimeRequirements = undefined; /** @type {Set} */ this.runtimeRequirementsInTree = new Set(); + + this._modulesBySourceType = defaultModulesBySourceType; } } @@ -315,6 +323,8 @@ class ChunkGraph { const cgm = this._getChunkGraphModule(module); const cgc = this._getChunkGraphChunk(chunk); cgc.modules.delete(module); + // No need to invalidate cgc._modulesBySourceType because we modified cgc.modules anyway + if (cgc.sourceTypesByModule) cgc.sourceTypesByModule.delete(module); cgm.chunks.delete(chunk); } @@ -568,11 +578,84 @@ class ChunkGraph { getChunkModulesIterableBySourceType(chunk, sourceType) { const cgc = this._getChunkGraphChunk(chunk); const modulesWithSourceType = cgc.modules - .getFromUnorderedCache(modulesBySourceType) + .getFromUnorderedCache(cgc._modulesBySourceType) .get(sourceType); return modulesWithSourceType; } + /** + * @param {Chunk} chunk chunk + * @param {Module} module chunk module + * @param {Set} sourceTypes source types + */ + setChunkModuleSourceTypes(chunk, module, sourceTypes) { + const cgc = this._getChunkGraphChunk(chunk); + if (cgc.sourceTypesByModule === undefined) { + cgc.sourceTypesByModule = new WeakMap(); + } + cgc.sourceTypesByModule.set(module, sourceTypes); + // Update cgc._modulesBySourceType to invalidate the cache + cgc._modulesBySourceType = modulesBySourceType(cgc.sourceTypesByModule); + } + + /** + * @param {Chunk} chunk chunk + * @param {Module} module chunk module + * @returns {Set} source types + */ + getChunkModuleSourceTypes(chunk, module) { + const cgc = this._getChunkGraphChunk(chunk); + if (cgc.sourceTypesByModule === undefined) { + return module.getSourceTypes(); + } + return cgc.sourceTypesByModule.get(module) || module.getSourceTypes(); + } + + /** + * @param {Module} module module + * @returns {Set} source types + */ + getModuleSourceTypes(module) { + return ( + this._getOverwrittenModuleSourceTypes(module) || module.getSourceTypes() + ); + } + + /** + * @param {Module} module module + * @returns {Set | undefined} source types + */ + _getOverwrittenModuleSourceTypes(module) { + let newSet = false; + let sourceTypes; + for (const chunk of this.getModuleChunksIterable(module)) { + const cgc = this._getChunkGraphChunk(chunk); + if (cgc.sourceTypesByModule === undefined) return; + const st = cgc.sourceTypesByModule.get(module); + if (st === undefined) return; + if (!sourceTypes) { + sourceTypes = st; + continue; + } else if (!newSet) { + for (const type of st) { + if (!newSet) { + if (!sourceTypes.has(type)) { + newSet = true; + sourceTypes = new Set(sourceTypes); + sourceTypes.add(type); + } + } else { + sourceTypes.add(type); + } + } + } else { + for (const type of st) sourceTypes.add(type); + } + } + + return sourceTypes; + } + /** * @param {Chunk} chunk the chunk * @param {function(Module, Module): -1|0|1} comparator comparator function @@ -593,7 +676,7 @@ class ChunkGraph { getOrderedChunkModulesIterableBySourceType(chunk, sourceType, comparator) { const cgc = this._getChunkGraphChunk(chunk); const modulesWithSourceType = cgc.modules - .getFromUnorderedCache(modulesBySourceType) + .getFromUnorderedCache(cgc._modulesBySourceType) .get(sourceType); if (modulesWithSourceType === undefined) return undefined; modulesWithSourceType.sortWith(comparator); @@ -1473,6 +1556,10 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza const graphHash = cgm.graphHashes.provide(runtime, () => { const hash = createHash(this._hashFunction); hash.update(`${cgm.id}${this.moduleGraph.isAsync(module)}`); + const sourceTypes = this._getOverwrittenModuleSourceTypes(module); + if (sourceTypes !== undefined) { + for (const type of sourceTypes) hash.update(type); + } this.moduleGraph.getExportsInfo(module).updateHash(hash, runtime); return BigInt(`0x${/** @type {string} */ (hash.digest("hex"))}`); }); diff --git a/lib/Module.js b/lib/Module.js index 4e0410ff0..aede59455 100644 --- a/lib/Module.js +++ b/lib/Module.js @@ -60,6 +60,7 @@ const makeSerializable = require("./util/makeSerializable"); * @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules * @property {CodeGenerationResults} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that) * @property {Compilation=} compilation the compilation + * @property {ReadonlySet=} sourceTypes source types */ /** diff --git a/lib/NormalModule.js b/lib/NormalModule.js index 5e8dbded4..fdc28f1a6 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -1176,7 +1176,8 @@ class NormalModule extends Module { chunkGraph, runtime, concatenationScope, - codeGenerationResults + codeGenerationResults, + sourceTypes }) { /** @type {Set} */ const runtimeRequirements = new Set(); @@ -1195,7 +1196,7 @@ class NormalModule extends Module { }; const sources = new Map(); - for (const type of this.generator.getTypes(this)) { + for (const type of sourceTypes || chunkGraph.getModuleSourceTypes(this)) { const source = this.error ? new RawSource( "throw new Error(" + JSON.stringify(this.error.message) + ");" diff --git a/lib/asset/AssetGenerator.js b/lib/asset/AssetGenerator.js index 0ee074d12..7b778e964 100644 --- a/lib/asset/AssetGenerator.js +++ b/lib/asset/AssetGenerator.js @@ -8,6 +8,7 @@ const mimeTypes = require("mime-types"); const path = require("path"); const { RawSource } = require("webpack-sources"); +const ConcatenationScope = require("../ConcatenationScope"); const Generator = require("../Generator"); const RuntimeGlobals = require("../RuntimeGlobals"); const createHash = require("../util/createHash"); @@ -23,6 +24,7 @@ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash"); /** @typedef {import("../Generator").GenerateContext} GenerateContext */ /** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */ /** @typedef {import("../Module")} Module */ +/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ /** @typedef {import("../NormalModule")} NormalModule */ /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ /** @typedef {import("../util/Hash")} Hash */ @@ -145,6 +147,15 @@ class AssetGenerator extends Generator { ).replace(/^\.\//, ""); } + /** + * @param {NormalModule} module module for which the bailout reason should be determined + * @param {ConcatenationBailoutReasonContext} context context + * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated + */ + getConcatenationBailoutReason(module, context) { + return undefined; + } + /** * @param {NormalModule} module module * @returns {string} mime type @@ -198,14 +209,21 @@ class AssetGenerator extends Generator { */ generate( module, - { runtime, chunkGraph, runtimeTemplate, runtimeRequirements, type, getData } + { + runtime, + concatenationScope, + chunkGraph, + runtimeTemplate, + runtimeRequirements, + type, + getData + } ) { switch (type) { case "asset": return module.originalSource(); default: { - runtimeRequirements.add(RuntimeGlobals.module); - + let content; const originalSource = module.originalSource(); if (module.buildInfo.dataUrl) { let encodedSource; @@ -255,11 +273,7 @@ class AssetGenerator extends Generator { } const data = getData(); data.set("url", Buffer.from(encodedSource)); - return new RawSource( - `${RuntimeGlobals.module}.exports = ${JSON.stringify( - encodedSource - )};` - ); + content = JSON.stringify(encodedSource); } else { const assetModuleFilename = this.filename || runtimeTemplate.outputOptions.assetModuleFilename; @@ -343,9 +357,22 @@ class AssetGenerator extends Generator { data.set("filename", filename); data.set("assetInfo", assetInfo); } + content = assetPath; + } + if (concatenationScope) { + concatenationScope.registerNamespaceExport( + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + ); return new RawSource( - `${RuntimeGlobals.module}.exports = ${assetPath};` + `${runtimeTemplate.supportsConst() ? "const" : "var"} ${ + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + } = ${content};` + ); + } else { + runtimeRequirements.add(RuntimeGlobals.module); + return new RawSource( + `${RuntimeGlobals.module}.exports = ${content};` ); } } diff --git a/lib/asset/AssetParser.js b/lib/asset/AssetParser.js index 7a0a4e307..3848715f2 100644 --- a/lib/asset/AssetParser.js +++ b/lib/asset/AssetParser.js @@ -31,6 +31,7 @@ class AssetParser extends Parser { } state.module.buildInfo.strict = true; state.module.buildMeta.exportsType = "default"; + state.module.buildMeta.defaultObject = false; if (typeof this.dataUrlCondition === "function") { state.module.buildInfo.dataUrl = this.dataUrlCondition(source, { diff --git a/lib/asset/AssetSourceGenerator.js b/lib/asset/AssetSourceGenerator.js index f8720a21b..6c0e51e98 100644 --- a/lib/asset/AssetSourceGenerator.js +++ b/lib/asset/AssetSourceGenerator.js @@ -6,11 +6,13 @@ "use strict"; const { RawSource } = require("webpack-sources"); +const ConcatenationScope = require("../ConcatenationScope"); const Generator = require("../Generator"); const RuntimeGlobals = require("../RuntimeGlobals"); /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("../Generator").GenerateContext} GenerateContext */ +/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ /** @typedef {import("../NormalModule")} NormalModule */ const TYPES = new Set(["javascript"]); @@ -21,9 +23,10 @@ class AssetSourceGenerator extends Generator { * @param {GenerateContext} generateContext context for generate * @returns {Source} generated code */ - generate(module, { chunkGraph, runtimeTemplate, runtimeRequirements }) { - runtimeRequirements.add(RuntimeGlobals.module); - + generate( + module, + { concatenationScope, chunkGraph, runtimeTemplate, runtimeRequirements } + ) { const originalSource = module.originalSource(); if (!originalSource) { @@ -38,9 +41,31 @@ class AssetSourceGenerator extends Generator { } else { encodedSource = content.toString("utf-8"); } - return new RawSource( - `${RuntimeGlobals.module}.exports = ${JSON.stringify(encodedSource)};` - ); + + let sourceContent; + if (concatenationScope) { + concatenationScope.registerNamespaceExport( + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + ); + sourceContent = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${ + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + } = ${JSON.stringify(encodedSource)};`; + } else { + runtimeRequirements.add(RuntimeGlobals.module); + sourceContent = `${RuntimeGlobals.module}.exports = ${JSON.stringify( + encodedSource + )};`; + } + return new RawSource(sourceContent); + } + + /** + * @param {NormalModule} module module for which the bailout reason should be determined + * @param {ConcatenationBailoutReasonContext} context context + * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated + */ + getConcatenationBailoutReason(module, context) { + return undefined; } /** diff --git a/lib/asset/AssetSourceParser.js b/lib/asset/AssetSourceParser.js index 505c363e7..11f778c25 100644 --- a/lib/asset/AssetSourceParser.js +++ b/lib/asset/AssetSourceParser.js @@ -23,6 +23,7 @@ class AssetSourceParser extends Parser { const { module } = state; module.buildInfo.strict = true; module.buildMeta.exportsType = "default"; + state.module.buildMeta.defaultObject = false; return state; } diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js index cfe6c1ca4..fd88ecaea 100644 --- a/lib/optimize/ConcatenatedModule.js +++ b/lib/optimize/ConcatenatedModule.js @@ -1669,7 +1669,8 @@ ${defineGetters}` chunkGraph, runtime, concatenationScope, - codeGenerationResults + codeGenerationResults, + sourceTypes: TYPES }); const source = codeGenResult.sources.get("javascript"); const data = codeGenResult.data; diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index 62175a64f..68b9404a7 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -425,7 +425,21 @@ class ModuleConcatenationPlugin { for (const chunk of chunkGraph.getModuleChunksIterable( rootModule )) { - chunkGraph.disconnectChunkAndModule(chunk, m); + const sourceTypes = chunkGraph.getChunkModuleSourceTypes( + chunk, + m + ); + if (sourceTypes.size === 1) { + chunkGraph.disconnectChunkAndModule(chunk, m); + } else { + const newSourceTypes = new Set(sourceTypes); + newSourceTypes.delete("javascript"); + chunkGraph.setChunkModuleSourceTypes( + chunk, + m, + newSourceTypes + ); + } } } } diff --git a/test/__snapshots__/StatsTestCases.basictest.js.snap b/test/__snapshots__/StatsTestCases.basictest.js.snap index 11b699e32..c7bb869e6 100644 --- a/test/__snapshots__/StatsTestCases.basictest.js.snap +++ b/test/__snapshots__/StatsTestCases.basictest.js.snap @@ -152,25 +152,41 @@ webpack/runtime/make namespace object 274 bytes {main} [code generated] [no exports] [used exports unknown] -1970-04-20 12:42:42: webpack x.x.x compiled successfully in X ms (d0d97703a88fdf5418be)" +1970-04-20 12:42:42: webpack x.x.x compiled successfully in X ms (64df70d049be415e3e5e)" `; exports[`StatsTestCases should print correct stats for asset 1`] = ` "asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main) -asset bundle.js 13.1 KiB [emitted] (name: main) +asset bundle.js 13.4 KiB [emitted] (name: main) asset static/file.html 12 bytes [emitted] [from: static/file.html] (auxiliary name: main) runtime modules 1.06 KiB 2 modules -asset modules 9.07 KiB (javascript) 14.6 KiB (asset) - modules by path ./ 8.9 KiB (javascript) 14.6 KiB (asset) +modules by path ./ 9.36 KiB (javascript) 14.6 KiB (asset) + modules by path ./images/ 8.86 KiB (javascript) 14.6 KiB (asset) ./images/file.png 42 bytes (javascript) 14.6 KiB (asset) [built] [code generated] ./images/file.svg 915 bytes [built] [code generated] ./images/file.jpg 7.92 KiB [built] [code generated] - ./static/file.html 42 bytes (javascript) 12 bytes (asset) [built] [code generated] - modules by mime type text/plain 172 bytes - data:text/plain;base64,szsaAAdsadasdfaf.. 72.2 bytes [built] [code generated] - data:text/plain,asd= 41.4 bytes [built] [code generated] - data:text/plain,XXXXXXXXXXXXXXX.. 58.8 bytes [built] [code generated] -./index.js 339 bytes [built] [code generated] + modules by path ./*.js 427 bytes + ./index.js 402 bytes [built] [code generated] + ./a.source.js 25 bytes [built] [code generated] + ./static/file.html 42 bytes (javascript) 12 bytes (asset) [built] [code generated] + ./a.css 41.4 bytes [built] [code generated] +modules by mime type text/plain 172 bytes + data:text/plain;base64,szsaAAdsadasdfaf.. 72.2 bytes [built] [code generated] + data:text/plain,asd= 41.4 bytes [built] [code generated] + data:text/plain,XXXXXXXXXXXXXXX.. 58.8 bytes [built] [code generated] +webpack x.x.x compiled successfully in X ms" +`; + +exports[`StatsTestCases should print correct stats for asset-concat 1`] = ` +"asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main) +asset bundle.js 11.7 KiB [emitted] (name: main) +asset static/file.html 12 bytes [emitted] [from: static/file.html] (auxiliary name: main) +orphan modules 9.05 KiB [orphan] 7 modules +runtime modules 1.06 KiB 2 modules +cacheable modules 9.6 KiB (javascript) 14.6 KiB (asset) + ./index.js + 9 modules 9.52 KiB [built] [code generated] + ./images/file.png 42 bytes (javascript) 14.6 KiB (asset) [built] [code generated] + ./static/file.html 42 bytes (javascript) 12 bytes (asset) [built] [code generated] webpack x.x.x compiled successfully in X ms" `; @@ -2565,26 +2581,26 @@ LOG from webpack.FileSystemInfo exports[`StatsTestCases should print correct stats for real-content-hash 1`] = ` "a-normal: - assets by path *.js 3.23 KiB - asset 9690d063d027560c1900-9690d0.js 2.75 KiB [emitted] [immutable] [minimized] (name: runtime) - asset a6d438a0676f93383d79-a6d438.js 262 bytes [emitted] [immutable] [minimized] (name: lazy) - asset cbb9c74e42f00ada40f7-cbb9c7.js 212 bytes [emitted] [immutable] [minimized] (name: index) + assets by path *.js 3.2 KiB + asset e9785128a82e17f93bc4-e97851.js 2.75 KiB [emitted] [immutable] [minimized] (name: runtime) + asset f96e917feecf51c4fc5c-f96e91.js 232 bytes [emitted] [immutable] [minimized] (name: lazy) + asset f17033ffbf027f2d71b7-f17033.js 212 bytes [emitted] [immutable] [minimized] (name: index) asset 666f2b8847021ccc7608-666f2b.js 21 bytes [emitted] [immutable] [minimized] (name: a, b) assets by chunk 20.4 KiB (auxiliary name: lazy) asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: file.png] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg?query 5.89 KiB [cached] [immutable] [from: file.jpg?query] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg 5.89 KiB [emitted] [immutable] [from: file.jpg] (auxiliary name: index) - Entrypoint index 2.96 KiB (5.89 KiB) = 9690d063d027560c1900-9690d0.js 2.75 KiB cbb9c74e42f00ada40f7-cbb9c7.js 212 bytes 1 auxiliary asset + Entrypoint index 2.96 KiB (5.89 KiB) = e9785128a82e17f93bc4-e97851.js 2.75 KiB f17033ffbf027f2d71b7-f17033.js 212 bytes 1 auxiliary asset Entrypoint a 21 bytes = 666f2b8847021ccc7608-666f2b.js Entrypoint b 21 bytes = 666f2b8847021ccc7608-666f2b.js runtime modules 7.28 KiB 9 modules orphan modules 23 bytes [orphan] 1 module - cacheable modules 514 bytes (javascript) 26.3 KiB (asset) - javascript modules 388 bytes + cacheable modules 556 bytes (javascript) 26.3 KiB (asset) + javascript modules 430 bytes ./a/index.js 150 bytes [built] [code generated] ./a/a.js 22 bytes [built] [code generated] ./a/b.js 66 bytes [built] [code generated] - ./a/lazy.js + 1 modules 150 bytes [built] [code generated] + ./a/lazy.js + 2 modules 192 bytes [built] [code generated] asset modules 126 bytes (javascript) 26.3 KiB (asset) ./a/file.jpg 42 bytes (javascript) 5.89 KiB (asset) [built] [code generated] ./a/file.png 42 bytes (javascript) 14.6 KiB (asset) [built] [code generated] @@ -2592,26 +2608,26 @@ exports[`StatsTestCases should print correct stats for real-content-hash 1`] = ` a-normal (webpack x.x.x) compiled successfully in X ms b-normal: - assets by path *.js 3.23 KiB - asset 1eb63f19f5ec7a706311-1eb63f.js 2.75 KiB [emitted] [immutable] [minimized] (name: runtime) - asset a6d438a0676f93383d79-a6d438.js 262 bytes [emitted] [immutable] [minimized] (name: lazy) - asset cbb9c74e42f00ada40f7-cbb9c7.js 212 bytes [emitted] [immutable] [minimized] (name: index) + assets by path *.js 3.2 KiB + asset 165a2ea225896183fda9-165a2e.js 2.75 KiB [emitted] [immutable] [minimized] (name: runtime) + asset f96e917feecf51c4fc5c-f96e91.js 232 bytes [emitted] [immutable] [minimized] (name: lazy) + asset f17033ffbf027f2d71b7-f17033.js 212 bytes [emitted] [immutable] [minimized] (name: index) asset 666f2b8847021ccc7608-666f2b.js 21 bytes [emitted] [immutable] [minimized] (name: a, b) assets by chunk 20.4 KiB (auxiliary name: lazy) asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: file.png] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg?query 5.89 KiB [cached] [immutable] [from: file.jpg?query] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg 5.89 KiB [emitted] [immutable] [from: file.jpg] (auxiliary name: index) - Entrypoint index 2.96 KiB (5.89 KiB) = 1eb63f19f5ec7a706311-1eb63f.js 2.75 KiB cbb9c74e42f00ada40f7-cbb9c7.js 212 bytes 1 auxiliary asset + Entrypoint index 2.96 KiB (5.89 KiB) = 165a2ea225896183fda9-165a2e.js 2.75 KiB f17033ffbf027f2d71b7-f17033.js 212 bytes 1 auxiliary asset Entrypoint a 21 bytes = 666f2b8847021ccc7608-666f2b.js Entrypoint b 21 bytes = 666f2b8847021ccc7608-666f2b.js runtime modules 7.28 KiB 9 modules orphan modules 19 bytes [orphan] 1 module - cacheable modules 469 bytes (javascript) 26.3 KiB (asset) - javascript modules 343 bytes + cacheable modules 511 bytes (javascript) 26.3 KiB (asset) + javascript modules 385 bytes ./b/index.js 109 bytes [built] [code generated] ./b/a.js 22 bytes [built] [code generated] ./b/b.js 66 bytes [built] [code generated] - ./b/lazy.js + 1 modules 146 bytes [built] [code generated] + ./b/lazy.js + 2 modules 188 bytes [built] [code generated] asset modules 126 bytes (javascript) 26.3 KiB (asset) ./b/file.jpg 42 bytes (javascript) 5.89 KiB (asset) [built] [code generated] ./b/file.png 42 bytes (javascript) 14.6 KiB (asset) [built] [code generated] @@ -2619,30 +2635,30 @@ b-normal: b-normal (webpack x.x.x) compiled successfully in X ms a-source-map: - assets by path *.js 3.45 KiB - asset 3c4c8b6907eb902d46e3-3c4c8b.js 2.8 KiB [emitted] [immutable] [minimized] (name: runtime) - sourceMap 3c4c8b6907eb902d46e3-3c4c8b.js.map 14.5 KiB [emitted] [dev] (auxiliary name: runtime) - asset da6ceedb86c86e79a49a-da6cee.js 318 bytes [emitted] [immutable] [minimized] (name: lazy) - sourceMap da6ceedb86c86e79a49a-da6cee.js.map 401 bytes [emitted] [dev] (auxiliary name: lazy) - asset 9e0ae6ff74fb2c3c821b-9e0ae6.js 268 bytes [emitted] [immutable] [minimized] (name: index) - sourceMap 9e0ae6ff74fb2c3c821b-9e0ae6.js.map 366 bytes [emitted] [dev] (auxiliary name: index) + assets by path *.js 3.42 KiB + asset 1289a35df2e6455ef167-1289a3.js 2.8 KiB [emitted] [immutable] [minimized] (name: runtime) + sourceMap 1289a35df2e6455ef167-1289a3.js.map 14.5 KiB [emitted] [dev] (auxiliary name: runtime) + asset 0a8aef384737d9f64f44-0a8aef.js 288 bytes [emitted] [immutable] [minimized] (name: lazy) + sourceMap 0a8aef384737d9f64f44-0a8aef.js.map 409 bytes [emitted] [dev] (auxiliary name: lazy) + asset da629d4acf5998c06668-da629d.js 268 bytes [emitted] [immutable] [minimized] (name: index) + sourceMap da629d4acf5998c06668-da629d.js.map 366 bytes [emitted] [dev] (auxiliary name: index) asset 222c2acc68675174e6b2-222c2a.js 77 bytes [emitted] [immutable] [minimized] (name: a, b) sourceMap 222c2acc68675174e6b2-222c2a.js.map 254 bytes [emitted] [dev] (auxiliary name: a, b) assets by chunk 20.4 KiB (auxiliary name: lazy) asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: file.png] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg?query 5.89 KiB [cached] [immutable] [from: file.jpg?query] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg 5.89 KiB [emitted] [immutable] [from: file.jpg] (auxiliary name: index) - Entrypoint index 3.06 KiB (20.7 KiB) = 3c4c8b6907eb902d46e3-3c4c8b.js 2.8 KiB 9e0ae6ff74fb2c3c821b-9e0ae6.js 268 bytes 3 auxiliary assets + Entrypoint index 3.06 KiB (20.7 KiB) = 1289a35df2e6455ef167-1289a3.js 2.8 KiB da629d4acf5998c06668-da629d.js 268 bytes 3 auxiliary assets Entrypoint a 77 bytes (254 bytes) = 222c2acc68675174e6b2-222c2a.js 1 auxiliary asset Entrypoint b 77 bytes (254 bytes) = 222c2acc68675174e6b2-222c2a.js 1 auxiliary asset runtime modules 7.28 KiB 9 modules orphan modules 23 bytes [orphan] 1 module - cacheable modules 514 bytes (javascript) 26.3 KiB (asset) - javascript modules 388 bytes + cacheable modules 556 bytes (javascript) 26.3 KiB (asset) + javascript modules 430 bytes ./a/index.js 150 bytes [built] [code generated] ./a/a.js 22 bytes [built] [code generated] ./a/b.js 66 bytes [built] [code generated] - ./a/lazy.js + 1 modules 150 bytes [built] [code generated] + ./a/lazy.js + 2 modules 192 bytes [built] [code generated] asset modules 126 bytes (javascript) 26.3 KiB (asset) ./a/file.jpg 42 bytes (javascript) 5.89 KiB (asset) [built] [code generated] ./a/file.png 42 bytes (javascript) 14.6 KiB (asset) [built] [code generated] @@ -2650,30 +2666,30 @@ a-source-map: a-source-map (webpack x.x.x) compiled successfully in X ms b-source-map: - assets by path *.js 3.45 KiB - asset 3c4c8b6907eb902d46e3-3c4c8b.js 2.8 KiB [emitted] [immutable] [minimized] (name: runtime) - sourceMap 3c4c8b6907eb902d46e3-3c4c8b.js.map 14.5 KiB [emitted] [dev] (auxiliary name: runtime) - asset da6ceedb86c86e79a49a-da6cee.js 318 bytes [emitted] [immutable] [minimized] (name: lazy) - sourceMap da6ceedb86c86e79a49a-da6cee.js.map 397 bytes [emitted] [dev] (auxiliary name: lazy) - asset 9e0ae6ff74fb2c3c821b-9e0ae6.js 268 bytes [emitted] [immutable] [minimized] (name: index) - sourceMap 9e0ae6ff74fb2c3c821b-9e0ae6.js.map 323 bytes [emitted] [dev] (auxiliary name: index) + assets by path *.js 3.42 KiB + asset 1289a35df2e6455ef167-1289a3.js 2.8 KiB [emitted] [immutable] [minimized] (name: runtime) + sourceMap 1289a35df2e6455ef167-1289a3.js.map 14.5 KiB [emitted] [dev] (auxiliary name: runtime) + asset 0a8aef384737d9f64f44-0a8aef.js 288 bytes [emitted] [immutable] [minimized] (name: lazy) + sourceMap 0a8aef384737d9f64f44-0a8aef.js.map 405 bytes [emitted] [dev] (auxiliary name: lazy) + asset da629d4acf5998c06668-da629d.js 268 bytes [emitted] [immutable] [minimized] (name: index) + sourceMap da629d4acf5998c06668-da629d.js.map 323 bytes [emitted] [dev] (auxiliary name: index) asset 222c2acc68675174e6b2-222c2a.js 77 bytes [emitted] [immutable] [minimized] (name: a, b) sourceMap 222c2acc68675174e6b2-222c2a.js.map 254 bytes [emitted] [dev] (auxiliary name: a, b) assets by chunk 20.4 KiB (auxiliary name: lazy) asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: file.png] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg?query 5.89 KiB [cached] [immutable] [from: file.jpg?query] (auxiliary name: lazy) asset 7382fad5b015914e0811.jpg 5.89 KiB [emitted] [immutable] [from: file.jpg] (auxiliary name: index) - Entrypoint index 3.06 KiB (20.7 KiB) = 3c4c8b6907eb902d46e3-3c4c8b.js 2.8 KiB 9e0ae6ff74fb2c3c821b-9e0ae6.js 268 bytes 3 auxiliary assets + Entrypoint index 3.06 KiB (20.7 KiB) = 1289a35df2e6455ef167-1289a3.js 2.8 KiB da629d4acf5998c06668-da629d.js 268 bytes 3 auxiliary assets Entrypoint a 77 bytes (254 bytes) = 222c2acc68675174e6b2-222c2a.js 1 auxiliary asset Entrypoint b 77 bytes (254 bytes) = 222c2acc68675174e6b2-222c2a.js 1 auxiliary asset runtime modules 7.28 KiB 9 modules orphan modules 19 bytes [orphan] 1 module - cacheable modules 469 bytes (javascript) 26.3 KiB (asset) - javascript modules 343 bytes + cacheable modules 511 bytes (javascript) 26.3 KiB (asset) + javascript modules 385 bytes ./b/index.js 109 bytes [built] [code generated] ./b/a.js 22 bytes [built] [code generated] ./b/b.js 66 bytes [built] [code generated] - ./b/lazy.js + 1 modules 146 bytes [built] [code generated] + ./b/lazy.js + 2 modules 188 bytes [built] [code generated] asset modules 126 bytes (javascript) 26.3 KiB (asset) ./b/file.jpg 42 bytes (javascript) 5.89 KiB (asset) [built] [code generated] ./b/file.png 42 bytes (javascript) 14.6 KiB (asset) [built] [code generated] diff --git a/test/statsCases/asset-concat/a.css b/test/statsCases/asset-concat/a.css new file mode 100644 index 000000000..3b16b0a1e --- /dev/null +++ b/test/statsCases/asset-concat/a.css @@ -0,0 +1 @@ +a{} diff --git a/test/statsCases/asset-concat/a.source.js b/test/statsCases/asset-concat/a.source.js new file mode 100644 index 000000000..55ba8379a --- /dev/null +++ b/test/statsCases/asset-concat/a.source.js @@ -0,0 +1 @@ +const b = 1; diff --git a/test/statsCases/asset-concat/images/file.jpg b/test/statsCases/asset-concat/images/file.jpg new file mode 100644 index 000000000..fe5c6eefa Binary files /dev/null and b/test/statsCases/asset-concat/images/file.jpg differ diff --git a/test/statsCases/asset-concat/images/file.png b/test/statsCases/asset-concat/images/file.png new file mode 100644 index 000000000..fb53b9ded Binary files /dev/null and b/test/statsCases/asset-concat/images/file.png differ diff --git a/test/statsCases/asset-concat/images/file.svg b/test/statsCases/asset-concat/images/file.svg new file mode 100644 index 000000000..d7b7e40b4 --- /dev/null +++ b/test/statsCases/asset-concat/images/file.svg @@ -0,0 +1 @@ +icon-square-small diff --git a/test/statsCases/asset-concat/index.js b/test/statsCases/asset-concat/index.js new file mode 100644 index 000000000..d1500102e --- /dev/null +++ b/test/statsCases/asset-concat/index.js @@ -0,0 +1,9 @@ +import png from "./images/file.png"; +import svg from "./images/file.svg"; +import jpg from "./images/file.jpg"; +import html from "./static/file.html"; +import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd==" +import text2 from "data:text/plain,asd=" +import text3 from "data:text/plain,XXXXXXXXXXXXXXXXX" // 17 chars +import css from "./a.css"; +import source from "./a.source"; diff --git a/test/statsCases/asset-concat/static/file.html b/test/statsCases/asset-concat/static/file.html new file mode 100644 index 000000000..7c89b545c --- /dev/null +++ b/test/statsCases/asset-concat/static/file.html @@ -0,0 +1 @@ +
diff --git a/test/statsCases/asset-concat/webpack.config.js b/test/statsCases/asset-concat/webpack.config.js new file mode 100644 index 000000000..67951bc27 --- /dev/null +++ b/test/statsCases/asset-concat/webpack.config.js @@ -0,0 +1,35 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + mode: "production", + entry: "./index.js", + module: { + rules: [ + { + test: /\.(png|jpg|svg)$/, + type: "asset" + }, + { + test: /\.html$/, + type: "asset/resource", + generator: { + filename: "static/[name][ext]" + } + }, + { + test: /\.css$/, + type: "asset/inline" + }, + { + test: /\.source\.js$/, + type: "asset/source" + }, + { + mimetype: "text/plain", + type: "asset" + } + ] + }, + output: { + filename: "bundle.js" + } +}; diff --git a/test/statsCases/asset/a.css b/test/statsCases/asset/a.css new file mode 100644 index 000000000..3b16b0a1e --- /dev/null +++ b/test/statsCases/asset/a.css @@ -0,0 +1 @@ +a{} diff --git a/test/statsCases/asset/a.source.js b/test/statsCases/asset/a.source.js new file mode 100644 index 000000000..55ba8379a --- /dev/null +++ b/test/statsCases/asset/a.source.js @@ -0,0 +1 @@ +const b = 1; diff --git a/test/statsCases/asset/index.js b/test/statsCases/asset/index.js index 85b8ea92e..467ff94c5 100644 --- a/test/statsCases/asset/index.js +++ b/test/statsCases/asset/index.js @@ -2,6 +2,8 @@ import png from "./images/file.png"; import svg from "./images/file.svg"; import jpg from "./images/file.jpg"; import html from "./static/file.html"; -import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd==" -import text2 from "data:text/plain,asd=" -import text3 from "data:text/plain,XXXXXXXXXXXXXXXXX" // 17 chars +import text1 from "data:text/plain;base64,szsaAAdsadasdfafasfasAADas123aasdasd=="; +import text2 from "data:text/plain,asd="; +import text3 from "data:text/plain,XXXXXXXXXXXXXXXXX"; // 17 chars +import css from "./a.css"; +import source from "./a.source"; diff --git a/test/statsCases/asset/webpack.config.js b/test/statsCases/asset/webpack.config.js index ad7722fca..6f5d1756e 100644 --- a/test/statsCases/asset/webpack.config.js +++ b/test/statsCases/asset/webpack.config.js @@ -15,12 +15,23 @@ module.exports = { filename: "static/[name][ext]" } }, + { + test: /\.css$/, + type: "asset/inline" + }, + { + test: /\.source\.js$/, + type: "asset/source" + }, { mimetype: "text/plain", type: "asset" } ] }, + optimization: { + concatenateModules: false + }, output: { filename: "bundle.js" } diff --git a/test/watchCases/cache/asset-concat/0/images/file.jpg b/test/watchCases/cache/asset-concat/0/images/file.jpg new file mode 100644 index 000000000..fe5c6eefa Binary files /dev/null and b/test/watchCases/cache/asset-concat/0/images/file.jpg differ diff --git a/test/watchCases/cache/asset-concat/0/images/file.png b/test/watchCases/cache/asset-concat/0/images/file.png new file mode 100644 index 000000000..fb53b9ded Binary files /dev/null and b/test/watchCases/cache/asset-concat/0/images/file.png differ diff --git a/test/watchCases/cache/asset-concat/0/images/file.svg b/test/watchCases/cache/asset-concat/0/images/file.svg new file mode 100644 index 000000000..d7b7e40b4 --- /dev/null +++ b/test/watchCases/cache/asset-concat/0/images/file.svg @@ -0,0 +1 @@ +icon-square-small diff --git a/test/watchCases/cache/asset-concat/0/index.js b/test/watchCases/cache/asset-concat/0/index.js new file mode 100644 index 000000000..e753a8de9 --- /dev/null +++ b/test/watchCases/cache/asset-concat/0/index.js @@ -0,0 +1,9 @@ +import png from "./images/file.png"; +import svg from "./images/file.svg"; +import jpg from "./images/file.jpg"; + +it("should generate assets correctly", () => { + expect(png).toMatch(/^data:image\/png;base64,/); + expect(svg).toMatch(/^data:image\/svg\+xml;base64,/); + expect(jpg).toMatch(/\.jpg$/); +}); diff --git a/test/watchCases/cache/asset-concat/1/index.js b/test/watchCases/cache/asset-concat/1/index.js new file mode 100644 index 000000000..afa409e38 --- /dev/null +++ b/test/watchCases/cache/asset-concat/1/index.js @@ -0,0 +1,9 @@ +it("should generate assets correctly", () => { + const png = require("./images/file.png"); + const svg = require("./images/file.svg"); + const jpg = require("./images/file.jpg"); + + expect(png).toMatch(/^data:image\/png;base64,/); + expect(svg).toMatch(/^data:image\/svg\+xml;base64,/); + expect(jpg).toMatch(/\.jpg$/); +}); diff --git a/test/watchCases/cache/asset-concat/test.filter.js b/test/watchCases/cache/asset-concat/test.filter.js new file mode 100644 index 000000000..87860f28c --- /dev/null +++ b/test/watchCases/cache/asset-concat/test.filter.js @@ -0,0 +1,3 @@ +module.exports = function (config) { + return !(config.experiments && config.experiments.cacheUnaffected); +}; diff --git a/test/watchCases/cache/asset-concat/webpack.config.js b/test/watchCases/cache/asset-concat/webpack.config.js new file mode 100644 index 000000000..b2a5d4c00 --- /dev/null +++ b/test/watchCases/cache/asset-concat/webpack.config.js @@ -0,0 +1,26 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + cache: { + type: "memory" + }, + module: { + rules: [ + { + test: /\.png$/, + type: "asset/inline" + }, + { + test: /\.jpg$/, + type: "asset/resource" + }, + { + test: /\.svg$/, + type: "asset" + } + ] + }, + optimization: { + concatenateModules: true + } +}; diff --git a/types.d.ts b/types.d.ts index a250c3c47..6949db3f8 100644 --- a/types.d.ts +++ b/types.d.ts @@ -817,6 +817,13 @@ declare class ChunkGraph { chunk: Chunk, sourceType: string ): undefined | Iterable; + setChunkModuleSourceTypes( + chunk: Chunk, + module: Module, + sourceTypes: Set + ): void; + getChunkModuleSourceTypes(chunk: Chunk, module: Module): Set; + getModuleSourceTypes(module: Module): Set; getOrderedChunkModulesIterable( chunk: Chunk, comparator: (arg0: Module, arg1: Module) => 0 | 1 | -1 @@ -1252,6 +1259,11 @@ declare interface CodeGenerationContext { * the compilation */ compilation?: Compilation; + + /** + * source types + */ + sourceTypes?: ReadonlySet; } declare interface CodeGenerationResult { /**