mirror of https://github.com/webpack/webpack.git
fix: HMR failure in defer module (#19759)
This commit is contained in:
parent
e8e9f15b82
commit
07a9d20a4c
|
@ -18,6 +18,8 @@ const NullDependency = require("./NullDependency");
|
||||||
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
|
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
|
||||||
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
|
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
|
||||||
/** @typedef {import("./HarmonyAcceptImportDependency")} HarmonyAcceptImportDependency */
|
/** @typedef {import("./HarmonyAcceptImportDependency")} HarmonyAcceptImportDependency */
|
||||||
|
/** @typedef {import("../Module")} Module */
|
||||||
|
/** @typedef {import("../Module").ModuleId} ModuleId */
|
||||||
|
|
||||||
class HarmonyAcceptDependency extends NullDependency {
|
class HarmonyAcceptDependency extends NullDependency {
|
||||||
/**
|
/**
|
||||||
|
@ -84,7 +86,57 @@ HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate extends
|
||||||
chunkGraph
|
chunkGraph
|
||||||
} = templateContext;
|
} = templateContext;
|
||||||
|
|
||||||
/** @type {HarmonyAcceptImportDependency[]} */
|
/**
|
||||||
|
* @param {Dependency} dependency the dependency to get module id for
|
||||||
|
* @returns {ModuleId | null} the module id or null if not found
|
||||||
|
*/
|
||||||
|
const getDependencyModuleId = (dependency) =>
|
||||||
|
chunkGraph.getModuleId(
|
||||||
|
/** @type {Module} */ (moduleGraph.getModule(dependency))
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Dependency} a the first dependency
|
||||||
|
* @param {Dependency} b the second dependency
|
||||||
|
* @returns {boolean} true if the dependencies are related
|
||||||
|
*/
|
||||||
|
const isRelatedHarmonyImportDependency = (a, b) =>
|
||||||
|
a !== b &&
|
||||||
|
b instanceof HarmonyImportDependency &&
|
||||||
|
getDependencyModuleId(a) === getDependencyModuleId(b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HarmonyAcceptImportDependency lacks a lot of information, such as the defer property.
|
||||||
|
* One HarmonyAcceptImportDependency may need to generate multiple ImportStatements.
|
||||||
|
* Therefore, we find its original HarmonyImportDependency for code generation.
|
||||||
|
* @param {HarmonyAcceptImportDependency} dependency the dependency to get harmony import dependencies for
|
||||||
|
* @returns {HarmonyImportDependency[]} array of related harmony import dependencies
|
||||||
|
*/
|
||||||
|
const getHarmonyImportDependencies = (dependency) => {
|
||||||
|
const result = [];
|
||||||
|
let deferDependency = null;
|
||||||
|
let noDeferredDependency = null;
|
||||||
|
|
||||||
|
for (const d of module.dependencies) {
|
||||||
|
if (deferDependency && noDeferredDependency) break;
|
||||||
|
if (isRelatedHarmonyImportDependency(dependency, d)) {
|
||||||
|
if (d.defer) {
|
||||||
|
deferDependency = /** @type {HarmonyImportDependency} */ (d);
|
||||||
|
} else {
|
||||||
|
noDeferredDependency = /** @type {HarmonyImportDependency} */ (d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deferDependency) result.push(deferDependency);
|
||||||
|
if (noDeferredDependency) result.push(noDeferredDependency);
|
||||||
|
if (result.length === 0) {
|
||||||
|
// fallback to the original dependency
|
||||||
|
result.push(dependency);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {HarmonyImportDependency[]} */
|
||||||
const syncDeps = [];
|
const syncDeps = [];
|
||||||
|
|
||||||
/** @type {HarmonyAcceptImportDependency[]} */
|
/** @type {HarmonyAcceptImportDependency[]} */
|
||||||
|
@ -96,7 +148,7 @@ HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate extends
|
||||||
if (connection && moduleGraph.isAsync(connection.module)) {
|
if (connection && moduleGraph.isAsync(connection.module)) {
|
||||||
asyncDeps.push(dependency);
|
asyncDeps.push(dependency);
|
||||||
} else {
|
} else {
|
||||||
syncDeps.push(dependency);
|
syncDeps.push(...getHarmonyImportDependencies(dependency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export const a = "1";
|
||||||
|
---
|
||||||
|
export const a = "2";
|
|
@ -0,0 +1,14 @@
|
||||||
|
import * as a /* webpackDefer: true */ from "./a.js";
|
||||||
|
import * as a2 from "./a.js";
|
||||||
|
|
||||||
|
it("should handle defer import", (done) => {
|
||||||
|
expect(a.a).toBe("1");
|
||||||
|
expect(a2.a).toBe("1");
|
||||||
|
|
||||||
|
module.hot.accept("./a", function() {
|
||||||
|
expect(a.a).toBe("2");
|
||||||
|
expect(a2.a).toBe("2");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
NEXT(require("../../update.js")(done));
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @type {import("../../../../").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
target: [`async-node${process.versions.node.split(".").map(Number)[0]}`],
|
||||||
|
entry: "./index.js",
|
||||||
|
experiments: {
|
||||||
|
deferImport: true
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
concatenateModules: false
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
export const a = "1";
|
||||||
|
---
|
||||||
|
export const a = "2";
|
|
@ -0,0 +1,11 @@
|
||||||
|
import * as a /* webpackDefer: true */ from "./a.js";
|
||||||
|
|
||||||
|
it("should handle defer import", (done) => {
|
||||||
|
expect(a.a).toBe("1");
|
||||||
|
|
||||||
|
module.hot.accept("./a", function() {
|
||||||
|
expect(a.a).toBe("2");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
NEXT(require("../../update")(done));
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @type {import("../../../../").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
target: [`async-node${process.versions.node.split(".").map(Number)[0]}`],
|
||||||
|
entry: "./index.js",
|
||||||
|
experiments: {
|
||||||
|
deferImport: true
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
concatenateModules: false
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue