mirror of https://github.com/webpack/webpack.git
fix: ensure HMR recover gracefully when CSS module with error
This commit is contained in:
commit
087abd7908
|
@ -369,7 +369,8 @@ class FlagDependencyExportsPlugin {
|
||||||
(module, callback) => {
|
(module, callback) => {
|
||||||
if (
|
if (
|
||||||
typeof (
|
typeof (
|
||||||
/** @type {BuildInfo} */ (module.buildInfo).hash
|
/** @type {BuildInfo} */
|
||||||
|
(module.buildInfo).hash
|
||||||
) !== "string"
|
) !== "string"
|
||||||
) {
|
) {
|
||||||
// not cacheable
|
// not cacheable
|
||||||
|
|
|
@ -28,6 +28,7 @@ const makeSerializable = require("./util/makeSerializable");
|
||||||
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
|
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
|
||||||
/** @typedef {import("./Dependency")} Dependency */
|
/** @typedef {import("./Dependency")} Dependency */
|
||||||
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
|
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
|
||||||
|
/** @typedef {import("./DependencyTemplate").CssData} CssData */
|
||||||
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
|
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
|
||||||
/** @typedef {import("./ExportsInfo").UsageStateType} UsageStateType */
|
/** @typedef {import("./ExportsInfo").UsageStateType} UsageStateType */
|
||||||
/** @typedef {import("./FileSystemInfo")} FileSystemInfo */
|
/** @typedef {import("./FileSystemInfo")} FileSystemInfo */
|
||||||
|
@ -120,19 +121,25 @@ const makeSerializable = require("./util/makeSerializable");
|
||||||
* @typedef {object} KnownBuildInfo
|
* @typedef {object} KnownBuildInfo
|
||||||
* @property {boolean=} cacheable
|
* @property {boolean=} cacheable
|
||||||
* @property {boolean=} parsed
|
* @property {boolean=} parsed
|
||||||
* @property {string=} moduleArgument
|
|
||||||
* @property {string=} exportsArgument
|
|
||||||
* @property {boolean=} strict
|
* @property {boolean=} strict
|
||||||
* @property {string=} moduleConcatenationBailout
|
* @property {string=} moduleArgument using in AMD
|
||||||
* @property {LazySet<string>=} fileDependencies
|
* @property {string=} exportsArgument using in AMD
|
||||||
* @property {LazySet<string>=} contextDependencies
|
* @property {string=} moduleConcatenationBailout using in CommonJs
|
||||||
* @property {LazySet<string>=} missingDependencies
|
* @property {boolean=} needCreateRequire using in APIPlugin
|
||||||
* @property {LazySet<string>=} buildDependencies
|
* @property {string=} resourceIntegrity using in HttpUriPlugin
|
||||||
* @property {ValueCacheVersions=} valueDependencies
|
* @property {LazySet<string>=} fileDependencies using in NormalModule
|
||||||
* @property {TODO=} hash
|
* @property {LazySet<string>=} contextDependencies using in NormalModule
|
||||||
* @property {Record<string, Source>=} assets
|
* @property {LazySet<string>=} missingDependencies using in NormalModule
|
||||||
* @property {Map<string, AssetInfo | undefined>=} assetsInfo
|
* @property {LazySet<string>=} buildDependencies using in NormalModule
|
||||||
* @property {(Snapshot | null)=} snapshot
|
* @property {ValueCacheVersions=} valueDependencies using in NormalModule
|
||||||
|
* @property {Record<string, Source>=} assets using in NormalModule
|
||||||
|
* @property {string=} hash using in NormalModule
|
||||||
|
* @property {(Snapshot | null)=} snapshot using in ContextModule
|
||||||
|
* @property {string=} fullContentHash for assets modules
|
||||||
|
* @property {string=} filename for assets modules
|
||||||
|
* @property {Map<string, AssetInfo | undefined>=} assetsInfo for assets modules
|
||||||
|
* @property {boolean=} dataUrl for assets modules
|
||||||
|
* @property {CssData=} cssData for css modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @typedef {Map<string, string | Set<string>>} ValueCacheVersions */
|
/** @typedef {Map<string, string | Set<string>>} ValueCacheVersions */
|
||||||
|
|
|
@ -1632,7 +1632,11 @@ class NormalModule extends Module {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
updateHash(hash, context) {
|
updateHash(hash, context) {
|
||||||
hash.update(/** @type {BuildInfo} */ (this.buildInfo).hash);
|
const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
|
||||||
|
hash.update(
|
||||||
|
/** @type {string} */
|
||||||
|
(buildInfo.hash)
|
||||||
|
);
|
||||||
/** @type {Generator} */
|
/** @type {Generator} */
|
||||||
(this.generator).updateHash(hash, {
|
(this.generator).updateHash(hash, {
|
||||||
module: this,
|
module: this,
|
||||||
|
|
|
@ -292,7 +292,7 @@ class CssGenerator extends Generator {
|
||||||
Array.from(exports).reduce((obj, [key, value]) => {
|
Array.from(exports).reduce((obj, [key, value]) => {
|
||||||
obj[key] = value;
|
obj[key] = value;
|
||||||
return obj;
|
return obj;
|
||||||
}, {})
|
}, /** @type {Record<string, string>} */ ({}))
|
||||||
);
|
);
|
||||||
|
|
||||||
return stringifiedExports.length + 42;
|
return stringifiedExports.length + 42;
|
||||||
|
|
|
@ -385,15 +385,17 @@ class CssModulesPlugin {
|
||||||
compilation
|
compilation
|
||||||
).renderModuleContent.tap(PLUGIN_NAME, (source, module) => {
|
).renderModuleContent.tap(PLUGIN_NAME, (source, module) => {
|
||||||
if (module instanceof CssModule && module.hot) {
|
if (module instanceof CssModule && module.hot) {
|
||||||
const exports =
|
const cssData = /** @type {BuildInfo} */ (module.buildInfo).cssData;
|
||||||
/** @type {BuildInfo} */
|
if (!cssData) {
|
||||||
(module.buildInfo).cssData.exports;
|
return source;
|
||||||
|
}
|
||||||
|
const exports = cssData.exports;
|
||||||
const stringifiedExports = JSON.stringify(
|
const stringifiedExports = JSON.stringify(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
Array.from(exports).reduce((obj, [key, value]) => {
|
Array.from(exports).reduce((obj, [key, value]) => {
|
||||||
obj[key] = value;
|
obj[key] = value;
|
||||||
return obj;
|
return obj;
|
||||||
}, {})
|
}, /** @type {Record<string, string>} */ ({}))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = [
|
||||||
|
/Error in loader/,
|
||||||
|
];
|
|
@ -0,0 +1,25 @@
|
||||||
|
import "./loader!./style.css";
|
||||||
|
|
||||||
|
it("should work", async function (done) {
|
||||||
|
const links = window.document.getElementsByTagName("link");
|
||||||
|
expect(links[0].sheet.css).toContain("color: red;");
|
||||||
|
|
||||||
|
NEXT(require("../../update")(done, {
|
||||||
|
ignoreErrored: true
|
||||||
|
}, () => {
|
||||||
|
expect(links[0].sheet.css).toContain("Error in loader");
|
||||||
|
|
||||||
|
NEXT(require("../../update")(done, {
|
||||||
|
ignoreErrored: true
|
||||||
|
}, () => {
|
||||||
|
expect(links[0].sheet.css).toContain("color: blue;");
|
||||||
|
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (import.meta.webpackHot) {
|
||||||
|
import.meta.webpackHot.accept("./loader!./style.css");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/** @type {import("../../../../").LoaderDefinition} */
|
||||||
|
module.exports = function(content) {
|
||||||
|
const callback = this.async();
|
||||||
|
|
||||||
|
if (content.includes("Failed")) {
|
||||||
|
callback(new Error("Error in loader"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, content);
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
.class {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
---
|
||||||
|
.class {
|
||||||
|
color: green;
|
||||||
|
}Failed
|
||||||
|
---
|
||||||
|
.class {
|
||||||
|
color: blue;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = function (config) {
|
||||||
|
return config.target === "web";
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
/** @type {import("../../../../").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
experiments: {
|
||||||
|
css: true
|
||||||
|
}
|
||||||
|
};
|
|
@ -3172,6 +3172,17 @@ declare interface CssAutoParserOptions {
|
||||||
*/
|
*/
|
||||||
url?: boolean;
|
url?: boolean;
|
||||||
}
|
}
|
||||||
|
declare interface CssData {
|
||||||
|
/**
|
||||||
|
* whether export __esModule
|
||||||
|
*/
|
||||||
|
esModule: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the css exports
|
||||||
|
*/
|
||||||
|
exports: Map<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generator options for css modules.
|
* Generator options for css modules.
|
||||||
|
@ -7711,19 +7722,97 @@ declare interface KnownAssetInfo {
|
||||||
declare interface KnownBuildInfo {
|
declare interface KnownBuildInfo {
|
||||||
cacheable?: boolean;
|
cacheable?: boolean;
|
||||||
parsed?: boolean;
|
parsed?: boolean;
|
||||||
moduleArgument?: string;
|
|
||||||
exportsArgument?: string;
|
|
||||||
strict?: boolean;
|
strict?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in AMD
|
||||||
|
*/
|
||||||
|
moduleArgument?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in AMD
|
||||||
|
*/
|
||||||
|
exportsArgument?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in CommonJs
|
||||||
|
*/
|
||||||
moduleConcatenationBailout?: string;
|
moduleConcatenationBailout?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in APIPlugin
|
||||||
|
*/
|
||||||
|
needCreateRequire?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in HttpUriPlugin
|
||||||
|
*/
|
||||||
|
resourceIntegrity?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
fileDependencies?: LazySet<string>;
|
fileDependencies?: LazySet<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
contextDependencies?: LazySet<string>;
|
contextDependencies?: LazySet<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
missingDependencies?: LazySet<string>;
|
missingDependencies?: LazySet<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
buildDependencies?: LazySet<string>;
|
buildDependencies?: LazySet<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
valueDependencies?: Map<string, string | Set<string>>;
|
valueDependencies?: Map<string, string | Set<string>>;
|
||||||
hash?: any;
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
assets?: Record<string, Source>;
|
assets?: Record<string, Source>;
|
||||||
assetsInfo?: Map<string, undefined | AssetInfo>;
|
|
||||||
|
/**
|
||||||
|
* using in NormalModule
|
||||||
|
*/
|
||||||
|
hash?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using in ContextModule
|
||||||
|
*/
|
||||||
snapshot?: null | Snapshot;
|
snapshot?: null | Snapshot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for assets modules
|
||||||
|
*/
|
||||||
|
fullContentHash?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for assets modules
|
||||||
|
*/
|
||||||
|
filename?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for assets modules
|
||||||
|
*/
|
||||||
|
assetsInfo?: Map<string, undefined | AssetInfo>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for assets modules
|
||||||
|
*/
|
||||||
|
dataUrl?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for css modules
|
||||||
|
*/
|
||||||
|
cssData?: CssData;
|
||||||
}
|
}
|
||||||
declare interface KnownBuildMeta {
|
declare interface KnownBuildMeta {
|
||||||
exportsType?: "namespace" | "dynamic" | "default" | "flagged";
|
exportsType?: "namespace" | "dynamic" | "default" | "flagged";
|
||||||
|
|
Loading…
Reference in New Issue