Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

avoid making the package.json in context a build dependency #12822

Merged
merged 2 commits into from Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/SourceMapDevToolPlugin.js
Expand Up @@ -211,7 +211,10 @@ class SourceMapDevToolPlugin {
}
const cacheItem = cache.getItemCache(
file,
cache.getLazyHashedEtag(asset.source)
cache.mergeEtags(
cache.getLazyHashedEtag(asset.source),
namespace
)
);

cacheItem.get((err, cacheEntry) => {
Expand Down
7 changes: 6 additions & 1 deletion lib/config/defaults.js
Expand Up @@ -562,10 +562,15 @@ const applyOutputDefaults = (
F(output, "uniqueName", () => {
const libraryName = getLibraryName(output.library);
if (libraryName) return libraryName;
const pkgPath = path.resolve(context, "package.json");
try {
const packageInfo = require(`${context}/package.json`);
const packageInfo = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
return packageInfo.name || "";
} catch (e) {
if (e.code !== "ENOENT") {
e.message += `\nwhile determining default 'output.uniqueName' from 'name' in ${pkgPath}`;
throw e;
}
return "";
}
});
Expand Down
121 changes: 79 additions & 42 deletions test/BuildDependencies.test.js
Expand Up @@ -50,6 +50,13 @@ describe("BuildDependencies", () => {
fs.mkdir(inputDirectory, { recursive: true }, done);
});
it("should capture loader and config dependencies", async () => {
fs.writeFileSync(
path.resolve(inputDirectory, "package.json"),
JSON.stringify({
name: "yep",
version: "1.0.0"
})
);
fs.writeFileSync(
path.resolve(inputDirectory, "loader-dependency.js"),
"module.exports = 0;"
Expand Down Expand Up @@ -89,79 +96,109 @@ describe("BuildDependencies", () => {
"module.exports = Date.now();"
);
const now1 = Date.now();
expect(await exec("2")).toMatch(/Captured build dependencies/);
expect(await exec("3")).not.toMatch(/Captured build dependencies/);
const output2 = await exec("2");
expect(output2).toMatch(/but build dependencies have changed/);
expect(output2).toMatch(/Captured build dependencies/);
const output3 = await exec("3");
expect(output3).not.toMatch(/resolving of build dependencies is invalid/);
expect(output3).not.toMatch(/but build dependencies have changed/);
expect(output3).not.toMatch(/Captured build dependencies/);
fs.writeFileSync(
path.resolve(inputDirectory, "package.json"),
JSON.stringify({
name: "other",
version: "2.0.0"
})
);
const output4 = await exec("4");
expect(output4).toMatch(/resolving of build dependencies is invalid/);
expect(output4).not.toMatch(/but build dependencies have changed/);
expect(output4).toMatch(/Captured build dependencies/);
fs.writeFileSync(
path.resolve(inputDirectory, "config-dependency"),
"module.exports = Date.now();"
);
const now2 = Date.now();
await exec("4");
const now3 = Date.now();
await exec("5");
const now3 = Date.now();
await exec("6");
let now4, now5;
if (supportsEsm) {
fs.writeFileSync(
path.resolve(inputDirectory, "esm-dependency.js"),
"module.exports = Date.now();"
);
now4 = Date.now();
await exec("6");
await exec("7");
fs.writeFileSync(
path.resolve(inputDirectory, "esm-async-dependency.mjs"),
"export default Date.now();"
);
now5 = Date.now();
await exec("7");
await exec("8");
}
const results = Array.from({ length: supportsEsm ? 8 : 6 }).map((_, i) =>
const results = Array.from({ length: supportsEsm ? 9 : 7 }).map((_, i) =>
require(`./js/buildDeps/${i}/main.js`)
);
for (const r of results) {
expect(typeof r.loader).toBe("number");
expect(typeof r.config).toBe("number");
expect(typeof r.uncached).toBe("number");
}
expect(results[0].loader).toBe(0);
expect(results[0].config).toBe(0);
if (supportsEsm) expect(results[0].esmConfig).toBe(0);
expect(results[0].uncached).toBe(0);
let result = results.shift();
expect(result.loader).toBe(0);
expect(result.config).toBe(0);
if (supportsEsm) expect(result.esmConfig).toBe(0);
expect(result.uncached).toBe(0);
// 0 -> 1 should not cache at all because of invalid buildDeps
expect(results[1].loader).toBe(1);
expect(results[1].config).toBe(1);
expect(results[1].esmConfig).toBe(1);
expect(results[1].uncached).toBe(1);
result = results.shift();
expect(result.loader).toBe(1);
expect(result.config).toBe(1);
expect(result.esmConfig).toBe(1);
expect(result.uncached).toBe(1);
// 1 -> 2 should be invalidated
expect(results[2].loader).toBeGreaterThan(now1);
expect(results[2].config).toBe(1);
expect(results[2].esmConfig).toBe(1);
expect(results[2].uncached).toBe(1);
result = results.shift();
expect(result.loader).toBeGreaterThan(now1);
expect(result.config).toBe(1);
expect(result.esmConfig).toBe(1);
expect(result.uncached).toBe(1);
// 2 -> 3 should stay cached
expect(results[3].loader).toBe(results[2].loader);
expect(results[3].config).toBe(1);
expect(results[3].esmConfig).toBe(1);
expect(results[3].uncached).toBe(1);
// 3 -> 4 should be invalidated
expect(results[4].loader).toBeGreaterThan(now2);
expect(results[4].config).toBeGreaterThan(now2);
expect(results[4].esmConfig).toBe(1);
expect(results[4].uncached).toBe(results[4].config);
// 4 -> 5 should stay cached, but uncacheable module still rebuilds
expect(results[5].loader).toBe(results[4].loader);
expect(results[5].config).toBe(results[4].config);
expect(results[5].uncached).toBeGreaterThan(now3);
result = results.shift();
expect(result.loader).toBe(result.loader);
expect(result.config).toBe(1);
expect(result.esmConfig).toBe(1);
expect(result.uncached).toBe(1);
// 3 -> 4 should stay cached
result = results.shift();
expect(result.loader).toBe(result.loader);
expect(result.config).toBe(1);
expect(result.esmConfig).toBe(1);
expect(result.uncached).toBe(1);
// 4 -> 5 should be invalidated
result = results.shift();
expect(result.loader).toBeGreaterThan(now2);
expect(result.config).toBeGreaterThan(now2);
expect(result.esmConfig).toBe(1);
expect(result.uncached).toBe(result.config);
// 5 -> 6 should stay cached, but uncacheable module still rebuilds
result = results.shift();
expect(result.loader).toBe(result.loader);
expect(result.config).toBe(result.config);
expect(result.uncached).toBeGreaterThan(now3);
if (supportsEsm) {
// 5 -> 6 should be invalidated
expect(results[6].loader).toBeGreaterThan(now4);
expect(results[6].config).toBeGreaterThan(now4);
expect(results[6].esmConfig).toBeGreaterThan(now4);
expect(results[6].uncached).toBeGreaterThan(now4);
// 6 -> 7 should be invalidated
expect(results[7].loader).toBeGreaterThan(now5);
expect(results[7].config).toBeGreaterThan(now5);
expect(results[7].esmConfig).toBeGreaterThan(now5);
expect(results[7].esmAsyncConfig).toBeGreaterThan(now5);
expect(results[7].uncached).toBeGreaterThan(now5);
result = results.shift();
expect(result.loader).toBeGreaterThan(now4);
expect(result.config).toBeGreaterThan(now4);
expect(result.esmConfig).toBeGreaterThan(now4);
expect(result.uncached).toBeGreaterThan(now4);
// 7 -> 8 should be invalidated
result = results.shift();
expect(result.loader).toBeGreaterThan(now5);
expect(result.config).toBeGreaterThan(now5);
expect(result.esmConfig).toBeGreaterThan(now5);
expect(result.esmAsyncConfig).toBeGreaterThan(now5);
expect(result.uncached).toBeGreaterThan(now5);
}
}, 100000);
});
9 changes: 5 additions & 4 deletions test/StatsTestCases.test.js
Expand Up @@ -117,6 +117,11 @@ describe("StatsTestCases", () => {
});
c.run((err, stats) => {
if (err) return done(err);
for (const compilation of []
.concat(stats.stats || stats)
.map(s => s.compilation)) {
compilation.logging.delete("webpack.Compilation.ModuleProfile");
}
if (/error$/.test(testName)) {
expect(stats.hasErrors()).toBe(true);
} else if (stats.hasErrors()) {
Expand Down Expand Up @@ -184,10 +189,6 @@ describe("StatsTestCases", () => {
actual = actual
.replace(/\r\n?/g, "\n")
.replace(/webpack [^ )]+(\)?) compiled/g, "webpack x.x.x$1 compiled")
.replace(
/LOG from webpack\.Compilation\.ModuleProfile\n([^\n]+\n)*\n/g,
""
)
.replace(new RegExp(quotemeta(testPath), "g"), "Xdir/" + testName)
.replace(/(\w)\\(\w)/g, "$1/$2")
.replace(/, additional resolving: X ms/g, "");
Expand Down
2 changes: 1 addition & 1 deletion test/configCases/worker/node-worker-named/index.js
Expand Up @@ -25,7 +25,7 @@ it("should allow to create another WebWorker", async () => {
});
});
expect(result).toBe("data: OK, thanks");
worker.terminate();
await worker.terminate();
});

it("should allow to share chunks", async () => {
Expand Down
6 changes: 3 additions & 3 deletions test/fixtures/buildDependencies/run.js
Expand Up @@ -21,8 +21,8 @@ function run({ default: value2, asyncDep: value3 }) {
const compiler = webpack(
{
mode: "development",
context: __dirname,
entry: "./index",
context: path.resolve(__dirname, "../../js/buildDepsInput"),
entry: path.resolve(__dirname, "./index"),
output: {
path: path.resolve(__dirname, "../../js/buildDeps/" + process.argv[2]),
libraryTarget: "commonjs2"
Expand All @@ -49,7 +49,7 @@ function run({ default: value2, asyncDep: value3 }) {
config: [
__filename,
path.resolve(__dirname, "../../../node_modules/.yarn-integrity")
].concat(esm ? ["./esm.mjs"] : []),
].concat(esm ? ["../../fixtures/buildDependencies/esm.mjs"] : []),
invalid: options.invalidBuildDepdencies
? ["should-fail-resolving"]
: []
Expand Down
5 changes: 3 additions & 2 deletions test/hotCases/worker/update-in-worker/index.js
Expand Up @@ -8,10 +8,11 @@ it("should support hot module replacement in WebWorkers", done => {
});
break;
case "done":
done();
Promise.resolve(worker.terminate()).then(() => done(), done);
break;
default:
throw new Error(`Unexpected message: ${msg}`);
}
};
worker.postMessage("test");
Promise.resolve(worker.terminate()).then(done, done);
});
32 changes: 18 additions & 14 deletions test/hotCases/worker/update-in-worker/worker.js
Expand Up @@ -3,21 +3,25 @@ import module from "./module";
let counter = 1;

self.onmessage = async ({ data: msg }) => {
switch (msg) {
case "next":
await import.meta.webpackHot.check(true);
case "test":
if (module === 42 && counter === 4) {
self.postMessage("done");
try {
switch (msg) {
case "next":
await import.meta.webpackHot.check(true);
case "test":
if (module === 42 && counter === 4) {
self.postMessage("done");
break;
}
if (module !== counter)
throw new Error(`module (${module}) should be ${counter}`);
counter++;
self.postMessage("next");
break;
}
if (module !== counter)
throw new Error(`module (${module}) should be ${counter}`);
counter++;
self.postMessage("next");
break;
default:
throw new Error("Unexpected message");
default:
throw new Error("Unexpected message");
}
} catch (e) {
self.postMessage("error: " + e.stack);
}
};

Expand Down