records, typo

This commit is contained in:
Tobias Koppers 2013-05-31 12:22:40 +02:00
parent df98aca36e
commit f84f000149
9 changed files with 221 additions and 59 deletions

View File

@ -4,7 +4,7 @@
# Introduction # Introduction
webpack is a bundler for modules. The main purpose is to bundle javascript files for useage in browser. webpack is a bundler for modules. The main purpose is to bundle javascript files for usage in browser.
**TL;DR** **TL;DR**

View File

@ -31,6 +31,12 @@ module.exports = function(optimist) {
.string("output-library-target").describe("output-library-target") .string("output-library-target").describe("output-library-target")
.string("records-input-path").describe("records-input-path")
.string("records-output-path").describe("records-output-path")
.string("records-path").describe("records-path")
.string("target").describe("target") .string("target").describe("target")
.boolean("cache").describe("cache") .boolean("cache").describe("cache")

View File

@ -184,6 +184,18 @@ module.exports = function(optimist, argv, convertOptions) {
options.output.libraryTarget = value; options.output.libraryTarget = value;
}); });
ifArg("records-input-path", function(value) {
options.recordsInputPath = path.resolve(value);
});
ifArg("records-output-path", function(value) {
options.recordsOutputPath = path.resolve(value);
});
ifArg("records-path", function(value) {
options.recordsPath = path.resolve(value);
});
ifArg("target", function(value) { ifArg("target", function(value) {
options.target = value; options.target = value;
}); });

View File

@ -35,6 +35,9 @@ function Compilation(compiler) {
this.modules = []; this.modules = [];
this._modules = {}; this._modules = {};
this.cache = null; this.cache = null;
this.records = null;
this.nextFreeModuleId = 1;
this.nextFreeChunkId = 1;
this.assets = {}; this.assets = {};
this.errors = []; this.errors = [];
this.warnings = []; this.warnings = [];
@ -347,21 +350,32 @@ Compilation.prototype.seal = function seal(callback) {
this.processDependenciesBlockForChunk(module, chunk); this.processDependenciesBlockForChunk(module, chunk);
}, this); }, this);
this.applyPlugins("optimize"); this.applyPlugins("optimize");
this.applyPlugins("optimize-modules", this.modules); this.applyPlugins("optimize-modules", this.modules);
this.applyPlugins("after-optimize-modules", this.modules); this.applyPlugins("after-optimize-modules", this.modules);
this.applyPlugins("optimize-chunks", this.chunks); this.applyPlugins("optimize-chunks", this.chunks);
this.applyPlugins("after-optimize-chunks", this.chunks); this.applyPlugins("after-optimize-chunks", this.chunks);
this.applyPlugins("revive-modules", this.modules, this.records);
this.applyPlugins("optimize-module-order", this.modules); this.applyPlugins("optimize-module-order", this.modules);
this.applyModuleIds(); this.applyModuleIds();
this.applyPlugins("optimize-chunk-order", this.chunks);
this.applyChunkIds();
this.applyPlugins("optimize-module-ids", this.modules); this.applyPlugins("optimize-module-ids", this.modules);
this.applyPlugins("after-optimize-module-ids", this.modules); this.applyPlugins("after-optimize-module-ids", this.modules);
this.applyPlugins("record-modules", this.modules, this.records);
this.applyPlugins("revive-chunks", this.chunks, this.records);
this.applyPlugins("optimize-chunk-order", this.chunks);
this.applyChunkIds();
this.applyPlugins("optimize-chunk-ids", this.chunks); this.applyPlugins("optimize-chunk-ids", this.chunks);
this.applyPlugins("after-optimize-chunk-ids", this.chunks); this.applyPlugins("after-optimize-chunk-ids", this.chunks);
this.applyPlugins("record-chunks", this.chunks, this.records);
this.sortItems(); this.sortItems();
this.createChunkAssets(); this.createChunkAssets();
this.summarizeDependencies(); this.summarizeDependencies();
this.applyPlugins("record", this, this.records);
this.applyPluginsAsync("optimize-chunk-assets", this.chunks, function(err) { this.applyPluginsAsync("optimize-chunk-assets", this.chunks, function(err) {
if(err) return callback(err); if(err) return callback(err);
this.applyPlugins("after-optimize-chunk-assets", this.chunks); this.applyPlugins("after-optimize-chunk-assets", this.chunks);
@ -418,62 +432,22 @@ Compilation.prototype.processDependenciesBlockForChunk = function processDepende
}; };
Compilation.prototype.applyModuleIds = function applyModuleIds() { Compilation.prototype.applyModuleIds = function applyModuleIds() {
var i = this.cache && this.cache["nextModuleId"] || 1;
var usedIds = {0:true};
this.modules.forEach(function(module) { this.modules.forEach(function(module) {
if(module.id === null) { if(module.id === null) {
if(module.lastId > 0) { module.id = this.nextFreeModuleId++;
if(!usedIds[module.lastId]) {
usedIds[module.lastId] = true;
module.id = module.lastId;
return;
}
}
module.id = i++;
} }
}); }, this);
if(this.cache) this.cache["nextModuleId"] = i;
}; };
Compilation.prototype.applyChunkIds = function applyChunkIds() { Compilation.prototype.applyChunkIds = function applyChunkIds() {
var i = this.cache && this.cache["nextChunkId"] || 1;
var usedIds = {0:true};
if(this.cache) {
if(!this.cache.chunks)
this.cache.chunks = {};
var keys = Object.keys(this.cache.chunks).slice();
var cacheChunks = this.cache.chunks;
this.cache.chunks = {};
}
this.chunks.forEach(function(chunk) { this.chunks.forEach(function(chunk) {
if(chunk.id === null) { if(chunk.id === null) {
if(this.cache) {
for(var j = 0; j < keys.length; j++) {
var chunkId = keys[j];
var cacheChunk = cacheChunks[chunkId];
if(usedIds[cacheChunk.id]) continue;
if(chunk.blocks.some(function(block) {
return cacheChunk.blocks.indexOf(block) >= 0;
})) {
usedIds[cacheChunk.id] = true;
chunk.id = cacheChunk.id;
break;
}
}
}
if(chunk.id === null) if(chunk.id === null)
chunk.id = i++; chunk.id = this.nextFreeChunkId++;
if(this.cache) {
this.cache.chunks["c"+chunk.id] = {
id: chunk.id,
blocks: chunk.blocks
};
}
} }
if(!chunk.ids) if(!chunk.ids)
chunk.ids = [chunk.id]; chunk.ids = [chunk.id];
}, this); }, this);
if(this.cache) this.cache["nextChunkId"] = i;
}; };
Compilation.prototype.sortItems = function sortItems() { Compilation.prototype.sortItems = function sortItems() {

View File

@ -23,14 +23,18 @@ var RequireEnsureItemDependency = require("./dependencies/RequireEnsureItemDepen
function Watching(compiler, handler, watchDelay) { function Watching(compiler, handler, watchDelay) {
this.startTime = null; this.startTime = null;
this.running = false;
this.invalid = false; this.invalid = false;
this.error = null; this.error = null;
this.stats = null; this.stats = null;
this.handler = handler; this.handler = handler;
this.watchDelay = watchDelay; this.watchDelay = watchDelay;
this.compiler = compiler; this.compiler = compiler;
this._go(); this.running = true;
this.compiler.readRecords(function(err) {
if(err) return this._done(err);
this._go();
}.bind(this));
} }
Watching.prototype._go = function() { Watching.prototype._go = function() {
@ -44,8 +48,13 @@ Watching.prototype._go = function() {
this.compiler.emitAssets(compilation, function(err) { this.compiler.emitAssets(compilation, function(err) {
if(err) return this._done(err); if(err) return this._done(err);
if(this.invalid) return this._done();
return this._done(null, compilation); this.compiler.emitRecords(function(err) {
if(err) return this._done(err);
return this._done(null, compilation);
}.bind(this));
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
@ -101,6 +110,10 @@ function Compiler() {
this.inputFileSystem = null; this.inputFileSystem = null;
this.separateExecutor = null; this.separateExecutor = null;
this.recordsInputPath = null;
this.recordsOutputPath = null;
this.records = {};
this.fileTimestamps = {}; this.fileTimestamps = {};
this.contextTimestamps = {}; this.contextTimestamps = {};
@ -130,17 +143,25 @@ Compiler.prototype.run = function(callback) {
this.applyPluginsAsync("run", this, function(err) { this.applyPluginsAsync("run", this, function(err) {
if(err) return callback(err); if(err) return callback(err);
this.compile(function(err, compilation) { this.readRecords(function(err) {
if(err) return callback(err); if(err) return callback(err);
this.emitAssets(compilation, function(err) { this.compile(function(err, compilation) {
if(err) return callback(err); if(err) return callback(err);
var stats = compilation.getStats(); this.emitAssets(compilation, function(err) {
stats.startTime = startTime; if(err) return callback(err);
stats.endTime = new Date().getTime();
this.applyPlugins("done", stats); this.emitRecords(function(err) {
return callback(null, stats); if(err) return callback(err);
var stats = compilation.getStats();
stats.startTime = startTime;
stats.endTime = new Date().getTime();
this.applyPlugins("done", stats);
return callback(null, stats);
}.bind(this));
}.bind(this));
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
@ -210,6 +231,36 @@ Compiler.prototype.emitAssets = function(compilation, callback) {
}; };
Compiler.prototype.emitRecords = function emitRecords(callback) {
if(!this.recordsOutputPath) return callback();
this.outputFileSystem.writeFile(this.recordsOutputPath, JSON.stringify(this.records, undefined, 2), callback);
};
Compiler.prototype.readRecords = function readRecords(callback) {
if(!this.recordsInputPath) {
this.records = {};
return callback();
}
this.inputFileSystem.stat(this.recordsInputPath, function(err) {
// It doesn't exist
// We can ignore this.
if(err) return callback();
this.inputFileSystem.readFile(this.recordsInputPath, function(err, content) {
if(err) return callback(err);
try {
this.records = JSON.parse(content);
} catch(e) {
e.message = "Cannot parse records: " + e.message;
return callback(e);
}
return callback();
}.bind(this));
}.bind(this));
};
Compiler.prototype.createChildCompiler = function(compilation, compilerName, outputOptions) { Compiler.prototype.createChildCompiler = function(compilation, compilerName, outputOptions) {
var childCompiler = new Compiler(); var childCompiler = new Compiler();
for(var name in this._plugins) { for(var name in this._plugins) {
@ -248,6 +299,7 @@ Compiler.prototype.newCompilation = function(params) {
compilation.fileTimestamps = this.fileTimestamps; compilation.fileTimestamps = this.fileTimestamps;
compilation.contextTimestamps = this.contextTimestamps; compilation.contextTimestamps = this.contextTimestamps;
compilation.name = this.name; compilation.name = this.name;
compilation.records = this.records;
this.applyPlugins("compilation", compilation, params); this.applyPlugins("compilation", compilation, params);
return compilation; return compilation;
}; };

View File

@ -13,6 +13,7 @@ module.exports = DependenciesBlock;
DependenciesBlock.prototype.addBlock = function(block) { DependenciesBlock.prototype.addBlock = function(block) {
this.blocks.push(block); this.blocks.push(block);
block.parent = this;
} }
DependenciesBlock.prototype.addVariable = function(name, expression, dependencies) { DependenciesBlock.prototype.addVariable = function(name, expression, dependencies) {

113
lib/RecordIdsPlugin.js Normal file
View File

@ -0,0 +1,113 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
function RecordIdsPlugin() {
}
module.exports = RecordIdsPlugin;
RecordIdsPlugin.prototype.apply = function(compiler) {
compiler.plugin("compilation", function(compilation) {
compilation.plugin("record-modules", function(modules, records) {
records.nextFreeModuleId = compilation.nextFreeModuleId;
if(!records.modules) records.modules = {};
if(!records.modules.byIdentifier) records.modules.byIdentifier = {};
modules.forEach(function(module) {
var identifier = module.identifier();
records.modules.byIdentifier[identifier] = module.id;
});
});
compilation.plugin("revive-modules", function(modules, records) {
if(records.nextFreeModuleId)
compilation.nextFreeModuleId = records.nextFreeModuleId;
if(!records.modules || !records.modules.byIdentifier) return;
var usedIds = {0: true};
modules.forEach(function(module) {
if(module.id !== null) return;
var identifier = module.identifier();
var id = records.modules.byIdentifier[identifier];
if(usedIds[id]) return;
usedIds[id] = true;
module.id = id;
});
});
function getDepBlockIdent(block) {
var ident = [];
while(block.parent) {
var p = block.parent;
var idx = p.blocks.indexOf(block);
var l = p.blocks.length - 1;
ident.unshift(idx + "/" + l);
block = block.parent;
}
if(!block.identifier) return null;
ident.unshift(block.identifier());
return ident.join(":");
}
compilation.plugin("record-chunks", function(chunks, records) {
records.nextFreeChunkId = compilation.nextFreeChunkId;
if(!records.chunks) records.chunks = {};
if(!records.chunks.byName) records.chunks.byName = {};
if(!records.chunks.byBlocks) records.chunks.byBlocks = {};
chunks.forEach(function(chunk) {
var name = chunk.name;
var blockIdents = chunk.blocks.map(getDepBlockIdent).filter(Boolean);
if(name) records.chunks.byName[name] = chunk.id;
blockIdents.forEach(function(blockIdent) {
records.chunks.byBlocks[blockIdent] = chunk.id;
});
});
});
compilation.plugin("revive-chunks", function(chunks, records) {
if(records.nextFreeChunkId)
compilation.nextFreeChunkId = records.nextFreeChunkId;
if(!records.chunks) return;
var usedIds = {0: true};
if(records.chunks.byName) {
chunks.forEach(function(chunk) {
if(chunk.id !== null) return;
if(!chunk.name) return;
var id = records.chunks.byName[chunk.name];
if(usedIds[id]) return;
usedIds[id] = true;
chunk.id = id;
});
}
if(records.chunks.byBlocks) {
var argumentedChunks = chunks.filter(function(chunk) {
return chunk.id === null
}).map(function(chunk) {
return {
chunk: chunk,
blockIdents: chunk.blocks.map(getDepBlockIdent).filter(Boolean)
}
}).filter(function(arg) {
return arg.blockIdents.length > 0;
});
var blockIdentsCount = {};
argumentedChunks.forEach(function(arg, idx) {
arg.blockIdents.forEach(function(blockIdent) {
var id = records.chunks.byBlocks[blockIdent]
if(!id) return;
var accessor = id + ":" + idx;
blockIdentsCount[accessor] = (blockIdentsCount[accessor] || 0) + 1;
});
});
blockIdentsCount = Object.keys(blockIdentsCount).map(function(accessor) {
return [blockIdentsCount[accessor]].concat(accessor.split(":").map(Number));
}).sort(function(a, b) {
return b[0] - a[0];
})
blockIdentsCount.forEach(function(arg) {
var id = arg[1];
if(usedIds[id]) return;
var idx = arg[2];
var chunk = argumentedChunks[idx].chunk;
if(chunk.id !== null) return;
usedIds[id] = true;
chunk.id = id;
});
}
});
});
};

View File

@ -16,8 +16,7 @@ var PrefetchPlugin = require("./PrefetchPlugin");
var SingleEntryPlugin = require("./SingleEntryPlugin"); var SingleEntryPlugin = require("./SingleEntryPlugin");
var MultiEntryPlugin = require("./MultiEntryPlugin"); var MultiEntryPlugin = require("./MultiEntryPlugin");
var CachePlugin = require("./CachePlugin"); var CachePlugin = require("./CachePlugin");
var RecordIdsPlugin = require("./RecordIdsPlugin");
var UglifyJsPlugin = require("./optimize/UglifyJsPlugin");
var APIPlugin = require("./APIPlugin"); var APIPlugin = require("./APIPlugin");
var ConstPlugin = require("./ConstPlugin"); var ConstPlugin = require("./ConstPlugin");
@ -35,6 +34,7 @@ var RequireContextPlugin = require("./dependencies/RequireContextPlugin");
var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin"); var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin"); var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
var UglifyJsPlugin = require("./optimize/UglifyJsPlugin");
var OccurenceOrderPlugin = require("./optimize/OccurenceOrderPlugin"); var OccurenceOrderPlugin = require("./optimize/OccurenceOrderPlugin");
var LimitChunkCountPlugin = require("./optimize/LimitChunkCountPlugin"); var LimitChunkCountPlugin = require("./optimize/LimitChunkCountPlugin");
var MinChunkSizePlugin = require("./optimize/MinChunkSizePlugin"); var MinChunkSizePlugin = require("./optimize/MinChunkSizePlugin");
@ -66,6 +66,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
compiler.apply.apply(compiler, options.plugins); compiler.apply.apply(compiler, options.plugins);
} }
compiler.outputPath = options.output.path; compiler.outputPath = options.output.path;
compiler.recordsInputPath = options.recordsInputPath || options.recordsPath;
compiler.recordsOutputPath = options.recordsOutputPath || options.recordsPath;
switch(options.target) { switch(options.target) {
case "web": case "web":
compiler.apply( compiler.apply(
@ -138,6 +140,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
new FlagIncludedChunksPlugin() new FlagIncludedChunksPlugin()
); );
compiler.apply(new RecordIdsPlugin());
if(options.optimize && options.optimize.occurenceOrder) if(options.optimize && options.optimize.occurenceOrder)
compiler.apply(new OccurenceOrderPlugin(options.optimize.occurenceOrderPreferEntry)); compiler.apply(new OccurenceOrderPlugin(options.optimize.occurenceOrderPreferEntry));

View File

@ -1,6 +1,6 @@
{ {
"name": "webpack", "name": "webpack",
"version": "0.10.0-beta17", "version": "0.10.0-beta18",
"author": "Tobias Koppers @sokra", "author": "Tobias Koppers @sokra",
"description": "Packs CommonJs/AMD/Labeled Modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jade, coffee, css, less, ... and your custom stuff.", "description": "Packs CommonJs/AMD/Labeled Modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jade, coffee, css, less, ... and your custom stuff.",
"dependencies": { "dependencies": {