Skip to content

Commit

Permalink
Merge pull request webpack#11433 from samcooke98/samc/fix-module-rebuild
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra authored Jan 15, 2021
2 parents de2b86e + 1019544 commit fa5cc45
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 15 deletions.
35 changes: 20 additions & 15 deletions lib/Compilation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2683,26 +2683,27 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
* @returns {void}
*/
removeReasonsOfDependencyBlock(module, block) {
const chunkGraph = this.chunkGraph;
const iteratorDependency = d => {
if (!d.module) {
return;
}
if (d.module.removeReason(module, d)) {
for (const chunk of chunkGraph.getModuleChunksIterable(d.module)) {
this.patchChunksAfterReasonRemoval(d.module, chunk);
}
}
};

if (block.blocks) {
for (const b of block.blocks) {
this.removeReasonsOfDependencyBlock(module, b);
}
}

if (block.dependencies) {
for (const dep of block.dependencies) iteratorDependency(dep);
for (const dep of block.dependencies) {
const originalModule = this.moduleGraph.getModule(dep);
if (originalModule) {
this.moduleGraph.removeConnection(dep);

if (this.chunkGraph) {
for (const chunk of this.chunkGraph.getModuleChunks(
originalModule
)) {
this.patchChunksAfterReasonRemoval(originalModule, chunk);
}
}
}
}
}
}

Expand Down Expand Up @@ -2730,11 +2731,15 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
* @returns {void}
*/
removeChunkFromDependencies(block, chunk) {
/**
* @param {Dependency} d dependency to (maybe) patch up
*/
const iteratorDependency = d => {
if (!d.module) {
const depModule = this.moduleGraph.getModule(d);
if (!depModule) {
return;
}
this.patchChunksAfterReasonRemoval(d.module, chunk);
this.patchChunksAfterReasonRemoval(depModule, chunk);
};

const blocks = block.blocks;
Expand Down
5 changes: 5 additions & 0 deletions test/configCases/rebuild/finishModules/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { doThings, foo } from "./other-file";

export { doThings, foo };

export const valueFromA = "A";
Empty file.
20 changes: 20 additions & 0 deletions test/configCases/rebuild/finishModules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { doThings, foo, valueFromA } from "./a";
it("should compile", function (done) {
expect(doThings("ok")).toBe("ok");

// Should be replaced by the code in the config.
expect(foo.foo).toBe("bar");
expect(valueFromA).toBe("A");

done();
});

it("should not reference the chunk", () => {
expect(__STATS__.chunks.length).toEqual(1);
expect(
__STATS__.modules
.filter(m => m.moduleType !== "runtime")
.map(m => m.name)
.sort()
).toEqual(["./a.js", "./index.js", "./other-file.js"]);
});
5 changes: 5 additions & 0 deletions test/configCases/rebuild/finishModules/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = function (source) {
if (this.shouldReplace)
return "module.exports = { foo: { foo: 'bar' }, doThings: (v) => v}";
return source;
};
1 change: 1 addition & 0 deletions test/configCases/rebuild/finishModules/module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default "foo";
9 changes: 9 additions & 0 deletions test/configCases/rebuild/finishModules/other-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import foo from "./module";

export function doThings(stuff) {
return import("./chunk");
}

export const foo = {
foo
};
60 changes: 60 additions & 0 deletions test/configCases/rebuild/finishModules/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const { resolve, join } = require("path");
const { NormalModule } = require("../../../../");

/**
* @param {import("../../../../").Compiler} compiler the compiler
*/
var testPlugin = compiler => {
compiler.hooks.compilation.tap("TestPlugin", compilation => {
let shouldReplace = false;
NormalModule.getCompilationHooks(compilation).loader.tap(
"TestPlugin",
loaderContext => {
/** @type {any} */ (loaderContext).shouldReplace = shouldReplace;
}
);
compilation.hooks.finishModules.tapAsync(
"TestPlugin",
function (modules, callback) {
const src = resolve(join(__dirname, "other-file.js"));

/**
*
* @param {any} m test
* @returns {boolean} test
*/
function matcher(m) {
return m.resource && m.resource === src;
}

const module = Array.from(modules).find(matcher);

if (!module) {
throw new Error("something went wrong");
}

shouldReplace = true;
compilation.rebuildModule(module, err => {
shouldReplace = false;
callback(err);
});
}
);
});
};

/** @type {import("../../../../").Configuration} */
module.exports = {
module: {
rules: [
{
test: /other-file/,
use: "./loader"
}
]
},
optimization: {
concatenateModules: false
},
plugins: [testPlugin]
};

0 comments on commit fa5cc45

Please sign in to comment.