From 6e09a51954aee1c8db904747e0b9bc42d14e7b47 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Fri, 2 Oct 2020 15:04:21 +0200 Subject: [PATCH] fix: better support for webpack 5 (#595) --- README.md | 8 +- src/CssLoadingRuntimeModule.js | 192 +++ src/CssModule.js | 25 +- src/index.js | 342 +++--- src/loader.js | 11 +- .../expected/webpack-5/common.js | 8 +- .../dependOn/expected/webpack-5/common.js | 8 +- test/cases/hmr/expected/webpack-5/main.js | 1069 ++++++++++++++++- test/cases/hmr/webpack.config.js | 35 +- test/enforce-esm.test.js | 12 +- test/manual/index.html | 11 +- test/manual/src/index.js | 23 +- test/manual/src/lazy.module.css | 3 + test/manual/webpack.config.js | 4 +- 14 files changed, 1552 insertions(+), 199 deletions(-) create mode 100644 src/CssLoadingRuntimeModule.js create mode 100644 test/manual/src/lazy.module.css diff --git a/README.md b/README.md index 825554ab..52ba3ae4 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ module.exports = { // you can specify a publicPath here // by default it uses publicPath in webpackOptions.output publicPath: '../', - hmr: process.env.NODE_ENV === 'development', + hmr: process.env.NODE_ENV === 'development', // webpack 4 only }, }, 'css-loader', @@ -379,7 +379,7 @@ module.exports = { { loader: MiniCssExtractPlugin.loader, options: { - hmr: process.env.NODE_ENV === 'development', + hmr: process.env.NODE_ENV === 'development', // webpack 4 only }, }, 'css-loader', @@ -394,6 +394,8 @@ module.exports = { ### Hot Module Reloading (HMR) +Note: HMR is automatically supported in webpack 5. No need to configure it. Skip the following: + The `mini-css-extract-plugin` supports hot reloading of actual css files in development. Some options are provided to enable HMR of both standard stylesheets and locally scoped CSS or CSS modules. Below is an example configuration of mini-css for HMR use with CSS modules. @@ -424,7 +426,7 @@ module.exports = { { loader: MiniCssExtractPlugin.loader, options: { - // only enable hot in development + // only enable hot in development (webpack 4 only) hmr: process.env.NODE_ENV === 'development', // if hmr does not work, this is a forceful method. reloadAll: true, diff --git a/src/CssLoadingRuntimeModule.js b/src/CssLoadingRuntimeModule.js new file mode 100644 index 00000000..e3b7d991 --- /dev/null +++ b/src/CssLoadingRuntimeModule.js @@ -0,0 +1,192 @@ +import { RuntimeGlobals, RuntimeModule, Template, util } from 'webpack'; + +import { MODULE_TYPE } from './utils'; + +const { + comparators: { compareModulesByIdentifier }, +} = util; + +const getCssChunkObject = (mainChunk, compilation) => { + const obj = {}; + const { chunkGraph } = compilation; + + for (const chunk of mainChunk.getAllAsyncChunks()) { + const modules = chunkGraph.getOrderedChunkModulesIterable( + chunk, + compareModulesByIdentifier + ); + for (const module of modules) { + if (module.type === MODULE_TYPE) { + obj[chunk.id] = 1; + break; + } + } + } + + return obj; +}; + +module.exports = class CssLoadingRuntimeModule extends RuntimeModule { + constructor(runtimeRequirements) { + super('css loading', 10); + this.runtimeRequirements = runtimeRequirements; + } + + generate() { + const { chunk, compilation, runtimeRequirements } = this; + const { + runtimeTemplate, + outputOptions: { crossOriginLoading }, + } = compilation; + const chunkMap = getCssChunkObject(chunk, compilation); + + const withLoading = + runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) && + Object.keys(chunkMap).length > 0; + const withHmr = runtimeRequirements.has( + RuntimeGlobals.hmrDownloadUpdateHandlers + ); + + if (!withLoading && !withHmr) return null; + + return Template.asString([ + `var createStylesheet = ${runtimeTemplate.basicFunction( + 'fullhref, resolve, reject', + [ + 'var linkTag = document.createElement("link");', + 'linkTag.rel = "stylesheet";', + 'linkTag.type = "text/css";', + 'linkTag.onload = resolve;', + 'linkTag.onerror = function(event) {', + Template.indent([ + 'var request = event && event.target && event.target.src || fullhref;', + 'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + request + ")");', + 'err.code = "CSS_CHUNK_LOAD_FAILED";', + 'err.request = request;', + 'linkTag.parentNode.removeChild(linkTag)', + 'reject(err);', + ]), + '};', + 'linkTag.href = fullhref;', + crossOriginLoading + ? Template.asString([ + `if (linkTag.href.indexOf(window.location.origin + '/') !== 0) {`, + Template.indent( + `linkTag.crossOrigin = ${JSON.stringify(crossOriginLoading)};` + ), + '}', + ]) + : '', + 'var head = document.getElementsByTagName("head")[0];', + 'head.appendChild(linkTag);', + 'return linkTag;', + ] + )};`, + `var findStylesheet = ${runtimeTemplate.basicFunction('href, fullhref', [ + 'var existingLinkTags = document.getElementsByTagName("link");', + 'for(var i = 0; i < existingLinkTags.length; i++) {', + Template.indent([ + 'var tag = existingLinkTags[i];', + 'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");', + 'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag;', + ]), + '}', + 'var existingStyleTags = document.getElementsByTagName("style");', + 'for(var i = 0; i < existingStyleTags.length; i++) {', + Template.indent([ + 'var tag = existingStyleTags[i];', + 'var dataHref = tag.getAttribute("data-href");', + 'if(dataHref === href || dataHref === fullhref) return tag;', + ]), + '}', + ])};`, + `var loadStylesheet = ${runtimeTemplate.basicFunction( + 'chunkId', + `return new Promise(${runtimeTemplate.basicFunction('resolve, reject', [ + `var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`, + `var fullhref = ${RuntimeGlobals.publicPath} + href;`, + 'if(findStylesheet(href, fullhref)) return resolve();', + 'createStylesheet(fullhref, resolve, reject);', + ])});` + )}`, + withLoading + ? Template.asString([ + '// object to store loaded CSS chunks', + 'var installedCssChunks = {', + Template.indent( + chunk.ids.map((id) => `${JSON.stringify(id)}: 0`).join(',\n') + ), + '};', + '', + `${ + RuntimeGlobals.ensureChunkHandlers + }.miniCss = ${runtimeTemplate.basicFunction('chunkId, promises', [ + `var cssChunks = ${JSON.stringify(chunkMap)};`, + 'if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);', + 'else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {', + Template.indent([ + `promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(${runtimeTemplate.basicFunction( + '', + 'installedCssChunks[chunkId] = 0;' + )}, ${runtimeTemplate.basicFunction('e', [ + 'delete installedCssChunks[chunkId];', + 'throw e;', + ])}));`, + ]), + '}', + ])};`, + ]) + : '// no chunk loading', + '', + withHmr + ? Template.asString([ + 'var oldTags = [];', + 'var newTags = [];', + `var applyHandler = ${runtimeTemplate.basicFunction('options', [ + `return { dispose: ${runtimeTemplate.basicFunction('', [ + 'for(var i = 0; i < oldTags.length; i++) {', + Template.indent([ + 'var oldTag = oldTags[i];', + 'if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);', + ]), + '}', + 'oldTags.length = 0;', + ])}, apply: ${runtimeTemplate.basicFunction('', [ + 'for(var i = 0; i < newTags.length; i++) newTags[i].rel = "stylesheet";', + 'newTags.length = 0;', + ])} };`, + ])}`, + `${ + RuntimeGlobals.hmrDownloadUpdateHandlers + }.miniCss = ${runtimeTemplate.basicFunction( + 'chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList', + [ + 'applyHandlers.push(applyHandler);', + `chunkIds.forEach(${runtimeTemplate.basicFunction('chunkId', [ + `var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`, + `var fullhref = ${RuntimeGlobals.publicPath} + href;`, + 'const oldTag = findStylesheet(href, fullhref);', + 'if(!oldTag) return;', + `promises.push(new Promise(${runtimeTemplate.basicFunction( + 'resolve, reject', + [ + `var tag = createStylesheet(fullhref, ${runtimeTemplate.basicFunction( + '', + [ + 'tag.as = "style";', + 'tag.rel = "preload";', + 'resolve();', + ] + )}, reject);`, + 'oldTags.push(oldTag);', + 'newTags.push(tag);', + ] + )}));`, + ])});`, + ] + )}`, + ]) + : '// no hmr', + ]); + } +}; diff --git a/src/CssModule.js b/src/CssModule.js index 80839d62..3bdac2d9 100644 --- a/src/CssModule.js +++ b/src/CssModule.js @@ -2,6 +2,12 @@ import webpack from 'webpack'; import { MODULE_TYPE } from './utils'; +const TYPES = new Set([MODULE_TYPE]); +const CODE_GENERATION_RESULT = { + sources: new Map(), + runtimeRequirements: new Set(), +}; + class CssModule extends webpack.Module { constructor({ context, @@ -20,9 +26,11 @@ class CssModule extends webpack.Module { this.content = content; this.media = media; this.sourceMap = sourceMap; + this.buildInfo = {}; + this.buildMeta = {}; } - // no source() so webpack doesn't do add stuff to the bundle + // no source() so webpack 4 doesn't do add stuff to the bundle size() { return this.content.length; @@ -38,6 +46,16 @@ class CssModule extends webpack.Module { }`; } + // eslint-disable-next-line class-methods-use-this + getSourceTypes() { + return TYPES; + } + + // eslint-disable-next-line class-methods-use-this + codeGeneration() { + return CODE_GENERATION_RESULT; + } + nameForCondition() { const resource = this._identifier.split('!').pop(); const idx = resource.indexOf('?'); @@ -60,6 +78,11 @@ class CssModule extends webpack.Module { return true; } + // eslint-disable-next-line class-methods-use-this + needBuild(context, callback) { + callback(null, false); + } + build(options, compilation, resolver, fileSystem, callback) { this.buildInfo = {}; this.buildMeta = {}; diff --git a/src/index.js b/src/index.js index 9a2cbc68..7713cdcc 100644 --- a/src/index.js +++ b/src/index.js @@ -57,9 +57,24 @@ class MiniCssExtractPlugin { ); } } + + if (!isWebpack4 && 'hmr' in this.options) { + throw new Error( + "The 'hmr' option doesn't exist for the mini-css-extract-plugin when using webpack 5 (it's automatically determined)" + ); + } } + /** @param {import("webpack").Compiler} compiler */ apply(compiler) { + if (!isWebpack4) { + const { splitChunks } = compiler.options.optimization; + if (splitChunks) { + if (splitChunks.defaultSizeTypes.includes('...')) { + splitChunks.defaultSizeTypes.push(MODULE_TYPE); + } + } + } compiler.hooks.thisCompilation.tap(pluginName, (compilation) => { compilation.dependencyFactories.set( CssDependency, @@ -145,17 +160,17 @@ class MiniCssExtractPlugin { (result, { chunk }) => { const { chunkGraph } = compilation; + // We don't need hot update chunks for css + // We will use the real asset instead to update + if (chunk instanceof webpack.HotUpdateChunk) return; + const renderedModules = Array.from( this.getChunkModules(chunk, chunkGraph) ).filter((module) => module.type === MODULE_TYPE); - const filenameTemplate = - chunk.filenameTemplate || - chunk.hasRuntime() || - chunk.isOnlyInitial() - ? ({ chunk: chunkData }) => - this.options.moduleFilename(chunkData) - : this.options.chunkFilename; + const filenameTemplate = chunk.canBeInitial() + ? ({ chunk: chunkData }) => this.options.moduleFilename(chunkData) + : this.options.chunkFilename; if (renderedModules.length > 0) { result.push({ @@ -228,169 +243,194 @@ class MiniCssExtractPlugin { const { mainTemplate } = compilation; - mainTemplate.hooks.localVars.tap(pluginName, (source, chunk) => { - const chunkMap = this.getCssChunkObject(chunk, compilation); - - if (Object.keys(chunkMap).length > 0) { - return Template.asString([ - source, - '', - '// object to store loaded CSS chunks', - 'var installedCssChunks = {', - Template.indent( - chunk.ids.map((id) => `${JSON.stringify(id)}: 0`).join(',\n') - ), - '};', - ]); - } - - return source; - }); - - mainTemplate.hooks.requireEnsure.tap( - pluginName, - (source, chunk, hash) => { + if (isWebpack4) { + mainTemplate.hooks.localVars.tap(pluginName, (source, chunk) => { const chunkMap = this.getCssChunkObject(chunk, compilation); if (Object.keys(chunkMap).length > 0) { - const maintemplateObject = isWebpack4 ? mainTemplate : compilation; - const chunkMaps = chunk.getChunkMaps(); - const { crossOriginLoading } = maintemplateObject.outputOptions; - const linkHrefPath = maintemplateObject.getAssetPath( - JSON.stringify(this.options.chunkFilename), - { - hash: isWebpack4 - ? `" + ${mainTemplate.renderCurrentHashCode(hash)} + "` - : `" + ${webpack.RuntimeGlobals.getFullHash} + "`, - hashWithLength: (length) => - isWebpack4 - ? `" + ${mainTemplate.renderCurrentHashCode( - hash, - length - )} + "` - : `" + ${webpack.RuntimeGlobals.getFullHash} + "`, - chunk: { - id: '" + chunkId + "', - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength(length) { - const shortChunkHashMap = Object.create(null); - - for (const chunkId of Object.keys(chunkMaps.hash)) { - if (typeof chunkMaps.hash[chunkId] === 'string') { - shortChunkHashMap[chunkId] = chunkMaps.hash[ - chunkId - ].substring(0, length); - } - } + return Template.asString([ + source, + '', + '// object to store loaded CSS chunks', + 'var installedCssChunks = {', + Template.indent( + chunk.ids.map((id) => `${JSON.stringify(id)}: 0`).join(',\n') + ), + '};', + ]); + } - return `" + ${JSON.stringify( - shortChunkHashMap - )}[chunkId] + "`; - }, - contentHash: { - [MODULE_TYPE]: `" + ${JSON.stringify( - chunkMaps.contentHash[MODULE_TYPE] - )}[chunkId] + "`, - }, - contentHashWithLength: { - [MODULE_TYPE]: (length) => { - const shortContentHashMap = {}; - const contentHash = chunkMaps.contentHash[MODULE_TYPE]; - - for (const chunkId of Object.keys(contentHash)) { - if (typeof contentHash[chunkId] === 'string') { - shortContentHashMap[chunkId] = contentHash[ + return source; + }); + + mainTemplate.hooks.requireEnsure.tap( + pluginName, + (source, chunk, hash) => { + const chunkMap = this.getCssChunkObject(chunk, compilation); + + if (Object.keys(chunkMap).length > 0) { + const chunkMaps = chunk.getChunkMaps(); + const { crossOriginLoading } = mainTemplate.outputOptions; + const linkHrefPath = mainTemplate.getAssetPath( + JSON.stringify(this.options.chunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: (length) => + `" + ${mainTemplate.renderCurrentHashCode( + hash, + length + )} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength(length) { + const shortChunkHashMap = Object.create(null); + + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === 'string') { + shortChunkHashMap[chunkId] = chunkMaps.hash[ chunkId ].substring(0, length); } } return `" + ${JSON.stringify( - shortContentHashMap + shortChunkHashMap )}[chunkId] + "`; }, + contentHash: { + [MODULE_TYPE]: `" + ${JSON.stringify( + chunkMaps.contentHash[MODULE_TYPE] + )}[chunkId] + "`, + }, + contentHashWithLength: { + [MODULE_TYPE]: (length) => { + const shortContentHashMap = {}; + const contentHash = chunkMaps.contentHash[MODULE_TYPE]; + + for (const chunkId of Object.keys(contentHash)) { + if (typeof contentHash[chunkId] === 'string') { + shortContentHashMap[chunkId] = contentHash[ + chunkId + ].substring(0, length); + } + } + + return `" + ${JSON.stringify( + shortContentHashMap + )}[chunkId] + "`; + }, + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "`, }, - name: `" + (${JSON.stringify( - chunkMaps.name - )}[chunkId]||chunkId) + "`, - }, - contentHashType: MODULE_TYPE, - } - ); + contentHashType: MODULE_TYPE, + } + ); - return Template.asString([ - source, - '', - `// ${pluginName} CSS loading`, - `var cssChunks = ${JSON.stringify(chunkMap)};`, - 'if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);', - 'else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {', - Template.indent([ - 'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {', + return Template.asString([ + source, + '', + `// ${pluginName} CSS loading`, + `var cssChunks = ${JSON.stringify(chunkMap)};`, + 'if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);', + 'else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {', Template.indent([ - `var href = ${linkHrefPath};`, - `var fullhref = ${ - isWebpack4 - ? mainTemplate.requireFn - : webpack.RuntimeGlobals.require - }.p + href;`, - 'var existingLinkTags = document.getElementsByTagName("link");', - 'for(var i = 0; i < existingLinkTags.length; i++) {', - Template.indent([ - 'var tag = existingLinkTags[i];', - 'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");', - 'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return resolve();', - ]), - '}', - 'var existingStyleTags = document.getElementsByTagName("style");', - 'for(var i = 0; i < existingStyleTags.length; i++) {', - Template.indent([ - 'var tag = existingStyleTags[i];', - 'var dataHref = tag.getAttribute("data-href");', - 'if(dataHref === href || dataHref === fullhref) return resolve();', - ]), - '}', - 'var linkTag = document.createElement("link");', - 'linkTag.rel = "stylesheet";', - 'linkTag.type = "text/css";', - 'linkTag.onload = resolve;', - 'linkTag.onerror = function(event) {', + 'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {', Template.indent([ - 'var request = event && event.target && event.target.src || fullhref;', - 'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + request + ")");', - 'err.code = "CSS_CHUNK_LOAD_FAILED";', - 'err.request = request;', - 'delete installedCssChunks[chunkId]', - 'linkTag.parentNode.removeChild(linkTag)', - 'reject(err);', + `var href = ${linkHrefPath};`, + `var fullhref = ${mainTemplate.requireFn}.p + href;`, + 'var existingLinkTags = document.getElementsByTagName("link");', + 'for(var i = 0; i < existingLinkTags.length; i++) {', + Template.indent([ + 'var tag = existingLinkTags[i];', + 'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");', + 'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return resolve();', + ]), + '}', + 'var existingStyleTags = document.getElementsByTagName("style");', + 'for(var i = 0; i < existingStyleTags.length; i++) {', + Template.indent([ + 'var tag = existingStyleTags[i];', + 'var dataHref = tag.getAttribute("data-href");', + 'if(dataHref === href || dataHref === fullhref) return resolve();', + ]), + '}', + 'var linkTag = document.createElement("link");', + 'linkTag.rel = "stylesheet";', + 'linkTag.type = "text/css";', + 'linkTag.onload = resolve;', + 'linkTag.onerror = function(event) {', + Template.indent([ + 'var request = event && event.target && event.target.src || fullhref;', + 'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + request + ")");', + 'err.code = "CSS_CHUNK_LOAD_FAILED";', + 'err.request = request;', + 'delete installedCssChunks[chunkId]', + 'linkTag.parentNode.removeChild(linkTag)', + 'reject(err);', + ]), + '};', + 'linkTag.href = fullhref;', + crossOriginLoading + ? Template.asString([ + `if (linkTag.href.indexOf(window.location.origin + '/') !== 0) {`, + Template.indent( + `linkTag.crossOrigin = ${JSON.stringify( + crossOriginLoading + )};` + ), + '}', + ]) + : '', + 'var head = document.getElementsByTagName("head")[0];', + 'head.appendChild(linkTag);', ]), - '};', - 'linkTag.href = fullhref;', - crossOriginLoading - ? Template.asString([ - `if (linkTag.href.indexOf(window.location.origin + '/') !== 0) {`, - Template.indent( - `linkTag.crossOrigin = ${JSON.stringify( - crossOriginLoading - )};` - ), - '}', - ]) - : '', - 'var head = document.getElementsByTagName("head")[0];', - 'head.appendChild(linkTag);', + '}).then(function() {', + Template.indent(['installedCssChunks[chunkId] = 0;']), + '}));', ]), - '}).then(function() {', - Template.indent(['installedCssChunks[chunkId] = 0;']), - '}));', - ]), - '}', - ]); - } + '}', + ]); + } - return source; - } - ); + return source; + } + ); + } else { + const enabledChunks = new WeakSet(); + const handler = (chunk, set) => { + if (enabledChunks.has(chunk)) return; + enabledChunks.add(chunk); + + // eslint-disable-next-line global-require + const CssLoadingRuntimeModule = require('./CssLoadingRuntimeModule'); + + set.add(webpack.RuntimeGlobals.publicPath); + compilation.addRuntimeModule( + chunk, + new webpack.runtime.GetChunkFilenameRuntimeModule( + MODULE_TYPE, + 'mini-css', + `${webpack.RuntimeGlobals.require}.miniCssF`, + (referencedChunk) => + referencedChunk.canBeInitial() + ? ({ chunk: chunkData }) => + this.options.moduleFilename(chunkData) + : this.options.chunkFilename, + true + ) + ); + compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set)); + }; + compilation.hooks.runtimeRequirementInTree + .for(webpack.RuntimeGlobals.ensureChunkHandlers) + .tap(pluginName, handler); + compilation.hooks.runtimeRequirementInTree + .for(webpack.RuntimeGlobals.hmrDownloadUpdateHandlers) + .tap(pluginName, handler); + } }); } diff --git a/src/loader.js b/src/loader.js index ff9e7f84..d1a4c373 100644 --- a/src/loader.js +++ b/src/loader.js @@ -192,11 +192,10 @@ export function pitch(request) { : originalExports; if (namedExport) { - locals = ''; - Object.keys(originalExports).forEach((key) => { if (key !== 'default') { - locals += `\nexport const ${key} = "${originalExports[key]}";`; + if (!locals) locals = {}; + locals[key] = originalExports[key]; } }); } else { @@ -228,7 +227,11 @@ export function pitch(request) { const result = locals ? namedExport - ? locals + ? Object.keys(locals) + .map( + (key) => `\nexport const ${key} = ${JSON.stringify(locals[key])};` + ) + .join('') : `\n${ esModule ? 'export default' : 'module.exports =' } ${JSON.stringify(locals)};` diff --git a/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js b/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js index 589cd38f..3e43d6d5 100644 --- a/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js +++ b/test/cases/dependOn-multiple-files-per-entry/expected/webpack-5/common.js @@ -103,13 +103,7 @@ __webpack_require__.r(__webpack_exports__); /******/ }; /******/ })(); /******/ -/******/ /* webpack/runtime/compat */ -/******/ -/******/ -/******/ // object to store loaded CSS chunks -/******/ var installedCssChunks = { -/******/ 0: 0 -/******/ };/* webpack/runtime/jsonp chunk loading */ +/******/ /* webpack/runtime/jsonp chunk loading */ /******/ (() => { /******/ // no baseURI /******/ diff --git a/test/cases/dependOn/expected/webpack-5/common.js b/test/cases/dependOn/expected/webpack-5/common.js index a1926b90..0b8c0134 100644 --- a/test/cases/dependOn/expected/webpack-5/common.js +++ b/test/cases/dependOn/expected/webpack-5/common.js @@ -86,13 +86,7 @@ __webpack_require__.r(__webpack_exports__); /******/ }; /******/ })(); /******/ -/******/ /* webpack/runtime/compat */ -/******/ -/******/ -/******/ // object to store loaded CSS chunks -/******/ var installedCssChunks = { -/******/ 0: 0 -/******/ };/* webpack/runtime/jsonp chunk loading */ +/******/ /* webpack/runtime/jsonp chunk loading */ /******/ (() => { /******/ // no baseURI /******/ diff --git a/test/cases/hmr/expected/webpack-5/main.js b/test/cases/hmr/expected/webpack-5/main.js index d45ee120..48dad557 100644 --- a/test/cases/hmr/expected/webpack-5/main.js +++ b/test/cases/hmr/expected/webpack-5/main.js @@ -1,4 +1,13 @@ /******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ([ +/* 0 */ +/***/ (() => { + +// extracted by mini-css-extract-plugin + +/***/ }) +/******/ ]); +/************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ @@ -16,16 +25,1066 @@ /******/ }; /******/ /******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ }; +/******/ __webpack_require__.i.forEach(function(handler) { handler(execOptions); }); +/******/ module = execOptions.module; +/******/ execOptions.factory.call(module.exports, module, module.exports, execOptions.require); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = __webpack_module_cache__; +/******/ +/******/ // expose the module execution interceptor +/******/ __webpack_require__.i = []; +/******/ /************************************************************************/ -/******/ /************************************************************************/ -// extracted by mini-css-extract-plugin - if(false) { var cssReload; } - +/******/ /* webpack/runtime/get javascript update chunk filename */ +/******/ (() => { +/******/ // This function allow to reference all chunks +/******/ __webpack_require__.hu = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return "" + chunkId + "." + __webpack_require__.h() + ".hot-update.js"; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get mini-css chunk filename */ +/******/ (() => { +/******/ // This function allow to reference all chunks +/******/ __webpack_require__.miniCssF = (chunkId) => { +/******/ // return url for filenames not based on template +/******/ if (chunkId === 0) return "main.css"; +/******/ // return url for filenames based on template +/******/ return undefined; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get update manifest filename */ +/******/ (() => { +/******/ __webpack_require__.hmrF = () => "" + __webpack_require__.h() + ".hot-update.json"; +/******/ })(); +/******/ +/******/ /* webpack/runtime/getFullHash */ +/******/ (() => { +/******/ __webpack_require__.h = () => "56250388fc166692d434" +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) +/******/ })(); +/******/ +/******/ /* webpack/runtime/load script */ +/******/ (() => { +/******/ var inProgress = {}; +/******/ // data-webpack is not used as build has no uniqueName +/******/ // loadScript function to load a script via script tag +/******/ __webpack_require__.l = (url, done, key) => { +/******/ if(inProgress[url]) { inProgress[url].push(done); return; } +/******/ var script, needAttach; +/******/ if(key !== undefined) { +/******/ var scripts = document.getElementsByTagName("script"); +/******/ for(var i = 0; i < scripts.length; i++) { +/******/ var s = scripts[i]; +/******/ if(s.getAttribute("src") == url) { script = s; break; } +/******/ } +/******/ } +/******/ if(!script) { +/******/ needAttach = true; +/******/ script = document.createElement('script'); +/******/ +/******/ script.charset = 'utf-8'; +/******/ script.timeout = 120; +/******/ if (__webpack_require__.nc) { +/******/ script.setAttribute("nonce", __webpack_require__.nc); +/******/ } +/******/ +/******/ script.src = url; +/******/ } +/******/ inProgress[url] = [done]; +/******/ var onScriptComplete = (prev, event) => { +/******/ // avoid mem leaks in IE. +/******/ script.onerror = script.onload = null; +/******/ clearTimeout(timeout); +/******/ var doneFns = inProgress[url]; +/******/ delete inProgress[url]; +/******/ script.parentNode && script.parentNode.removeChild(script); +/******/ doneFns && doneFns.forEach((fn) => fn(event)); +/******/ if(prev) return prev(event); +/******/ } +/******/ ; +/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); +/******/ script.onerror = onScriptComplete.bind(null, script.onerror); +/******/ script.onload = onScriptComplete.bind(null, script.onload); +/******/ needAttach && document.head.appendChild(script); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hot module replacement */ +/******/ (() => { +/******/ var currentModuleData = {}; +/******/ var installedModules = __webpack_require__.c; +/******/ +/******/ // module and require creation +/******/ var currentChildModule; +/******/ var currentParents = []; +/******/ +/******/ // status +/******/ var registeredStatusHandlers = []; +/******/ var currentStatus = "idle"; +/******/ +/******/ // while downloading +/******/ var blockingPromises; +/******/ +/******/ // The update info +/******/ var currentUpdateApplyHandlers; +/******/ var queuedInvalidatedModules; +/******/ +/******/ __webpack_require__.hmrD = currentModuleData; +/******/ +/******/ __webpack_require__.i.push(function (options) { +/******/ var module = options.module; +/******/ var require = createRequire(options.require, options.id); +/******/ module.hot = createModuleHotObject(options.id, module); +/******/ module.parents = currentParents; +/******/ module.children = []; +/******/ currentParents = []; +/******/ options.require = require; +/******/ }); +/******/ +/******/ __webpack_require__.hmrC = {}; +/******/ __webpack_require__.hmrI = {}; +/******/ +/******/ function createRequire(require, moduleId) { +/******/ var me = installedModules[moduleId]; +/******/ if (!me) return require; +/******/ var fn = function (request) { +/******/ if (me.hot.active) { +/******/ if (installedModules[request]) { +/******/ var parents = installedModules[request].parents; +/******/ if (parents.indexOf(moduleId) === -1) { +/******/ parents.push(moduleId); +/******/ } +/******/ } else { +/******/ currentParents = [moduleId]; +/******/ currentChildModule = request; +/******/ } +/******/ if (me.children.indexOf(request) === -1) { +/******/ me.children.push(request); +/******/ } +/******/ } else { +/******/ console.warn( +/******/ "[HMR] unexpected require(" + +/******/ request + +/******/ ") from disposed module " + +/******/ moduleId +/******/ ); +/******/ currentParents = []; +/******/ } +/******/ return require(request); +/******/ }; +/******/ var createPropertyDescriptor = function (name) { +/******/ return { +/******/ configurable: true, +/******/ enumerable: true, +/******/ get: function () { +/******/ return require[name]; +/******/ }, +/******/ set: function (value) { +/******/ require[name] = value; +/******/ } +/******/ }; +/******/ }; +/******/ for (var name in require) { +/******/ if (Object.prototype.hasOwnProperty.call(require, name) && name !== "e") { +/******/ Object.defineProperty(fn, name, createPropertyDescriptor(name)); +/******/ } +/******/ } +/******/ fn.e = function (chunkId) { +/******/ return trackBlockingPromise(require.e(chunkId)); +/******/ }; +/******/ return fn; +/******/ } +/******/ +/******/ function createModuleHotObject(moduleId, me) { +/******/ var hot = { +/******/ // private stuff +/******/ _acceptedDependencies: {}, +/******/ _declinedDependencies: {}, +/******/ _selfAccepted: false, +/******/ _selfDeclined: false, +/******/ _selfInvalidated: false, +/******/ _disposeHandlers: [], +/******/ _main: currentChildModule !== moduleId, +/******/ _requireSelf: function () { +/******/ currentParents = me.parents.slice(); +/******/ currentChildModule = moduleId; +/******/ __webpack_require__(moduleId); +/******/ }, +/******/ +/******/ // Module API +/******/ active: true, +/******/ accept: function (dep, callback) { +/******/ if (dep === undefined) hot._selfAccepted = true; +/******/ else if (typeof dep === "function") hot._selfAccepted = dep; +/******/ else if (typeof dep === "object" && dep !== null) +/******/ for (var i = 0; i < dep.length; i++) +/******/ hot._acceptedDependencies[dep[i]] = callback || function () {}; +/******/ else hot._acceptedDependencies[dep] = callback || function () {}; +/******/ }, +/******/ decline: function (dep) { +/******/ if (dep === undefined) hot._selfDeclined = true; +/******/ else if (typeof dep === "object" && dep !== null) +/******/ for (var i = 0; i < dep.length; i++) +/******/ hot._declinedDependencies[dep[i]] = true; +/******/ else hot._declinedDependencies[dep] = true; +/******/ }, +/******/ dispose: function (callback) { +/******/ hot._disposeHandlers.push(callback); +/******/ }, +/******/ addDisposeHandler: function (callback) { +/******/ hot._disposeHandlers.push(callback); +/******/ }, +/******/ removeDisposeHandler: function (callback) { +/******/ var idx = hot._disposeHandlers.indexOf(callback); +/******/ if (idx >= 0) hot._disposeHandlers.splice(idx, 1); +/******/ }, +/******/ invalidate: function () { +/******/ this._selfInvalidated = true; +/******/ switch (currentStatus) { +/******/ case "idle": +/******/ currentUpdateApplyHandlers = []; +/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) { +/******/ __webpack_require__.hmrI[key]( +/******/ moduleId, +/******/ currentUpdateApplyHandlers +/******/ ); +/******/ }); +/******/ setStatus("ready"); +/******/ break; +/******/ case "ready": +/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) { +/******/ __webpack_require__.hmrI[key]( +/******/ moduleId, +/******/ currentUpdateApplyHandlers +/******/ ); +/******/ }); +/******/ break; +/******/ case "prepare": +/******/ case "check": +/******/ case "dispose": +/******/ case "apply": +/******/ (queuedInvalidatedModules = queuedInvalidatedModules || []).push( +/******/ moduleId +/******/ ); +/******/ break; +/******/ default: +/******/ // ignore requests in error states +/******/ break; +/******/ } +/******/ }, +/******/ +/******/ // Management API +/******/ check: hotCheck, +/******/ apply: hotApply, +/******/ status: function (l) { +/******/ if (!l) return currentStatus; +/******/ registeredStatusHandlers.push(l); +/******/ }, +/******/ addStatusHandler: function (l) { +/******/ registeredStatusHandlers.push(l); +/******/ }, +/******/ removeStatusHandler: function (l) { +/******/ var idx = registeredStatusHandlers.indexOf(l); +/******/ if (idx >= 0) registeredStatusHandlers.splice(idx, 1); +/******/ }, +/******/ +/******/ //inherit from previous dispose call +/******/ data: currentModuleData[moduleId] +/******/ }; +/******/ currentChildModule = undefined; +/******/ return hot; +/******/ } +/******/ +/******/ function setStatus(newStatus) { +/******/ currentStatus = newStatus; +/******/ for (var i = 0; i < registeredStatusHandlers.length; i++) +/******/ registeredStatusHandlers[i].call(null, newStatus); +/******/ } +/******/ +/******/ function trackBlockingPromise(promise) { +/******/ switch (currentStatus) { +/******/ case "ready": +/******/ setStatus("prepare"); +/******/ blockingPromises.push(promise); +/******/ waitForBlockingPromises(function () { +/******/ setStatus("ready"); +/******/ }); +/******/ return promise; +/******/ case "prepare": +/******/ blockingPromises.push(promise); +/******/ return promise; +/******/ default: +/******/ return promise; +/******/ } +/******/ } +/******/ +/******/ function waitForBlockingPromises(fn) { +/******/ if (blockingPromises.length === 0) return fn(); +/******/ var blocker = blockingPromises; +/******/ blockingPromises = []; +/******/ return Promise.all(blocker).then(function () { +/******/ return waitForBlockingPromises(fn); +/******/ }); +/******/ } +/******/ +/******/ function hotCheck(applyOnUpdate) { +/******/ if (currentStatus !== "idle") { +/******/ throw new Error("check() is only allowed in idle status"); +/******/ } +/******/ setStatus("check"); +/******/ return __webpack_require__.hmrM().then(function (update) { +/******/ if (!update) { +/******/ setStatus(applyInvalidatedModules() ? "ready" : "idle"); +/******/ return null; +/******/ } +/******/ +/******/ setStatus("prepare"); +/******/ +/******/ var updatedModules = []; +/******/ blockingPromises = []; +/******/ currentUpdateApplyHandlers = []; +/******/ +/******/ return Promise.all( +/******/ Object.keys(__webpack_require__.hmrC).reduce(function ( +/******/ promises, +/******/ key +/******/ ) { +/******/ __webpack_require__.hmrC[key]( +/******/ update.c, +/******/ update.r, +/******/ update.m, +/******/ promises, +/******/ currentUpdateApplyHandlers, +/******/ updatedModules +/******/ ); +/******/ return promises; +/******/ }, +/******/ []) +/******/ ).then(function () { +/******/ return waitForBlockingPromises(function () { +/******/ if (applyOnUpdate) { +/******/ return internalApply(applyOnUpdate); +/******/ } else { +/******/ setStatus("ready"); +/******/ +/******/ return updatedModules; +/******/ } +/******/ }); +/******/ }); +/******/ }); +/******/ } +/******/ +/******/ function hotApply(options) { +/******/ if (currentStatus !== "ready") { +/******/ return Promise.resolve().then(function () { +/******/ throw new Error("apply() is only allowed in ready status"); +/******/ }); +/******/ } +/******/ return internalApply(options); +/******/ } +/******/ +/******/ function internalApply(options) { +/******/ options = options || {}; +/******/ +/******/ applyInvalidatedModules(); +/******/ +/******/ var results = currentUpdateApplyHandlers.map(function (handler) { +/******/ return handler(options); +/******/ }); +/******/ currentUpdateApplyHandlers = undefined; +/******/ +/******/ var errors = results +/******/ .map(function (r) { +/******/ return r.error; +/******/ }) +/******/ .filter(Boolean); +/******/ +/******/ if (errors.length > 0) { +/******/ setStatus("abort"); +/******/ return Promise.resolve().then(function () { +/******/ throw errors[0]; +/******/ }); +/******/ } +/******/ +/******/ // Now in "dispose" phase +/******/ setStatus("dispose"); +/******/ +/******/ results.forEach(function (result) { +/******/ if (result.dispose) result.dispose(); +/******/ }); +/******/ +/******/ // Now in "apply" phase +/******/ setStatus("apply"); +/******/ +/******/ var error; +/******/ var reportError = function (err) { +/******/ if (!error) error = err; +/******/ }; +/******/ +/******/ var outdatedModules = []; +/******/ results.forEach(function (result) { +/******/ if (result.apply) { +/******/ var modules = result.apply(reportError); +/******/ if (modules) { +/******/ for (var i = 0; i < modules.length; i++) { +/******/ outdatedModules.push(modules[i]); +/******/ } +/******/ } +/******/ } +/******/ }); +/******/ +/******/ // handle errors in accept handlers and self accepted module load +/******/ if (error) { +/******/ setStatus("fail"); +/******/ return Promise.resolve().then(function () { +/******/ throw error; +/******/ }); +/******/ } +/******/ +/******/ if (queuedInvalidatedModules) { +/******/ return internalApply(options).then(function (list) { +/******/ outdatedModules.forEach(function (moduleId) { +/******/ if (list.indexOf(moduleId) < 0) list.push(moduleId); +/******/ }); +/******/ return list; +/******/ }); +/******/ } +/******/ +/******/ setStatus("idle"); +/******/ return Promise.resolve(outdatedModules); +/******/ } +/******/ +/******/ function applyInvalidatedModules() { +/******/ if (queuedInvalidatedModules) { +/******/ if (!currentUpdateApplyHandlers) currentUpdateApplyHandlers = []; +/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) { +/******/ queuedInvalidatedModules.forEach(function (moduleId) { +/******/ __webpack_require__.hmrI[key]( +/******/ moduleId, +/******/ currentUpdateApplyHandlers +/******/ ); +/******/ }); +/******/ }); +/******/ queuedInvalidatedModules = undefined; +/******/ return true; +/******/ } +/******/ } +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + ""; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName("script"); +/******/ if(scripts.length) scriptUrl = scripts[scripts.length - 1].src +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/css loading */ +/******/ (() => { +/******/ var createStylesheet = (fullhref, resolve, reject) => { +/******/ var linkTag = document.createElement("link"); +/******/ linkTag.rel = "stylesheet"; +/******/ linkTag.type = "text/css"; +/******/ linkTag.onload = resolve; +/******/ linkTag.onerror = function(event) { +/******/ var request = event && event.target && event.target.src || fullhref; +/******/ var err = new Error("Loading CSS chunk " + chunkId + " failed.\n(" + request + ")"); +/******/ err.code = "CSS_CHUNK_LOAD_FAILED"; +/******/ err.request = request; +/******/ linkTag.parentNode.removeChild(linkTag) +/******/ reject(err); +/******/ }; +/******/ linkTag.href = fullhref; +/******/ +/******/ var head = document.getElementsByTagName("head")[0]; +/******/ head.appendChild(linkTag); +/******/ return linkTag; +/******/ }; +/******/ var findStylesheet = (href, fullhref) => { +/******/ var existingLinkTags = document.getElementsByTagName("link"); +/******/ for(var i = 0; i < existingLinkTags.length; i++) { +/******/ var tag = existingLinkTags[i]; +/******/ var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href"); +/******/ if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag; +/******/ } +/******/ var existingStyleTags = document.getElementsByTagName("style"); +/******/ for(var i = 0; i < existingStyleTags.length; i++) { +/******/ var tag = existingStyleTags[i]; +/******/ var dataHref = tag.getAttribute("data-href"); +/******/ if(dataHref === href || dataHref === fullhref) return tag; +/******/ } +/******/ }; +/******/ var loadStylesheet = (chunkId) => { +/******/ return new Promise((resolve, reject) => { +/******/ var href = __webpack_require__.miniCssF(chunkId); +/******/ var fullhref = __webpack_require__.p + href; +/******/ if(findStylesheet(href, fullhref)) return resolve(); +/******/ createStylesheet(fullhref, resolve, reject); +/******/ }); +/******/ } +/******/ // no chunk loading +/******/ +/******/ var oldTags = []; +/******/ var newTags = []; +/******/ var applyHandler = (options) => { +/******/ return { dispose: () => { +/******/ for(var i = 0; i < oldTags.length; i++) { +/******/ var oldTag = oldTags[i]; +/******/ if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag); +/******/ } +/******/ oldTags.length = 0; +/******/ }, apply: () => { +/******/ for(var i = 0; i < newTags.length; i++) newTags[i].rel = "stylesheet"; +/******/ newTags.length = 0; +/******/ } }; +/******/ } +/******/ __webpack_require__.hmrC.miniCss = (chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList) => { +/******/ applyHandlers.push(applyHandler); +/******/ chunkIds.forEach((chunkId) => { +/******/ var href = __webpack_require__.miniCssF(chunkId); +/******/ var fullhref = __webpack_require__.p + href; +/******/ const oldTag = findStylesheet(href, fullhref); +/******/ if(!oldTag) return; +/******/ promises.push(new Promise((resolve, reject) => { +/******/ var tag = createStylesheet(fullhref, () => { +/******/ tag.as = "style"; +/******/ tag.rel = "preload"; +/******/ resolve(); +/******/ }, reject); +/******/ oldTags.push(oldTag); +/******/ newTags.push(tag); +/******/ })); +/******/ }); +/******/ } +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ // no baseURI +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // Promise = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ 0: 0 +/******/ }; +/******/ +/******/ +/******/ // no chunk on demand loading +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ var currentUpdatedModulesList; +/******/ var waitingUpdateResolves = {}; +/******/ function loadUpdateChunk(chunkId) { +/******/ return new Promise((resolve, reject) => { +/******/ waitingUpdateResolves[chunkId] = resolve; +/******/ // start update chunk loading +/******/ var url = __webpack_require__.p + __webpack_require__.hu(chunkId); +/******/ // create error before stack unwound to get useful stacktrace later +/******/ var error = new Error(); +/******/ var loadingEnded = (event) => { +/******/ if(waitingUpdateResolves[chunkId]) { +/******/ waitingUpdateResolves[chunkId] = undefined +/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); +/******/ var realSrc = event && event.target && event.target.src; +/******/ error.message = 'Loading hot update chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; +/******/ error.name = 'ChunkLoadError'; +/******/ error.type = errorType; +/******/ error.request = realSrc; +/******/ reject(error); +/******/ } +/******/ }; +/******/ __webpack_require__.l(url, loadingEnded); +/******/ }); +/******/ } +/******/ +/******/ self["webpackHotUpdate"] = (chunkId, moreModules, runtime) => { +/******/ for(var moduleId in moreModules) { +/******/ if(__webpack_require__.o(moreModules, moduleId)) { +/******/ currentUpdate[moduleId] = moreModules[moduleId]; +/******/ if(currentUpdatedModulesList) currentUpdatedModulesList.push(moduleId); +/******/ } +/******/ } +/******/ if(runtime) currentUpdateRuntime.push(runtime); +/******/ if(waitingUpdateResolves[chunkId]) { +/******/ waitingUpdateResolves[chunkId](); +/******/ waitingUpdateResolves[chunkId] = undefined; +/******/ } +/******/ }; +/******/ +/******/ var currentUpdateChunks; +/******/ var currentUpdate; +/******/ var currentUpdateRemovedChunks; +/******/ var currentUpdateRuntime; +/******/ function applyHandler(options) { +/******/ if (__webpack_require__.f) delete __webpack_require__.f.jsonpHmr; +/******/ currentUpdateChunks = undefined; +/******/ function getAffectedModuleEffects(updateModuleId) { +/******/ var outdatedModules = [updateModuleId]; +/******/ var outdatedDependencies = {}; +/******/ +/******/ var queue = outdatedModules.map(function (id) { +/******/ return { +/******/ chain: [id], +/******/ id: id +/******/ }; +/******/ }); +/******/ while (queue.length > 0) { +/******/ var queueItem = queue.pop(); +/******/ var moduleId = queueItem.id; +/******/ var chain = queueItem.chain; +/******/ var module = __webpack_require__.c[moduleId]; +/******/ if ( +/******/ !module || +/******/ (module.hot._selfAccepted && !module.hot._selfInvalidated) +/******/ ) +/******/ continue; +/******/ if (module.hot._selfDeclined) { +/******/ return { +/******/ type: "self-declined", +/******/ chain: chain, +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ if (module.hot._main) { +/******/ return { +/******/ type: "unaccepted", +/******/ chain: chain, +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ for (var i = 0; i < module.parents.length; i++) { +/******/ var parentId = module.parents[i]; +/******/ var parent = __webpack_require__.c[parentId]; +/******/ if (!parent) continue; +/******/ if (parent.hot._declinedDependencies[moduleId]) { +/******/ return { +/******/ type: "declined", +/******/ chain: chain.concat([parentId]), +/******/ moduleId: moduleId, +/******/ parentId: parentId +/******/ }; +/******/ } +/******/ if (outdatedModules.indexOf(parentId) !== -1) continue; +/******/ if (parent.hot._acceptedDependencies[moduleId]) { +/******/ if (!outdatedDependencies[parentId]) +/******/ outdatedDependencies[parentId] = []; +/******/ addAllToSet(outdatedDependencies[parentId], [moduleId]); +/******/ continue; +/******/ } +/******/ delete outdatedDependencies[parentId]; +/******/ outdatedModules.push(parentId); +/******/ queue.push({ +/******/ chain: chain.concat([parentId]), +/******/ id: parentId +/******/ }); +/******/ } +/******/ } +/******/ +/******/ return { +/******/ type: "accepted", +/******/ moduleId: updateModuleId, +/******/ outdatedModules: outdatedModules, +/******/ outdatedDependencies: outdatedDependencies +/******/ }; +/******/ } +/******/ +/******/ function addAllToSet(a, b) { +/******/ for (var i = 0; i < b.length; i++) { +/******/ var item = b[i]; +/******/ if (a.indexOf(item) === -1) a.push(item); +/******/ } +/******/ } +/******/ +/******/ // at begin all updates modules are outdated +/******/ // the "outdated" status can propagate to parents if they don't accept the children +/******/ var outdatedDependencies = {}; +/******/ var outdatedModules = []; +/******/ var appliedUpdate = {}; +/******/ +/******/ var warnUnexpectedRequire = function warnUnexpectedRequire(module) { +/******/ console.warn( +/******/ "[HMR] unexpected require(" + module.id + ") to disposed module" +/******/ ); +/******/ }; +/******/ +/******/ for (var moduleId in currentUpdate) { +/******/ if (__webpack_require__.o(currentUpdate, moduleId)) { +/******/ var newModuleFactory = currentUpdate[moduleId]; +/******/ /** @type {TODO} */ +/******/ var result; +/******/ if (newModuleFactory) { +/******/ result = getAffectedModuleEffects(moduleId); +/******/ } else { +/******/ result = { +/******/ type: "disposed", +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ /** @type {Error|false} */ +/******/ var abortError = false; +/******/ var doApply = false; +/******/ var doDispose = false; +/******/ var chainInfo = ""; +/******/ if (result.chain) { +/******/ chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); +/******/ } +/******/ switch (result.type) { +/******/ case "self-declined": +/******/ if (options.onDeclined) options.onDeclined(result); +/******/ if (!options.ignoreDeclined) +/******/ abortError = new Error( +/******/ "Aborted because of self decline: " + +/******/ result.moduleId + +/******/ chainInfo +/******/ ); +/******/ break; +/******/ case "declined": +/******/ if (options.onDeclined) options.onDeclined(result); +/******/ if (!options.ignoreDeclined) +/******/ abortError = new Error( +/******/ "Aborted because of declined dependency: " + +/******/ result.moduleId + +/******/ " in " + +/******/ result.parentId + +/******/ chainInfo +/******/ ); +/******/ break; +/******/ case "unaccepted": +/******/ if (options.onUnaccepted) options.onUnaccepted(result); +/******/ if (!options.ignoreUnaccepted) +/******/ abortError = new Error( +/******/ "Aborted because " + moduleId + " is not accepted" + chainInfo +/******/ ); +/******/ break; +/******/ case "accepted": +/******/ if (options.onAccepted) options.onAccepted(result); +/******/ doApply = true; +/******/ break; +/******/ case "disposed": +/******/ if (options.onDisposed) options.onDisposed(result); +/******/ doDispose = true; +/******/ break; +/******/ default: +/******/ throw new Error("Unexception type " + result.type); +/******/ } +/******/ if (abortError) { +/******/ return { +/******/ error: abortError +/******/ }; +/******/ } +/******/ if (doApply) { +/******/ appliedUpdate[moduleId] = newModuleFactory; +/******/ addAllToSet(outdatedModules, result.outdatedModules); +/******/ for (moduleId in result.outdatedDependencies) { +/******/ if (__webpack_require__.o(result.outdatedDependencies, moduleId)) { +/******/ if (!outdatedDependencies[moduleId]) +/******/ outdatedDependencies[moduleId] = []; +/******/ addAllToSet( +/******/ outdatedDependencies[moduleId], +/******/ result.outdatedDependencies[moduleId] +/******/ ); +/******/ } +/******/ } +/******/ } +/******/ if (doDispose) { +/******/ addAllToSet(outdatedModules, [result.moduleId]); +/******/ appliedUpdate[moduleId] = warnUnexpectedRequire; +/******/ } +/******/ } +/******/ } +/******/ currentUpdate = undefined; +/******/ +/******/ // Store self accepted outdated modules to require them later by the module system +/******/ var outdatedSelfAcceptedModules = []; +/******/ for (var j = 0; j < outdatedModules.length; j++) { +/******/ var outdatedModuleId = outdatedModules[j]; +/******/ if ( +/******/ __webpack_require__.c[outdatedModuleId] && +/******/ __webpack_require__.c[outdatedModuleId].hot._selfAccepted && +/******/ // removed self-accepted modules should not be required +/******/ appliedUpdate[outdatedModuleId] !== warnUnexpectedRequire && +/******/ // when called invalidate self-accepting is not possible +/******/ !__webpack_require__.c[outdatedModuleId].hot._selfInvalidated +/******/ ) { +/******/ outdatedSelfAcceptedModules.push({ +/******/ module: outdatedModuleId, +/******/ require: __webpack_require__.c[outdatedModuleId].hot._requireSelf, +/******/ errorHandler: __webpack_require__.c[outdatedModuleId].hot._selfAccepted +/******/ }); +/******/ } +/******/ } +/******/ +/******/ var moduleOutdatedDependencies; +/******/ +/******/ return { +/******/ dispose: function () { +/******/ currentUpdateRemovedChunks.forEach(function (chunkId) { +/******/ delete installedChunks[chunkId]; +/******/ }); +/******/ currentUpdateRemovedChunks = undefined; +/******/ +/******/ var idx; +/******/ var queue = outdatedModules.slice(); +/******/ while (queue.length > 0) { +/******/ var moduleId = queue.pop(); +/******/ var module = __webpack_require__.c[moduleId]; +/******/ if (!module) continue; +/******/ +/******/ var data = {}; +/******/ +/******/ // Call dispose handlers +/******/ var disposeHandlers = module.hot._disposeHandlers; +/******/ for (j = 0; j < disposeHandlers.length; j++) { +/******/ disposeHandlers[j].call(null, data); +/******/ } +/******/ __webpack_require__.hmrD[moduleId] = data; +/******/ +/******/ // disable module (this disables requires from this module) +/******/ module.hot.active = false; +/******/ +/******/ // remove module from cache +/******/ delete __webpack_require__.c[moduleId]; +/******/ +/******/ // when disposing there is no need to call dispose handler +/******/ delete outdatedDependencies[moduleId]; +/******/ +/******/ // remove "parents" references from all children +/******/ for (j = 0; j < module.children.length; j++) { +/******/ var child = __webpack_require__.c[module.children[j]]; +/******/ if (!child) continue; +/******/ idx = child.parents.indexOf(moduleId); +/******/ if (idx >= 0) { +/******/ child.parents.splice(idx, 1); +/******/ } +/******/ } +/******/ } +/******/ +/******/ // remove outdated dependency from module children +/******/ var dependency; +/******/ for (var outdatedModuleId in outdatedDependencies) { +/******/ if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) { +/******/ module = __webpack_require__.c[outdatedModuleId]; +/******/ if (module) { +/******/ moduleOutdatedDependencies = +/******/ outdatedDependencies[outdatedModuleId]; +/******/ for (j = 0; j < moduleOutdatedDependencies.length; j++) { +/******/ dependency = moduleOutdatedDependencies[j]; +/******/ idx = module.children.indexOf(dependency); +/******/ if (idx >= 0) module.children.splice(idx, 1); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ }, +/******/ apply: function (reportError) { +/******/ // insert new code +/******/ for (var updateModuleId in appliedUpdate) { +/******/ if (__webpack_require__.o(appliedUpdate, updateModuleId)) { +/******/ __webpack_require__.m[updateModuleId] = appliedUpdate[updateModuleId]; +/******/ } +/******/ } +/******/ +/******/ // run new runtime modules +/******/ for (var i = 0; i < currentUpdateRuntime.length; i++) { +/******/ currentUpdateRuntime[i](__webpack_require__); +/******/ } +/******/ +/******/ // call accept handlers +/******/ for (var outdatedModuleId in outdatedDependencies) { +/******/ if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) { +/******/ var module = __webpack_require__.c[outdatedModuleId]; +/******/ if (module) { +/******/ moduleOutdatedDependencies = +/******/ outdatedDependencies[outdatedModuleId]; +/******/ var callbacks = []; +/******/ var dependenciesForCallbacks = []; +/******/ for (var j = 0; j < moduleOutdatedDependencies.length; j++) { +/******/ var dependency = moduleOutdatedDependencies[j]; +/******/ var acceptCallback = +/******/ module.hot._acceptedDependencies[dependency]; +/******/ if (acceptCallback) { +/******/ if (callbacks.indexOf(acceptCallback) !== -1) continue; +/******/ callbacks.push(acceptCallback); +/******/ dependenciesForCallbacks.push(dependency); +/******/ } +/******/ } +/******/ for (var k = 0; k < callbacks.length; k++) { +/******/ try { +/******/ callbacks[k].call(null, moduleOutdatedDependencies); +/******/ } catch (err) { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "accept-errored", +/******/ moduleId: outdatedModuleId, +/******/ dependencyId: dependenciesForCallbacks[k], +/******/ error: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ // Load self accepted modules +/******/ for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) { +/******/ var item = outdatedSelfAcceptedModules[o]; +/******/ var moduleId = item.module; +/******/ try { +/******/ item.require(moduleId); +/******/ } catch (err) { +/******/ if (typeof item.errorHandler === "function") { +/******/ try { +/******/ item.errorHandler(err); +/******/ } catch (err2) { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "self-accept-error-handler-errored", +/******/ moduleId: moduleId, +/******/ error: err2, +/******/ originalError: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err2); +/******/ } +/******/ reportError(err); +/******/ } +/******/ } else { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "self-accept-errored", +/******/ moduleId: moduleId, +/******/ error: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ return outdatedModules; +/******/ } +/******/ }; +/******/ } +/******/ __webpack_require__.hmrI.jsonp = function (moduleId, applyHandlers) { +/******/ if (!currentUpdate) { +/******/ currentUpdate = {}; +/******/ currentUpdateRuntime = []; +/******/ currentUpdateRemovedChunks = []; +/******/ applyHandlers.push(applyHandler); +/******/ } +/******/ if (!__webpack_require__.o(currentUpdate, moduleId)) { +/******/ currentUpdate[moduleId] = __webpack_require__.m[moduleId]; +/******/ } +/******/ }; +/******/ __webpack_require__.hmrC.jsonp = function ( +/******/ chunkIds, +/******/ removedChunks, +/******/ removedModules, +/******/ promises, +/******/ applyHandlers, +/******/ updatedModulesList +/******/ ) { +/******/ applyHandlers.push(applyHandler); +/******/ currentUpdateChunks = {}; +/******/ currentUpdateRemovedChunks = removedChunks; +/******/ currentUpdate = removedModules.reduce(function (obj, key) { +/******/ obj[key] = false; +/******/ return obj; +/******/ }, {}); +/******/ currentUpdateRuntime = []; +/******/ chunkIds.forEach(function (chunkId) { +/******/ if ( +/******/ __webpack_require__.o(installedChunks, chunkId) && +/******/ installedChunks[chunkId] !== undefined +/******/ ) { +/******/ promises.push(loadUpdateChunk(chunkId, updatedModulesList)); +/******/ currentUpdateChunks[chunkId] = true; +/******/ } +/******/ }); +/******/ if (__webpack_require__.f) { +/******/ __webpack_require__.f.jsonpHmr = function (chunkId, promises) { +/******/ if ( +/******/ currentUpdateChunks && +/******/ !__webpack_require__.o(currentUpdateChunks, chunkId) && +/******/ __webpack_require__.o(installedChunks, chunkId) && +/******/ installedChunks[chunkId] !== undefined +/******/ ) { +/******/ promises.push(loadUpdateChunk(chunkId)); +/******/ currentUpdateChunks[chunkId] = true; +/******/ } +/******/ }; +/******/ } +/******/ }; +/******/ +/******/ __webpack_require__.hmrM = () => { +/******/ if (typeof fetch === "undefined") throw new Error("No browser support: need fetch API"); +/******/ return fetch(__webpack_require__.p + __webpack_require__.hmrF()).then((response) => { +/******/ if(response.status === 404) return; // no update available +/******/ if(!response.ok) throw new Error("Failed to fetch update manifest " + response.statusText); +/******/ return response.json(); +/******/ }); +/******/ }; +/******/ +/******/ // no deferred startup +/******/ +/******/ // no jsonp function +/******/ })(); +/******/ +/************************************************************************/ +/******/ // module cache are used so entry inlining is disabled +/******/ // startup +/******/ // Load entry module +/******/ __webpack_require__(0); /******/ })() ; \ No newline at end of file diff --git a/test/cases/hmr/webpack.config.js b/test/cases/hmr/webpack.config.js index 0bd33f7d..59546433 100644 --- a/test/cases/hmr/webpack.config.js +++ b/test/cases/hmr/webpack.config.js @@ -1,3 +1,5 @@ +import { HotModuleReplacementPlugin, version } from 'webpack'; + import Self from '../../../src'; module.exports = { @@ -7,20 +9,31 @@ module.exports = { { test: /\.css$/, use: [ - { - loader: Self.loader, - options: { - hmr: true, - }, - }, + version.startsWith('4') + ? { + loader: Self.loader, + options: { + hmr: true, + }, + } + : { + loader: Self.loader, + }, 'css-loader', ], }, ], }, - plugins: [ - new Self({ - filename: '[name].css', - }), - ], + plugins: version.startsWith('4') + ? [ + new Self({ + filename: '[name].css', + }), + ] + : [ + new HotModuleReplacementPlugin(), + new Self({ + filename: '[name].css', + }), + ], }; diff --git a/test/enforce-esm.test.js b/test/enforce-esm.test.js index cc4afe51..3587ffea 100644 --- a/test/enforce-esm.test.js +++ b/test/enforce-esm.test.js @@ -2,7 +2,7 @@ import webpack from 'webpack'; import { getCompiler, source, compile } from './helpers'; -const isWebpack5 = webpack.version[0] === '5'; +const isWebpack4 = webpack.version[0] === '4'; it('should enforce esm for empty module with options.esModule', async (done) => { const compiler = getCompiler( @@ -15,7 +15,10 @@ it('should enforce esm for empty module with options.esModule', async (done) => ); const stats = await compile(compiler); expect(stats.hasErrors()).toBe(false); - expect(stats.compilation.modules.length).toBe(isWebpack5 ? 4 : 2); + const { modules } = stats.toJson({ all: false, modules: true }); + expect( + modules.filter((m) => m.moduleType !== 'runtime' && !m.orphan).length + ).toBe(isWebpack4 ? 1 : 2); expect(source('./simple.css', stats)).toMatchInlineSnapshot(` "// extracted by mini-css-extract-plugin export {};" @@ -34,7 +37,10 @@ it('should keep empty module without options.esModule', async (done) => { ); const stats = await compile(compiler); expect(stats.hasErrors()).toBe(false); - expect(stats.compilation.modules.length).toBe(isWebpack5 ? 7 : 3); + const { modules } = stats.toJson({ all: false, modules: true }); + expect( + modules.filter((m) => m.moduleType !== 'runtime' && !m.orphan).length + ).toBe(isWebpack4 ? 2 : 3); expect(source('./simple.css', stats)).toMatchInlineSnapshot( `"// extracted by mini-css-extract-plugin"` ); diff --git a/test/manual/index.html b/test/manual/index.html index c95108db..26b9e7c9 100644 --- a/test/manual/index.html +++ b/test/manual/index.html @@ -5,7 +5,7 @@ mini-css-extract-plugin testcase - + -