Merge branch 'master' into feature/main-template-type-support

This commit is contained in:
Tobias Koppers 2018-04-30 09:23:54 +02:00 committed by GitHub
commit 4d614981b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 733 additions and 560 deletions

9
SECURITY.md Normal file
View File

@ -0,0 +1,9 @@
# Reporting Security Issues
If you discover a security issue in webpack, please report it by sending an
email to [webpack@opencollective.com](mailto:webpack@opencollective.com).
This will allow us to assess the risk, and make a fix available before we add a
bug report to the GitHub repository.
Thanks for helping make webpack safe for everyone.

26
declarations.d.ts vendored
View File

@ -9,25 +9,23 @@ declare namespace NodeJS {
}
// There are no typings for chrome-trace-event
declare module 'chrome-trace-event' {
declare module "chrome-trace-event" {
interface Event {
name: string
id?: number
cat: string[]
args?: Object
name: string;
id?: number;
cat: string[];
args?: Object;
}
export class Tracer {
constructor(options: {
noStream: boolean
})
pipe(stream: NodeJS.WritableStream) : void
instantEvent(event: Event) : void
counter: number
constructor(options: { noStream: boolean });
pipe(stream: NodeJS.WritableStream): void;
instantEvent(event: Event): void;
counter: number;
trace: {
begin(event: Event) : void
end(event: Event) : void
}
begin(event: Event): void;
end(event: Event): void;
};
}
}

View File

@ -100,7 +100,9 @@ class Stats {
const optionOrLocalFallback = (v, def) =>
typeof v !== "undefined"
? v
: typeof options.all !== "undefined" ? options.all : def;
: typeof options.all !== "undefined"
? options.all
: def;
const testAgainstGivenOption = item => {
if (typeof item === "string") {
@ -135,6 +137,10 @@ class Stats {
const showBuiltAt = optionOrLocalFallback(options.builtAt, true);
const showAssets = optionOrLocalFallback(options.assets, true);
const showEntrypoints = optionOrLocalFallback(options.entrypoints, true);
const showChunkGroups = optionOrLocalFallback(
options.chunkGroups,
!forToString
);
const showChunks = optionOrLocalFallback(options.chunks, !forToString);
const showChunkModules = optionOrLocalFallback(options.chunkModules, true);
const showChunkOrigins = optionOrLocalFallback(
@ -262,7 +268,9 @@ class Stats {
text += `chunk ${e.chunk.name || e.chunk.id}${
e.chunk.hasRuntime()
? " [entry]"
: e.chunk.canBeInitial() ? " [initial]" : ""
: e.chunk.canBeInitial()
? " [initial]"
: ""
}\n`;
}
if (e.file) {
@ -396,15 +404,15 @@ class Stats {
obj.assets.sort(sortByField(sortAssets));
}
if (showEntrypoints) {
obj.entrypoints = {};
for (const keyValuePair of compilation.entrypoints) {
const fnChunkGroup = groupMap => {
const obj = {};
for (const keyValuePair of groupMap) {
const name = keyValuePair[0];
const ep = keyValuePair[1];
const children = ep.getChildrenByOrders();
obj.entrypoints[name] = {
chunks: ep.chunks.map(c => c.id),
assets: ep.chunks.reduce(
const cg = keyValuePair[1];
const children = cg.getChildrenByOrders();
obj[name] = {
chunks: cg.chunks.map(c => c.id),
assets: cg.chunks.reduce(
(array, c) => array.concat(c.files || []),
[]
),
@ -436,9 +444,19 @@ class Stats {
}, Object.create(null))
};
if (showPerformance) {
obj.entrypoints[name].isOverSizeLimit = ep.isOverSizeLimit;
obj[name].isOverSizeLimit = cg.isOverSizeLimit;
}
}
return obj;
};
if (showEntrypoints) {
obj.entrypoints = fnChunkGroup(compilation.entrypoints);
}
if (showChunkGroups) {
obj.namedChunkGroups = fnChunkGroup(compilation.namedChunkGroups);
}
const fnModule = module => {
@ -866,22 +884,23 @@ class Stats {
colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset");
newline();
}
if (obj.entrypoints) {
for (const name of Object.keys(obj.entrypoints)) {
const ep = obj.entrypoints[name];
colors.normal("Entrypoint ");
const processChunkGroups = (namedGroups, prefix) => {
for (const name of Object.keys(namedGroups)) {
const cg = namedGroups[name];
colors.normal(`${prefix} `);
colors.bold(name);
if (ep.isOverSizeLimit) {
if (cg.isOverSizeLimit) {
colors.normal(" ");
colors.yellow("[big]");
}
colors.normal(" =");
for (const asset of ep.assets) {
for (const asset of cg.assets) {
colors.normal(" ");
colors.green(asset);
}
for (const name of Object.keys(ep.childAssets)) {
const assets = ep.childAssets[name];
for (const name of Object.keys(cg.childAssets)) {
const assets = cg.childAssets[name];
if (assets && assets.length > 0) {
colors.normal(" ");
colors.magenta(`(${name}:`);
@ -894,7 +913,25 @@ class Stats {
}
newline();
}
};
if (obj.entrypoints) {
processChunkGroups(obj.entrypoints, "Entrypoint");
}
if (obj.namedChunkGroups) {
let outputChunkGroups = obj.namedChunkGroups;
if (obj.entrypoints) {
outputChunkGroups = Object.keys(outputChunkGroups)
.filter(name => !obj.entrypoints[name])
.reduce((result, name) => {
result[name] = obj.namedChunkGroups[name];
return result;
}, {});
}
processChunkGroups(outputChunkGroups, "Chunk Group");
}
const modulesByIdentifier = {};
if (obj.modules) {
for (const module of obj.modules) {
@ -1260,6 +1297,7 @@ class Stats {
case "verbose":
return {
entrypoints: true,
chunkGroups: true,
modules: false,
chunks: true,
chunkModules: true,
@ -1278,6 +1316,7 @@ class Stats {
case "detailed":
return {
entrypoints: true,
chunkGroups: true,
chunks: true,
chunkModules: false,
chunkOrigins: true,

View File

@ -235,7 +235,9 @@ class WebpackOptionsApply extends OptionsApply {
"MappingURL=[url]\n*/"
: legacy
? "\n/*\n//@ source" + "MappingURL=[url]\n*/"
: modern ? "\n//# source" + "MappingURL=[url]" : null;
: modern
? "\n//# source" + "MappingURL=[url]"
: null;
let Plugin = evalWrapped
? EvalSourceMapDevToolPlugin
: SourceMapDevToolPlugin;
@ -259,7 +261,9 @@ class WebpackOptionsApply extends OptionsApply {
? "\n//@ sourceURL=[url]\n//# sourceURL=[url]"
: legacy
? "\n//@ sourceURL=[url]"
: modern ? "\n//# sourceURL=[url]" : null;
: modern
? "\n//# sourceURL=[url]"
: null;
new EvalDevToolModulePlugin({
sourceUrlComment: comment,
moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,

View File

@ -33,6 +33,23 @@ class ImportParserPlugin {
const importOptions = parser.getCommentOptions(expr.range);
if (importOptions) {
if (typeof importOptions.webpackIgnore !== "undefined") {
if (typeof importOptions.webpackIgnore !== "boolean") {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackIgnore\` expected a boolean, but received: ${
importOptions.webpackIgnore
}.`
)
);
} else {
// Do not instrument `import()` is `webpackIgnore` is `true`
if (importOptions.webpackIgnore) {
return false;
}
}
}
if (typeof importOptions.webpackChunkName !== "undefined") {
if (typeof importOptions.webpackChunkName !== "string") {
parser.state.module.warnings.push(

View File

@ -291,11 +291,15 @@ module.exports = class SplitChunksPlugin {
minSize:
cacheGroupSource.minSize !== undefined
? cacheGroupSource.minSize
: cacheGroupSource.enforce ? 0 : this.options.minSize,
: cacheGroupSource.enforce
? 0
: this.options.minSize,
minChunks:
cacheGroupSource.minChunks !== undefined
? cacheGroupSource.minChunks
: cacheGroupSource.enforce ? 1 : this.options.minChunks,
: cacheGroupSource.enforce
? 1
: this.options.minChunks,
maxAsyncRequests:
cacheGroupSource.maxAsyncRequests !== undefined
? cacheGroupSource.maxAsyncRequests

View File

@ -88,7 +88,8 @@
"buildin/",
"hot/",
"web_modules/",
"schemas/"
"schemas/",
"SECURITY.md"
],
"scripts": {
"setup": "node ./setup/setup.js",

View File

@ -1853,6 +1853,10 @@
"type": "boolean",
"description": "Display the entry points with the corresponding bundles"
},
"chunkGroups": {
"type": "boolean",
"description": "Display all chunk groups with the corresponding bundles"
},
"errorDetails": {
"type": "boolean",
"description": "add details to errors (like resolving log)"

View File

@ -8,9 +8,8 @@ const Chunk = require("../lib/Chunk");
describe("Chunk", () => {
let ChunkInstance;
beforeEach(
() => (ChunkInstance = new Chunk("chunk-test", "module-test", "loc-test"))
);
beforeEach(() =>
(ChunkInstance = new Chunk("chunk-test", "module-test", "loc-test")));
it("should have debugId more than 999", () =>
should(ChunkInstance.debugId).be.above(999));

View File

@ -33,9 +33,8 @@ describe("NullDependency", () => {
it("is a function", () => NullDependency.Template.should.be.a.Function());
describe("when created", () => {
beforeEach(
() => (env.nullDependencyTemplate = new NullDependency.Template())
);
beforeEach(() =>
(env.nullDependencyTemplate = new NullDependency.Template()));
it("has apply function", () =>
env.nullDependencyTemplate.apply.should.be.Function());

View File

@ -11,32 +11,28 @@ describe("SourceMapDevToolModuleOptionsPlugin", () => {
beforeEach(() => (eventBindings = undefined));
describe("with module false and line-to-line false", () => {
beforeEach(
() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: false,
lineToLine: false
}
))
);
beforeEach(() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: false,
lineToLine: false
}
)));
it("does not bind any event handlers", () =>
eventBindings.length.should.be.exactly(0));
});
describe("with module true", () => {
beforeEach(
() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: true,
lineToLine: false
}
))
);
beforeEach(() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: true,
lineToLine: false
}
)));
it("binds one event handler", () =>
eventBindings.length.should.be.exactly(1));
@ -56,16 +52,14 @@ describe("SourceMapDevToolModuleOptionsPlugin", () => {
});
describe("with line-to-line true", () => {
beforeEach(
() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: false,
lineToLine: true
}
))
);
beforeEach(() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: false,
lineToLine: true
}
)));
it("binds one event handler", () =>
eventBindings.length.should.be.exactly(1));
@ -85,16 +79,14 @@ describe("SourceMapDevToolModuleOptionsPlugin", () => {
});
describe("with line-to-line object", () => {
beforeEach(
() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: false,
lineToLine: {}
}
))
);
beforeEach(() =>
(eventBindings = applyPluginWithOptions(
SourceMapDevToolModuleOptionsPlugin,
{
module: false,
lineToLine: {}
}
)));
it("binds one event handler", () =>
eventBindings.length.should.be.exactly(1));

View File

@ -116,6 +116,7 @@ describe(
warnings: [],
assets: [],
entrypoints: new Map(),
namedChunkGroups: new Map(),
chunks: [],
modules: [],
children: [],
@ -142,6 +143,7 @@ describe(
assets: [],
entrypoints: new Map(),
chunks: [],
namedChunkGroups: new Map(),
modules: [],
children: [],
hash: "1234",
@ -162,6 +164,7 @@ describe(
children: [],
chunks: [],
entrypoints: {},
namedChunkGroups: {},
filteredAssets: 0,
filteredModules: 0,
errors: [],

View File

@ -0,0 +1,9 @@
const fs = require("fs");
const path = require("path");
const should = require("should");
it("should be able to ignore import()", () => {
const source = fs.readFileSync(path.join(__dirname, "bundle1.js"), "utf-8");
should(source).containEql(`import(/* webpackIgnore: true */ "./other2.js")`);
should(source).not.containEql(`import(/* webpackIgnore: false */ "./other3.js")`);
});

View File

@ -0,0 +1,2 @@
import(/* webpackIgnore: true */ "./other2.js");
import(/* webpackIgnore: false */ "./other3.js");

View File

@ -0,0 +1 @@
export default "other2";

View File

@ -0,0 +1 @@
export default "other3";

View File

@ -0,0 +1,12 @@
module.exports = {
entry: {
bundle0: "./index.js",
bundle1: "./other.js"
},
output: {
filename: "[name].js"
},
node: {
__dirname: false
}
};

View File

@ -0,0 +1,3 @@
import "./shared";
export default "a";

View File

@ -0,0 +1,3 @@
import "./shared";
export default "b";

View File

@ -0,0 +1,4 @@
import "x";
import "y";
export default "c";

View File

@ -0,0 +1,50 @@
Child
Chunk Group main = main.js
Chunk Group async-a = async-a~async-b.js async-a.js
Chunk Group async-b = async-a~async-b.js async-b.js
Chunk Group async-c = vendors.js async-c.js
chunk {0} async-a~async-b.js (async-a~async-b) 133 bytes <{5}> ={1}= ={2}= [rendered] split chunk (cache group: default) (name: async-a~async-b)
> ./a [6] ./index.js 1:0-47
> ./b [6] ./index.js 2:0-47
[0] ./shared.js 133 bytes {0} [built]
chunk {1} async-a.js (async-a) 40 bytes <{5}> ={0}= [rendered]
> ./a [6] ./index.js 1:0-47
[3] ./a.js 40 bytes {1} [built]
chunk {2} async-b.js (async-b) 40 bytes <{5}> ={0}= [rendered]
> ./b [6] ./index.js 2:0-47
[4] ./b.js 40 bytes {2} [built]
chunk {3} async-c.js (async-c) 45 bytes <{5}> ={4}= [rendered]
> ./c [6] ./index.js 3:0-47
[5] ./c.js 45 bytes {3} [built]
chunk {4} vendors.js (vendors) 40 bytes <{5}> ={3}= [rendered] split chunk (cache group: vendors) (name: vendors)
> ./c [6] ./index.js 3:0-47
[1] ./node_modules/x.js 20 bytes {4} [built]
[2] ./node_modules/y.js 20 bytes {4} [built]
chunk {5} main.js (main) 146 bytes >{0}< >{1}< >{2}< >{3}< >{4}< [entry] [rendered]
> ./ main
[6] ./index.js 146 bytes {5} [built]
Child
Entrypoint main = main.js
Chunk Group async-a = async-a~async-b.js async-a.js
Chunk Group async-b = async-a~async-b.js async-b.js
Chunk Group async-c = vendors.js async-c.js
chunk {0} async-a~async-b.js (async-a~async-b) 133 bytes <{5}> ={1}= ={2}= [rendered] split chunk (cache group: default) (name: async-a~async-b)
> ./a [6] ./index.js 1:0-47
> ./b [6] ./index.js 2:0-47
[0] ./shared.js 133 bytes {0} [built]
chunk {1} async-a.js (async-a) 40 bytes <{5}> ={0}= [rendered]
> ./a [6] ./index.js 1:0-47
[3] ./a.js 40 bytes {1} [built]
chunk {2} async-b.js (async-b) 40 bytes <{5}> ={0}= [rendered]
> ./b [6] ./index.js 2:0-47
[4] ./b.js 40 bytes {2} [built]
chunk {3} async-c.js (async-c) 45 bytes <{5}> ={4}= [rendered]
> ./c [6] ./index.js 3:0-47
[5] ./c.js 45 bytes {3} [built]
chunk {4} vendors.js (vendors) 40 bytes <{5}> ={3}= [rendered] split chunk (cache group: vendors) (name: vendors)
> ./c [6] ./index.js 3:0-47
[1] ./node_modules/x.js 20 bytes {4} [built]
[2] ./node_modules/y.js 20 bytes {4} [built]
chunk {5} main.js (main) 146 bytes >{0}< >{1}< >{2}< >{3}< >{4}< [entry] [rendered]
> ./ main
[6] ./index.js 146 bytes {5} [built]

View File

@ -0,0 +1,3 @@
import(/* webpackChunkName: "async-a" */ "./a");
import(/* webpackChunkName: "async-b" */ "./b");
import(/* webpackChunkName: "async-c" */ "./c");

1
test/statsCases/named-chunk-groups/node_modules/x.js generated vendored Normal file
View File

@ -0,0 +1 @@
export default "x";

1
test/statsCases/named-chunk-groups/node_modules/y.js generated vendored Normal file
View File

@ -0,0 +1 @@
export default "y";

View File

@ -0,0 +1,2 @@
// content content content content content content content content
// content content content content content content content content

View File

@ -0,0 +1,47 @@
const stats = {
hash: false,
timings: false,
builtAt: false,
assets: false,
chunks: true,
chunkOrigins: true,
modules: false
};
const config = {
mode: "production",
entry: {
main: "./"
},
output: {
filename: "[name].js"
},
optimization: {
splitChunks: {
minSize: 100,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
chunks: "async",
enforce: true,
name: "vendors"
}
}
}
}
};
module.exports = [
Object.assign(
{
stats: Object.assign({ entrypoints: false, chunkGroups: true }, stats)
},
config
),
Object.assign(
{
stats: Object.assign({ entrypoints: true, chunkGroups: true }, stats)
},
config
)
];

917
yarn.lock

File diff suppressed because it is too large Load Diff