Merge pull request #11137 from webpack/change/dev-no-used

disable used exports optimization in development
This commit is contained in:
Tobias Koppers 2020-07-09 09:23:49 +02:00 committed by GitHub
commit 342a596463
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 197 additions and 122 deletions

View File

@ -550,8 +550,8 @@ const applyOptimizationDefaults = (
});
D(optimization, "sideEffects", true);
D(optimization, "providedExports", true);
D(optimization, "usedExports", true);
D(optimization, "innerGraph", true);
D(optimization, "usedExports", production);
D(optimization, "innerGraph", production);
D(optimization, "mangleExports", production);
D(optimization, "concatenateModules", production);
D(optimization, "runtimeChunk", false);

View File

@ -29,8 +29,13 @@ const getProperty = (moduleGraph, module, exportName, property) => {
switch (property) {
case "usedExports": {
const usedExports = moduleGraph.getExportsInfo(module).getUsedExports();
if (typeof usedExports === "boolean" || usedExports === undefined)
if (
typeof usedExports === "boolean" ||
usedExports === undefined ||
usedExports === null
) {
return usedExports;
}
return Array.from(usedExports).sort();
}
}

View File

@ -148,7 +148,7 @@ describe("Defaults", () => {
"chunkIds": "natural",
"concatenateModules": false,
"flagIncludedChunks": false,
"innerGraph": true,
"innerGraph": false,
"mangleExports": false,
"mangleWasmImports": false,
"mergeDuplicateChunks": true,
@ -191,7 +191,7 @@ describe("Defaults", () => {
"minRemainingSize": undefined,
"minSize": 10000,
},
"usedExports": true,
"usedExports": false,
},
"output": Object {
"assetModuleFilename": "[hash][ext]",
@ -357,12 +357,13 @@ describe("Defaults", () => {
- "chunkIds": "natural",
- "concatenateModules": false,
- "flagIncludedChunks": false,
- "innerGraph": false,
- "mangleExports": false,
+ "checkWasmTypes": true,
+ "chunkIds": "deterministic",
+ "concatenateModules": true,
+ "flagIncludedChunks": true,
@@ ... @@
- "mangleExports": false,
+ "innerGraph": true,
+ "mangleExports": true,
@@ ... @@
- "minimize": false,
@ -385,6 +386,9 @@ describe("Defaults", () => {
- "minSize": 10000,
+ "minSize": 30000,
@@ ... @@
- "usedExports": false,
+ "usedExports": true,
@@ ... @@
- "performance": false,
+ "performance": Object {
+ "hints": "warning",
@ -406,12 +410,13 @@ describe("Defaults", () => {
- "chunkIds": "natural",
- "concatenateModules": false,
- "flagIncludedChunks": false,
- "innerGraph": false,
- "mangleExports": false,
+ "checkWasmTypes": true,
+ "chunkIds": "deterministic",
+ "concatenateModules": true,
+ "flagIncludedChunks": true,
@@ ... @@
- "mangleExports": false,
+ "innerGraph": true,
+ "mangleExports": true,
@@ ... @@
- "minimize": false,
@ -434,6 +439,9 @@ describe("Defaults", () => {
- "minSize": 10000,
+ "minSize": 30000,
@@ ... @@
- "usedExports": false,
+ "usedExports": true,
@@ ... @@
- "performance": false,
+ "performance": Object {
+ "hints": "warning",

View File

@ -447,29 +447,31 @@ Child all:
`;
exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = `
"Hash: f33d111f25cd01c8c3cf
"Hash: 024b7b1350be3708ba8e
Time: X ms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
Asset Size
main1.js 1.9 KiB [emitted] [name: main1]
main2.js 1.9 KiB [emitted] [name: main2]
Asset Size
main1.js 4.39 KiB [emitted] [name: main1]
main2.js 4.38 KiB [emitted] [name: main2]
Entrypoint main1 = main1.js
Entrypoint main2 = main2.js
chunk main2.js (main2) 136 bytes [entry] [rendered]
chunk main2.js (main2) 136 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
> ./main2 main2
./a.js 20 bytes [built]
./d.js 20 bytes [built]
./e.js 20 bytes [built]
./f.js 20 bytes [built]
./main2.js 56 bytes [built]
chunk main1.js (main1) 136 bytes [entry] [rendered]
+ 3 hidden chunk modules
chunk main1.js (main1) 136 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
> ./main1 main1
./a.js 20 bytes [built]
./b.js 20 bytes [built]
./c.js 20 bytes [built]
./d.js 20 bytes [built]
./main1.js 56 bytes [built]"
./main1.js 56 bytes [built]
+ 3 hidden chunk modules"
`;
exports[`StatsTestCases should print correct stats for chunks 1`] = `
@ -3568,10 +3570,10 @@ Child development:
chunk dev-main-very-big_js-4647fb9d.js (main-very-big_js-4647fb9d) 1.57 KiB ={main-big_js-1}= ={main-in-some-directory_b}= ={main-in-some-directory_very-big_js-8d76cf03}= ={main-index_js-41f5a26e}= ={main-inner-module_small_js-3}= ={main-small_js-1}= ={main-subfolder_big_js-b}= ={main-subfolder_small_js-1}= ={main-very-big_js-08cf55cf}= ={main-very-big_js-62f7f644}= ={vendors-node_modules_big_js_1-node_modules_small_js_1-node_modules_small_js_2}= ={vendors-node_modules_very-big_js_1}= [initial] [rendered]
> ./ main
./very-big.js?3 1.57 KiB [built]
chunk dev-main-very-big_js-62f7f644.js (main-very-big_js-62f7f644) 1.57 KiB (javascript) 4.84 KiB (runtime) ={main-big_js-1}= ={main-in-some-directory_b}= ={main-in-some-directory_very-big_js-8d76cf03}= ={main-index_js-41f5a26e}= ={main-inner-module_small_js-3}= ={main-small_js-1}= ={main-subfolder_big_js-b}= ={main-subfolder_small_js-1}= ={main-very-big_js-08cf55cf}= ={main-very-big_js-4647fb9d}= ={vendors-node_modules_big_js_1-node_modules_small_js_1-node_modules_small_js_2}= ={vendors-node_modules_very-big_js_1}= [entry] [rendered]
chunk dev-main-very-big_js-62f7f644.js (main-very-big_js-62f7f644) 1.57 KiB (javascript) 5.11 KiB (runtime) ={main-big_js-1}= ={main-in-some-directory_b}= ={main-in-some-directory_very-big_js-8d76cf03}= ={main-index_js-41f5a26e}= ={main-inner-module_small_js-3}= ={main-small_js-1}= ={main-subfolder_big_js-b}= ={main-subfolder_small_js-1}= ={main-very-big_js-08cf55cf}= ={main-very-big_js-4647fb9d}= ={vendors-node_modules_big_js_1-node_modules_small_js_1-node_modules_small_js_2}= ={vendors-node_modules_very-big_js_1}= [entry] [rendered]
> ./ main
./very-big.js?1 1.57 KiB [built]
+ 5 hidden root modules
+ 6 hidden root modules
chunk dev-vendors-node_modules_big_js_1-node_modules_small_js_1-node_modules_small_js_2.js (id hint: vendors) 402 bytes ={main-big_js-1}= ={main-in-some-directory_b}= ={main-in-some-directory_very-big_js-8d76cf03}= ={main-index_js-41f5a26e}= ={main-inner-module_small_js-3}= ={main-small_js-1}= ={main-subfolder_big_js-b}= ={main-subfolder_small_js-1}= ={main-very-big_js-08cf55cf}= ={main-very-big_js-4647fb9d}= ={main-very-big_js-62f7f644}= ={vendors-node_modules_very-big_js_1}= [initial] [rendered] split chunk (cache group: defaultVendors)
> ./ main
./node_modules/big.js?1 268 bytes [built]

View File

@ -116,67 +116,71 @@ it("should not find module when mode is weak and chunk not served elsewhere (wit
});
});
it("should contain only one export from webpackExports from module", function () {
return import(/* webpackExports: "usedExports" */ "./dir12/a?1").then(
module => {
expect(module.usedExports).toEqual(["usedExports"]);
}
);
});
it("should contain only webpackExports from module", function () {
return import(
/* webpackExports: ["a", "usedExports", "b"] */ "./dir12/a?2"
).then(module => {
expect(module.usedExports).toEqual(["a", "b", "usedExports"]);
if (process.env.NODE_ENV === "production") {
it("should contain only one export from webpackExports from module", function () {
return import(/* webpackExports: "usedExports" */ "./dir12/a?1").then(
module => {
expect(module.usedExports).toEqual(["usedExports"]);
}
);
});
});
it("should contain only webpackExports from module in eager mode", function () {
return import(
/*
it("should contain only webpackExports from module", function () {
return import(
/* webpackExports: ["a", "usedExports", "b"] */ "./dir12/a?2"
).then(module => {
expect(module.usedExports).toEqual(["a", "b", "usedExports"]);
});
});
it("should contain only webpackExports from module in eager mode", function () {
return import(
/*
webpackMode: "eager",
webpackExports: ["a", "usedExports", "b"]
*/ "./dir12/a?3"
).then(module => {
expect(module.usedExports).toEqual(["a", "b", "usedExports"]);
).then(module => {
expect(module.usedExports).toEqual(["a", "b", "usedExports"]);
});
});
});
it("should contain webpackExports from module in weak mode", function () {
require.resolve("./dir12/a?4");
return import(
/*
it("should contain webpackExports from module in weak mode", function () {
require.resolve("./dir12/a?4");
return import(
/*
webpackMode: "weak",
webpackExports: ["a", "usedExports", "b"]
*/ "./dir12/a?4"
).then(module => {
expect(module.usedExports).toEqual(["a", "b", "usedExports"]);
).then(module => {
expect(module.usedExports).toEqual(["a", "b", "usedExports"]);
});
});
});
it("should not mangle webpackExports from module", function () {
return import(/* webpackExports: "longnameforexport" */ "./dir12/a?5").then(
module => {
expect(module).toHaveProperty("longnameforexport");
}
);
});
it("should not mangle default webpackExports from module", function () {
return import(/* webpackExports: "default" */ "./dir12/a?6").then(module => {
expect(module).toHaveProperty("default");
it("should not mangle webpackExports from module", function () {
return import(/* webpackExports: "longnameforexport" */ "./dir12/a?5").then(
module => {
expect(module).toHaveProperty("longnameforexport");
}
);
});
});
it("should contain only webpackExports from module in context mode", function () {
const x = "b";
return import(/* webpackExports: "usedExports" */ `./dir13/${x}`).then(
module => {
expect(module.usedExports).toEqual(["usedExports"]);
}
);
});
it("should not mangle default webpackExports from module", function () {
return import(/* webpackExports: "default" */ "./dir12/a?6").then(
module => {
expect(module).toHaveProperty("default");
}
);
});
it("should contain only webpackExports from module in context mode", function () {
const x = "b";
return import(/* webpackExports: "usedExports" */ `./dir13/${x}`).then(
module => {
expect(module.usedExports).toEqual(["usedExports"]);
}
);
});
}
function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested) {
var sync = false;

View File

@ -5,6 +5,8 @@ it("export should be unused when only unused functions use it", () => {
expect(y("a")).toBe("okBAA");
expect(exportAUsed).toBe(true);
expect(exportBUsed).toBe(true);
expect(exportCUsed).toBe(false);
if (process.env.NODE_ENV === "production") {
expect(exportCUsed).toBe(false);
}
return import("./chunk");
});

View File

@ -21,21 +21,25 @@ it("a should be used", () => {
expect(a).toBe(true);
});
it("b should be unused", () => {
expect(b).toBe(false);
});
if (process.env.NODE_ENV === "production") {
it("b should be unused", () => {
expect(b).toBe(false);
});
}
it("c should be used", () => {
expect(c).toBe(true);
});
it("d should be used", () => {
expect(d).toBe(true);
});
if (process.env.NODE_ENV === "production") {
it("d should be used", () => {
expect(d).toBe(true);
});
it("e should be unused", () => {
expect(e).toBe(false);
});
it("e should be unused", () => {
expect(e).toBe(false);
});
}
it("f should be used", () => {
expect(f).toBe(true);

View File

@ -14,9 +14,11 @@ it("should load modules correctly", () => {
require("./module2");
});
it("B should not be used", () => {
expect(exportsInfoForB).toBe(false);
});
if (process.env.NODE_ENV === "production") {
it("B should not be used", () => {
expect(exportsInfoForB).toBe(false);
});
}
it("A should be used", () => {
expect(exportsInfoForA).toBe(true);
@ -27,7 +29,9 @@ it("Z used, inner graph can not determine const usage", () => {
});
it("Pure super expression should be unused, another used", () => {
expect(exportsInfoForMixin1).toBe(false);
if (process.env.NODE_ENV === "production") {
expect(exportsInfoForMixin1).toBe(false);
}
expect(exportsInfoForMixin2).toBe(true);
expect(exportsInfoForMixin3).toBe(true);

View File

@ -25,20 +25,24 @@ it("A should be used", () => {
expect(exprA).toBe(true);
});
it("B should not be used", () => {
expect(declB).toBe(false);
expect(exprB).toBe(false);
});
if (process.env.NODE_ENV === "production") {
it("B should not be used", () => {
expect(declB).toBe(false);
expect(exprB).toBe(false);
});
}
it("C should be used", () => {
expect(declC).toBe(true);
expect(exprC).toBe(true);
});
it("D should not be used", () => {
expect(declD).toBe(false);
expect(exprD).toBe(false);
});
if (process.env.NODE_ENV === "production") {
it("D should not be used", () => {
expect(declD).toBe(false);
expect(exprD).toBe(false);
});
}
it("E should be used", () => {
expect(declE).toBe(true);

View File

@ -1,15 +1,17 @@
import {exportDefaultUsed as export1} from "./package1/script";
import {exportDefaultUsed as export2} from "./package1/script2";
import {exportDefaultUsed as export3} from "./package2/script";
import { exportDefaultUsed as export1 } from "./package1/script";
import { exportDefaultUsed as export2 } from "./package1/script2";
import { exportDefaultUsed as export3 } from "./package2/script";
it("should load module correctly", () => {
require('./module');
require("./module");
});
it("default export should be unused", () => {
expect(export1).toBe(false);
expect(export2).toBe(false);
});
if (process.env.NODE_ENV === "production") {
it("default export should be unused", () => {
expect(export1).toBe(false);
expect(export2).toBe(false);
});
}
it("default export should be used", () => {
expect(export3).toBe(true);

View File

@ -12,11 +12,13 @@ it("export should be unused when only unused functions use it", () => {
f1();
expect(pureUsed).toBe(42);
expect(fWithDefault()).toBe(42);
expect(exportUsed).toBe(false);
expect(export2Used).toBe(true);
expect(export3Used).toBe(true);
expect(export4Used).toBe(true);
expect(export5Used).toBe(true);
expect(export6Used).toBe(true);
if (process.env.NODE_ENV === "production") {
expect(exportUsed).toBe(false);
expect(export2Used).toBe(true);
expect(export3Used).toBe(true);
expect(export4Used).toBe(true);
expect(export5Used).toBe(true);
expect(export6Used).toBe(true);
}
return import("./chunk");
});

View File

@ -32,21 +32,34 @@ it("should be able to call a deep function in commonjs", () => {
it("should report consistent exports info", () => {
const x1 = counter.exportsInfo;
expect(x1.incrementInfo).toBe(true);
expect(x1.counterInfo).toBe(true);
expect(x1.resetInfo).toBe(true);
expect(x1.unusedExport).toBe(false);
expect(x1.unusedExportInfo).toBe(false);
expect(x1.somethingElse).toBe(false);
expect(x1.somethingElseInfo).toBe(false);
if (process.env.NODE_ENV === "production") {
expect(x1.incrementInfo).toBe(true);
expect(x1.counterInfo).toBe(true);
expect(x1.resetInfo).toBe(true);
expect(x1.unusedExport).toBe(false);
expect(x1.unusedExportInfo).toBe(false);
expect(x1.somethingElse).toBe(false);
expect(x1.somethingElseInfo).toBe(false);
expect(C.exportsInfo.nsInfo).toBe(true);
expect(C.exportsInfo.ns2).toBe(false);
expect(C.exportsInfo.ns2Info).toBe(false);
} else if (process.env.NODE_ENV === "development") {
expect(x1.incrementInfo).toBe(undefined);
expect(x1.counterInfo).toBe(undefined);
expect(x1.resetInfo).toBe(undefined);
expect(x1.unusedExport).toBe(true);
expect(x1.unusedExportInfo).toBe(undefined);
expect(x1.somethingElse).toBe(true);
expect(x1.somethingElseInfo).toBe(undefined);
expect(C.exportsInfo.nsInfo).toBe(undefined);
expect(C.exportsInfo.ns2).toBe(true);
expect(C.exportsInfo.ns2Info).toBe(undefined);
}
expect(x1.increment).toBe(true);
expect(x1.counter).toBe(true);
expect(x1.reset).toBe(true);
expect(x1.incrementProvideInfo).toBe(true);
expect(x1.somethingElseProvideInfo).toBe(false);
expect(C.exportsInfo.nsInfo).toBe(true);
expect(C.exportsInfo.ns2).toBe(false);
expect(C.exportsInfo.ns2Info).toBe(false);
expect(C.exportsInfo.increment).toBe(x1.increment);
expect(C.exportsInfo.counter).toBe(x1.counter);
expect(C.exportsInfo.reset).toBe(x1.reset);

View File

@ -1,31 +1,37 @@
"use strict";
import { x, y } from "./a";
import {d2, usedD1, usedD2} from "./d.js";
import {b1, usedB1, usedB2, usedB3, usedB4} from "./b.js";
import {usedE1, usedE2} from "./e.js";
import {h} from "./h.js";
import { d2, usedD1, usedD2 } from "./d.js";
import { b1, usedB1, usedB2, usedB3, usedB4 } from "./b.js";
import { usedE1, usedE2 } from "./e.js";
import { h } from "./h.js";
it("namespace export as from commonjs should override named export", function() {
it("namespace export as from commonjs should override named export", function () {
expect(x).toBe(1);
expect(y).toBe(3);
});
it("named namespace export should work correctly", function () {
expect(d2).toBe(2);
expect(usedD1).toBe(false);
if (process.env.NODE_ENV === "production") {
expect(usedD1).toBe(false);
}
expect(usedD2).toBe(true);
expect(b1.d2).toBe(2);
expect(usedB1).toBe(true);
expect(usedB2).toBe(false);
expect(usedB3).toBe(false);
expect(usedB4).toBe(false);
if (process.env.NODE_ENV === "production") {
expect(usedB2).toBe(false);
expect(usedB3).toBe(false);
expect(usedB4).toBe(false);
}
});
it("complex case should work correctly", () => {
expect(h.f1.e.e1).toBe(10);
expect(h.g1.e1).toBe(10);
expect(usedE1).toBe(true);
expect(usedE2).toBe(false);
if (process.env.NODE_ENV === "production") {
expect(usedE2).toBe(false);
}
});

View File

@ -1,2 +1,2 @@
export * from "./empty";
export const valueUsed = __webpack_exports_info__.value.useInfo;
export const valueUsed = __webpack_exports_info__.value.used;

View File

@ -0,0 +1,13 @@
import { ghi } from "./subject";
import value from "./module";
it("should not invalidate subject in unrelated locations", done => {
expect(ghi).toBe(42);
expect(value).toBe(40);
import.meta.webpackHot.accept("./module", () => {
expect(ghi).toBe(42);
expect(value).toBe(41);
done();
});
NEXT(require("../../update")(done));
});

View File

@ -0,0 +1,3 @@
export { abc as default } from "./subject";
---
export { def as default } from "./subject";

View File

@ -0,0 +1,3 @@
export const abc = 40;
export const def = 41;
export const ghi = 42;