Skip to content

Commit 2741098

Browse files
TheLarkInnsokra
authored andcommitted
feat(perfbudget): creat initialAssetsCost with hardcoded limit
1 parent e949aa1 commit 2741098

4 files changed

Lines changed: 128 additions & 77 deletions

File tree

lib/Compilation.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Author Tobias Koppers @sokra
44
*/
55
var async = require("async");
6+
var path = require("path");
67

78
var Tapable = require("tapable");
89
var EntryModuleNotFoundError = require("./EntryModuleNotFoundError");
@@ -1030,3 +1031,95 @@ Compilation.prototype.checkConstraints = function() {
10301031
chunk.checkConstraints();
10311032
}.bind(this));
10321033
};
1034+
1035+
Compilation.prototype.getAssetsByChunks = function() {
1036+
var webpackStatsJson = this.getStats().toJson();
1037+
var chunks = getFilteredChunks(webpackStatsJson);
1038+
1039+
function getFilteredChunks(webpackStatsJson) {
1040+
return webpackStatsJson.chunks.filter(function(chunk) {
1041+
var chunkName = chunk.names[0];
1042+
// This chunk doesn't have a name. This script can't handled it.
1043+
if (chunkName === undefined) {
1044+
return false;
1045+
}
1046+
// Skip if the chunk should be lazy loaded
1047+
if (!chunk.initial) {
1048+
return false;
1049+
}
1050+
1051+
// Add otherwise
1052+
return true;
1053+
});
1054+
};
1055+
1056+
var assets = {
1057+
// Will contain all js & css files by chunk
1058+
chunks: {},
1059+
// Will contain all js files
1060+
js: [],
1061+
// Will contain all css files
1062+
css: [],
1063+
// Will contain the html5 appcache manifest files if it exists
1064+
manifest: Object.keys(this.assets).filter(function(assetFile) {
1065+
return path.extname(assetFile) === '.appcache';
1066+
})[0]
1067+
};
1068+
1069+
// Append a hash for cache busting
1070+
for(var i = 0; i < chunks.length; i++) {
1071+
var chunk = chunks[i];
1072+
1073+
debugger;
1074+
1075+
var chunkName = chunk.names && chunk.names[0] || "";
1076+
1077+
assets.chunks[chunkName] = {};
1078+
1079+
// Prepend the public path to all chunk files
1080+
var chunkFiles = [].concat(chunk.files).map(function(chunkFile) {
1081+
return chunkFile;
1082+
});
1083+
1084+
// Webpack outputs an array for each chunk when using sourcemaps
1085+
// But we need only the entry file
1086+
1087+
var entry = chunkFiles[0];
1088+
assets.chunks[chunkName].size = chunk.size;
1089+
assets.chunks[chunkName].entry = entry;
1090+
assets.chunks[chunkName].hash = chunk.hash;
1091+
assets.js.push(entry);
1092+
1093+
// Gather all css files
1094+
var css = chunkFiles.filter(function(chunkFile) {
1095+
// Some chunks may contain content hash in their names, for ex. 'main.css?1e7cac4e4d8b52fd5ccd2541146ef03f'.
1096+
// We must proper handle such cases, so we use regexp testing here
1097+
return /.css($|\?)/.test(chunkFile);
1098+
});
1099+
assets.chunks[chunkName].css = css;
1100+
assets.css = assets.css.concat(css);
1101+
}
1102+
1103+
// Duplicate css assets can occur on occasion if more than one chunk
1104+
// requires the same css.
1105+
1106+
assets.css = uniques(assets.css);
1107+
1108+
return assets;
1109+
};
1110+
1111+
// TODO# Find better module or make more reusable
1112+
function uniques(array) {
1113+
var result = [],
1114+
val, ridx;
1115+
outer:
1116+
for(var i = 0, length = array.length; i < length; i++) {
1117+
val = array[i];
1118+
ridx = result.length;
1119+
while(ridx--) {
1120+
if(val === result[ridx]) continue outer;
1121+
}
1122+
result.push(val);
1123+
}
1124+
return result;
1125+
}

lib/Stats.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,6 @@ Stats.prototype.toJson = function toJson(options, forToString) {
325325
});
326326
}
327327

328-
debugger;
329-
330328
if(showPerformance && compilation.compiler.options.target === "web") {
331329
obj.performance = compilation.compiler.options.performance;
332330
}
@@ -487,6 +485,7 @@ Stats.jsonToString = function jsonToString(obj, useColors) {
487485
colors.bold(obj.publicPath);
488486
newline();
489487
}
488+
490489
if(obj.assets && obj.assets.length > 0) {
491490
var t = [
492491
["Asset", "Size", "Chunks", "", "Chunk Names"]

lib/performance/EmittedAssetSizeLimitPlugin.js

Lines changed: 31 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,30 @@ function EmittedAssetSizeLimitPlugin(performanceOptions) {
1111

1212
module.exports = EmittedAssetSizeLimitPlugin;
1313

14-
function uniques(array) {
15-
var result = [],
16-
val, ridx;
17-
outer:
18-
for(var i = 0, length = array.length; i < length; i++) {
19-
val = array[i];
20-
ridx = result.length;
21-
while(ridx--) {
22-
if(val === result[ridx]) continue outer;
23-
}
24-
result.push(val);
25-
}
26-
return result;
27-
}
28-
2914
function normalizeAndCompare(sizeLimit, assetSize) {
3015
// sizeLimit=maxAssetSize is always expressed in kB
3116
// assetSize is expressed in byte size
32-
sizeLimit = sizeLimit * 1024;
17+
sizeLimit *= 1024;
3318
return sizeLimit < assetSize;
3419
}
3520

21+
function doesExceedInitialLimit(initialLimit, actualInitialSize) {
22+
23+
initialLimit *= 1024;
24+
return initialLimit < actualInitialSize;
25+
}
26+
3627
function getJSWarnings(noOfAssets, sizeLimit, assetSize) {
3728
var warnings = [];
29+
3830
if(normalizeAndCompare(sizeLimit, assetSize)) {
3931
if(noOfAssets === 1) {
4032
warnings.push(new Error("EmmittedAssetSizeWarning: " + "This asset exceeds " + sizeLimit + "kB. Consider reducing the size for optimal web performance."));
4133
} else {
4234
warnings.push(new Error("EmmittedAssetSizeWarning: " + "Highlighted chunks are large and are likely to impact web performance. Consider keeping total chunks of page < " + sizeLimit + "kB"));
4335
}
4436
}
37+
4538
return warnings;
4639
}
4740

@@ -56,72 +49,36 @@ EmittedAssetSizeLimitPlugin.prototype.apply = function(compiler) {
5649
var jsRegex = /\.js($|\?)/i;
5750

5851
compiler.plugin("after-emit", function(compilation, callback) {
59-
console.log("Plugin Init");
52+
debugger;
6053
var assets = Object.keys(compilation.assets);
6154
var noOfAssets = assets.length;
55+
var warnings = null;
56+
var initialLimit = 300;
57+
var totalInitialCost = 0;
58+
6259
assets.forEach(function(file) {
6360
var assetSize = compilation.assets[file].size();
64-
var warnings = jsRegex.test(file) && getJSWarnings(noOfAssets, sizeLimit, assetSize);
65-
if(warnings.length > 0) {
66-
Array.prototype.push.apply(compilation.warnings, warnings);
67-
}
68-
});
69-
callback();
70-
});
61+
var assetsByChunks = compilation.getAssetsByChunks().chunks;
7162

72-
};
63+
for(var chunkKey in assetsByChunks) {
64+
var chunk = assetsByChunks[chunkKey];
7365

74-
//TODO# This should probably be moved to compilation
75-
EmittedAssetSizeLimitPlugin.prototype.getAssets = function(compilation, chunks) {
76-
var self = this;
77-
var webpackStatsJson = compilation.getStats().toJson();
78-
79-
var assets = {
80-
// Will contain all js & css files by chunk
81-
chunks: {},
82-
// Will contain all js files
83-
js: [],
84-
// Will contain all css files
85-
css: [],
86-
// Will contain the html5 appcache manifest files if it exists
87-
manifest: Object.keys(compilation.assets).filter(function(assetFile) {
88-
return path.extname(assetFile) === '.appcache';
89-
})[0]
90-
};
91-
92-
// Append a hash for cache busting
93-
for(var i = 0; i < chunks.length; i++) {
94-
var chunk = chunks[i];
95-
var chunkName = chunk.names[0];
96-
97-
assets.chunks[chunkName] = {};
98-
99-
// Prepend the public path to all chunk files
100-
var chunkFiles = [].concat(chunk.files).map(function(chunkFile) {
101-
return chunkFile;
102-
});
66+
totalInitialCost += chunk.size;
67+
}
10368

104-
// Webpack outputs an array for each chunk when using sourcemaps
105-
// But we need only the entry file
106-
var entry = chunkFiles[0];
107-
assets.chunks[chunkName].size = chunk.size;
108-
assets.chunks[chunkName].entry = entry;
109-
assets.chunks[chunkName].hash = chunk.hash;
110-
assets.js.push(entry);
111-
112-
// Gather all css files
113-
var css = chunkFiles.filter(function(chunkFile) {
114-
// Some chunks may contain content hash in their names, for ex. 'main.css?1e7cac4e4d8b52fd5ccd2541146ef03f'.
115-
// We must proper handle such cases, so we use regexp testing here
116-
return /.css($|\?)/.test(chunkFile);
69+
warnings = jsRegex.test(file) && getJSWarnings(noOfAssets, sizeLimit, assetSize, initialLimit, totalInitialCost);
11770
});
118-
assets.chunks[chunkName].css = css;
119-
assets.css = assets.css.concat(css);
120-
}
12171

122-
// Duplicate css assets can occur on occasion if more than one chunk
123-
// requires the same css.
124-
assets.css = uniques(assets.css);
72+
if(doesExceedInitialLimit(initialLimit, totalInitialCost)) {
73+
//TODO# Maybe separate warning name
74+
warnings.push(new Error("EmittedAssetSizeWarning: " + "The total initial download cost for these assets are likey to impact web performance. Consider keeping the total size of your initial assets < " + initialLimit + "kB"));
75+
}
76+
77+
if(warnings.length > 0) {
78+
Array.prototype.push.apply(compilation.warnings, warnings);
79+
}
80+
81+
callback();
82+
});
12583

126-
return assets;
12784
};

test/statsCases/preset-normal-performance/actual.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ chunk {<CLR=33,BOLD>3</CLR>} <CLR=32,BOLD>main.js</CLR> (main) 413 kB<CLR=33,
1919
[3] <CLR=BOLD>(webpack)/test/statsCases/preset-normal-performance/a.js</CLR> 22 bytes {<CLR=33,BOLD>3</CLR>}<CLR=32,BOLD> [built]</CLR>
2020
[8] <CLR=BOLD>(webpack)/test/statsCases/preset-normal-performance/index.js</CLR> 93 bytes {<CLR=33,BOLD>3</CLR>}<CLR=32,BOLD> [built]</CLR>
2121

22-
<CLR=33,BOLD>WARNING in EmmittedAssetSizeWarning: Highlighted chunks are large and are likely to impact web performance. Consider keeping total chunks of page < 250kB</CLR>
22+
<CLR=33,BOLD>WARNING in EmmittedAssetSizeWarning: Highlighted chunks are large and are likely to impact web performance. Consider keeping total chunks of page < 250kB</CLR>
23+
24+
<CLR=33,BOLD>WARNING in EmittedAssetSizeWarning: The total initial download cost for these assets are likey to impact web performance. Consider keeping the total size of your initial assets < 300kB</CLR>

0 commit comments

Comments
 (0)