nice output

This commit is contained in:
Tobias Koppers 2012-03-15 00:05:29 +01:00
parent 0bc303cbf3
commit 6d1a7a77d6
6 changed files with 122 additions and 40 deletions

View File

@ -6,6 +6,8 @@
*/
var path = require("path");
var fs = require("fs");
var util = require("util");
var sprintf = require("sprintf").sprintf;
var argv = require("optimist")
.usage("Usage: $0 <input> <output>")
@ -34,6 +36,10 @@ var argv = require("optimist")
.describe("colors", "Output Stats with colors")
.default("colors", false)
.boolean("json")
.describe("json", "Output Stats as JSON")
.default("json", false)
.demand(1)
.argv;
@ -96,6 +102,47 @@ if(argv.single) {
console.error(err);
return;
}
console.log(require("util").inspect(stats, false, 10, argv.colors));
if(argv.json)
console.log(util.inspect(stats, false, 10, argv.colors));
else {
console.log("Chunks: \033[1m" + stats.chunkCount + "\033[22m");
console.log("Modules: \033[1m" + stats.modulesCount + "\033[22m");
console.log("Modules including duplicates: \033[1m" + stats.modulesIncludingDuplicates + "\033[22m");
console.log("Modules pre chunk: \033[1m" + stats.modulesPerChunk + "\033[22m");
console.log("Modules first chunk: \033[1m" + stats.modulesFirstChunk + "\033[22m");
if(stats.fileSizes)
for(var file in stats.fileSizes) {
console.log("\033[1m" + sprintf("%" + (5 + options.output.length) + "s", file) + "\033[22m: \033[1m" + sprintf("%8d", stats.fileSizes[file]) + "\033[22m characters");
};
if(stats.fileModules) {
for(var file in stats.fileModules) {
console.log("\033[1m\033[32m" + file + "\033[39m\033[22m");
var modules = stats.fileModules[file];
modules.forEach(function(module) {
console.log(" \033[1m" + sprintf("%3s", module.id+"") + " " + (module.filename || (module.dirname && ("generated " + module.dirname)) || "generated") + "\033[22m");
module.reasons.forEach(function(reason) {
switch(reason.type) {
case "require":
console.log(" \033[36mrequire (" + reason.count + "x) from " + reason.filename + "\033[39m");
break;
case "context":
console.log(" \033[90mcontext from " + reason.filename + "\033[39m");
break;
case "ensure":
console.log(" \033[35mensure from " + reason.filename + "\033[39m");
break;
default:
console.log(" \033[31m" + reason.type + "\033[39m");
}
});
});
}
}
if(stats.warnings) {
stats.warnings.forEach(function(warning) {
console.log("\033[1m\033[33mWARNING: " + warning + "\033[39m\033[22m");
});
}
}
});
}

View File

@ -30,7 +30,7 @@ module.exports = function buildDeps(context, mainModule, options, callback) {
chunkModules: {} // used by checkObsolete
}
var mainModuleId;
addModule(depTree, context, mainModule, options, function(err, id) {
addModule(depTree, context, mainModule, options, {type: "main"}, function(err, id) {
if(err) {
callback(err);
return;
@ -45,11 +45,19 @@ module.exports = function buildDeps(context, mainModule, options, callback) {
removeChunkIfEmpty(depTree, depTree.chunks[chunkId]);
checkObsolete(depTree, depTree.chunks[chunkId]);
}
// cleanup
delete depTree.chunkModules;
depTree.modulesByFile = depTree.modules;
depTree.modules = depTree.modulesById;
delete depTree.modulesById;
delete depTree.nextModuleId;
delete depTree.nextChunkId;
// return
callback(null, depTree);
}
}
function addModule(depTree, context, module, options, callback) {
function addModule(depTree, context, module, options, reason, callback) {
if(context)
resolve(context, module, options.resolve, resolved);
else
@ -60,11 +68,13 @@ function addModule(depTree, context, module, options, callback) {
return;
}
if(depTree.modules[filename]) {
depTree.modules[filename].reasons.push(reason);
callback(null, depTree.modules[filename].id);
} else {
var module = depTree.modules[filename] = {
id: depTree.nextModuleId++,
filename: filename
filename: filename,
reasons: [reason]
};
depTree.modulesById[module.id] = module;
fs.readFile(filename, "utf-8", function(err, source) {
@ -113,7 +123,12 @@ function addModule(depTree, context, module, options, callback) {
var errors = [];
if(requiresNames.length)
requiresNames.forEach(function(moduleName) {
addModule(depTree, path.dirname(filename), moduleName, options, function(err, moduleId) {
var reason = {
type: "require",
count: requires[moduleName].length,
filename: filename
};
addModule(depTree, path.dirname(filename), moduleName, options, reason, function(err, moduleId) {
if(err) {
errors.push(err+"\n @ " + filename + " (line " + requires[moduleName][0].line + ", column " + requires[moduleName][0].column + ")");
} else {
@ -128,7 +143,11 @@ function addModule(depTree, context, module, options, callback) {
contexts.forEach(function(contextObj) {
var context = contextObj.context;
var module = contextObj.module;
addContextModule(depTree, path.dirname(filename), context.name, options, function(err, contextModuleId) {
var reason = {
type: "ensure",
filename: filename
};
addContextModule(depTree, path.dirname(filename), context.name, options, reason, function(err, contextModuleId) {
if(err) {
errors.push(err+"\n @ " + filename + " (line " + context.line + ", column " + context.column + ")");
} else {
@ -159,7 +178,7 @@ function addModule(depTree, context, module, options, callback) {
}
}
function addContextModule(depTree, context, contextModuleName, options, callback) {
function addContextModule(depTree, context, contextModuleName, options, reason, callback) {
resolve.context(context, contextModuleName, options.resolve, resolved);
function resolved(err, dirname) {
if(err) {
@ -167,13 +186,16 @@ function addContextModule(depTree, context, contextModuleName, options, callback
return;
}
if(depTree.modules[dirname]) {
depTree.modules[dirname].reasons.push(reason);
callback(null, depTree.modules[dirname].id);
} else {
var contextModule = depTree.modules[dirname] = {
name: contextModuleName,
dirname: dirname,
id: depTree.nextModuleId++,
requireMap: {},
requires: []
requires: [],
reasons: [reason]
};
depTree.modulesById[contextModule.id] = contextModule;
var extensions = (options.resolve && options.resolve.extensions) || [".web.js", ".js"];
@ -204,7 +226,10 @@ function addContextModule(depTree, context, contextModuleName, options, callback
endOne();
} else {
if(stat.isDirectory()) {
doDir(filename, moduleName + "/" + file, endOne);
if(file === "node_modules" || file === "web_modules")
endOne();
else
doDir(filename, moduleName + "/" + file, endOne);
} else {
var hasExt = false;
extensions.forEach(function(ext) {
@ -215,7 +240,11 @@ function addContextModule(depTree, context, contextModuleName, options, callback
endOne();
return;
}
addModule(depTree, null, filename, options, function(err, moduleId) {
var modulereason = {
type: "context",
filename: reason.filename
};
addModule(depTree, null, filename, options, modulereason, function(err, moduleId) {
if(err) {
endOne(err);
} else {
@ -240,7 +269,7 @@ function addContextModule(depTree, context, contextModuleName, options, callback
var extensionsAccess = [];
extensions.forEach(function(ext) {
extensionsAccess.push("||map[name+\"");
extensionsAccess.push(ext.replace(/"/g, "\\\""));
extensionsAccess.push(ext.replace(/\\/g, "\\\\").replace(/"/g, "\\\""));
extensionsAccess.push("\"]");
});

View File

@ -118,14 +118,19 @@ module.exports = function(context, moduleName, options, callback) {
fileSizeMap[path.basename(filename)] = buffer.length;
var modulesArray = [];
for(var moduleId in chunk.modules) {
var modu = depTree.modules[moduleId];
if(chunk.modules[moduleId] === "include")
modulesArray.push({id: moduleId, filename: depTree.modulesById[moduleId].filename});
modulesArray.push({
id: moduleId,
filename: depTree.modules[moduleId].filename,
dirname: depTree.modules[moduleId].dirname,
reasons: modu.reasons});
}
fileModulesMap[path.basename(filename)] = modulesArray;
}
buffer = {};
buffer.chunkCount = chunksCount;
buffer.modulesCount = Object.keys(depTree.modulesById).length;
buffer.modulesCount = Object.keys(depTree.modules).length;
var sum = 0;
for(var chunkId in depTree.chunks) {
for(var moduleId in depTree.chunks[chunkId].modules) {

View File

@ -10,13 +10,13 @@ module.exports = function(depTree, chunk, options) {
chunk = null;
}
var buffer = [];
var modules = chunk ? chunk.modules : depTree.modulesById;
var modules = chunk ? chunk.modules : depTree.modules;
for(var moduleId in modules) {
if(chunk) {
if(chunk.modules[moduleId] !== "include")
continue;
}
var module = depTree.modulesById[moduleId];
var module = depTree.modules[moduleId];
buffer.push("/******/");
buffer.push(moduleId);
buffer.push(": function(module, exports, require) {\n\n");

View File

@ -1,12 +1,13 @@
{
"name": "webpack",
"version": "0.2.0",
"version": "0.2.1",
"author": "Tobias Koppers @sokra",
"description": "Packs CommonJs Modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand.",
"dependencies": {
"esprima": "0.9.8",
"optimist": "0.2.x",
"uglify-js": "1.2.5"
"uglify-js": "1.2.5",
"sprintf": "0.1.x"
},
"licenses": [
{

View File

@ -14,10 +14,10 @@ vows.describe("buildDeps").addBatch({
},
"all modules loaded": function(depTree) {
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "main1.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "a.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "b.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "node_modules", "m1", "a.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "main1.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "a.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "b.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "node_modules", "m1", "a.js")], null);
},
"one chunk": function(depTree) {
@ -34,20 +34,20 @@ vows.describe("buildDeps").addBatch({
},
"all modules loaded": function(depTree) {
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "main2.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "a.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "b.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "node_modules", "m1", "a.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "node_modules", "m1", "b.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "main2.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "a.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "b.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "node_modules", "m1", "a.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "node_modules", "m1", "b.js")], null);
},
"two chunks": function(depTree) {
assert.deepEqual(Object.keys(depTree.chunks), ["0", "1"]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "main2.js")].chunks, [0]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "a.js")].chunks, [0]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "b.js")].chunks, [0]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "node_modules", "m1", "a.js")].chunks, [1]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "node_modules", "m1", "b.js")].chunks, [1]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "main2.js")].chunks, [0]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "a.js")].chunks, [0]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "b.js")].chunks, [0]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "node_modules", "m1", "a.js")].chunks, [1]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "node_modules", "m1", "b.js")].chunks, [1]);
}
},
@ -57,19 +57,19 @@ vows.describe("buildDeps").addBatch({
},
"all modules loaded": function(depTree) {
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "main3.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "a.js")], null);
assert.notEqual(depTree.modules[path.join(__dirname, "fixtures", "c.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "main3.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "a.js")], null);
assert.notEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "c.js")], null);
},
"two chunks": function(depTree) {
assert.deepEqual(Object.keys(depTree.chunks), ["0", "1"]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "main3.js")].chunks, [0]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "a.js")].chunks, [0, 1]);
assert.deepEqual(depTree.modules[path.join(__dirname, "fixtures", "c.js")].chunks, [1]);
var main3id = ""+depTree.modules[path.join(__dirname, "fixtures", "main3.js")].id;
var aid = ""+depTree.modules[path.join(__dirname, "fixtures", "a.js")].id;
var cid = ""+depTree.modules[path.join(__dirname, "fixtures", "c.js")].id;
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "main3.js")].chunks, [0]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "a.js")].chunks, [0, 1]);
assert.deepEqual(depTree.modulesByFile[path.join(__dirname, "fixtures", "c.js")].chunks, [1]);
var main3id = ""+depTree.modulesByFile[path.join(__dirname, "fixtures", "main3.js")].id;
var aid = ""+depTree.modulesByFile[path.join(__dirname, "fixtures", "a.js")].id;
var cid = ""+depTree.modulesByFile[path.join(__dirname, "fixtures", "c.js")].id;
assert.deepEqual(Object.keys(depTree.chunks[0].modules), [main3id, aid]);
assert.deepEqual(Object.keys(depTree.chunks[1].modules), [cid, aid]);
assert.deepEqual(depTree.chunks[0].modules[main3id], "include");