added option to prefetch modules

This commit is contained in:
Tobias Koppers 2013-05-13 13:34:00 +02:00
parent 96275187cc
commit 209f96c543
10 changed files with 122 additions and 24 deletions

View File

@ -55,6 +55,8 @@ module.exports = function(optimist) {
.boolean("optimize-occurence-order").describe("optimize-occurence-order") .boolean("optimize-occurence-order").describe("optimize-occurence-order")
.string("prefetch").describe("prefetch")
.string("provide").describe("provide") .string("provide").describe("provide")
.string("plugin").describe("plugin") .string("plugin").describe("plugin")

View File

@ -255,6 +255,11 @@ module.exports = function(optimist, argv, convertOptions) {
options.optimize.occurenceOrder = true; options.optimize.occurenceOrder = true;
}); });
ifArg("prefetch", function(request) {
ensureArray(options, "prefetch");
options.prefetch.push(request);
});
ifArg("provide", function(value) { ifArg("provide", function(value) {
ensureObject(options, "provide"); ensureObject(options, "provide");
var idx = value.indexOf("="); var idx = value.indexOf("=");

View File

@ -234,61 +234,104 @@ Compilation.prototype.processModuleDependencies = function(module, callback) {
}); });
}; };
Compilation.prototype.addEntry = function process(context, entry, name, callback) { Compilation.prototype._addModuleChain = function process(context, dependency, onModule, callback) {
var errorAndCallback = this.bail ? function errorAndCallback(err) { var errorAndCallback = this.bail ? function errorAndCallback(err) {
callback(err); callback(err);
} : function errorAndCallback(err) { } : function errorAndCallback(err) {
err.dependencies = [entry]; err.dependencies = [dependency];
this.errors.push(err); this.errors.push(err);
callback(); callback();
}.bind(this); }.bind(this);
if(!(typeof entry == "object" && entry != null && entry.Class)) if(!(typeof dependency == "object" && dependency != null && dependency.Class))
return callback(new Error("Parameter 'entry' must be a Dependency")); throw new Error("Parameter 'dependency' must be a Dependency");
var moduleFactory = this.dependencyFactories.get(entry.Class); var moduleFactory = this.dependencyFactories.get(dependency.Class);
if(!moduleFactory) if(!moduleFactory)
return callback(new Error("No dependency factory availible for this entry dependency type: " + entry.Class.name)); throw new Error("No dependency factory availible for this dependency type: " + dependency.Class.name);
moduleFactory.create(context, entry, function(err, module) { if(this.profile) var start = +new Date();
moduleFactory.create(context, dependency, function(err, module) {
if(err) return errorAndCallback(new EntryModuleNotFoundError(err)); if(err) return errorAndCallback(new EntryModuleNotFoundError(err));
if(this.profile) {
if(!module.profile) module.profile = {};
var afterFactory = +new Date();
module.profile.factory = afterFactory - start;
}
var result = this.addModule(module); var result = this.addModule(module);
if(!result) { if(!result) {
return callback(new Error("Entry module is already added")); module = this.getModule(module);
onModule(module);
return callback(null, module);
} }
if(result instanceof Module) { if(result instanceof Module) {
if(this.profile) {
result.profile = module.profile;
}
module = result; module = result;
} }
this.entries.push(module); onModule(module);
module.id = 0;
if(result instanceof Module) { if(result instanceof Module) {
entryReady.call(this); moduleReady.call(this);
} else { } else {
this.buildModule(module, function(err) { this.buildModule(module, function(err) {
if(err) return errorAndCallback(err); if(err) return errorAndCallback(err);
entryReady.call(this); if(this.profile) {
var afterBuilding = +new Date();
module.profile.building = afterBuilding - afterFactory;
}
moduleReady.call(this);
}.bind(this)); }.bind(this));
} }
function entryReady() { function moduleReady() {
this.processModuleDependencies(module, function(err) { this.processModuleDependencies(module, function(err) {
if(err) return callback(err); if(err) return callback(err);
return callback(null, module);
}.bind(this));
}
}.bind(this));
};
Compilation.prototype.addEntry = function process(context, entry, name, callback) {
this._addModuleChain(context, entry, function(module) {
this.entries.push(module);
module.id = 0;
}.bind(this), function(err, module) {
if(err) return callback(err);
if(module) {
var chunk = this.addChunk(name); var chunk = this.addChunk(name);
chunk.id = 0; chunk.id = 0;
chunk.entry = true; chunk.entry = true;
chunk.addModule(module); chunk.addModule(module);
module.addChunk(chunk); module.addChunk(chunk);
this.processDependenciesBlockForChunk(module, chunk); this.processDependenciesBlockForChunk(module, chunk);
}
return callback(); return callback();
}.bind(this)); }.bind(this));
} };
}.bind(this));
Compilation.prototype.prefetch = function process(context, dependency, callback) {
this._addModuleChain(context, dependency, function(module) {
module.prefetched = true;
}, callback);
}; };
Compilation.prototype.seal = function seal(callback) { Compilation.prototype.seal = function seal(callback) {

View File

@ -278,7 +278,7 @@ Compiler.prototype.compile = function(callback) {
var compilation = this.newCompilation(params); var compilation = this.newCompilation(params);
this.applyPluginsAsync("make", compilation, function(err) { this.applyPluginsParallel("make", compilation, function(err) {
if(err) return callback(err); if(err) return callback(err);
compilation.seal(function(err) { compilation.seal(function(err) {

21
lib/PrefetchPlugin.js Normal file
View File

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var PrefetchDependency = require("./dependencies/PrefetchDependency");
function PrefetchPlugin(context, request) {
this.context = context;
this.request = request;
}
module.exports = PrefetchPlugin;
PrefetchPlugin.prototype.apply = function(compiler) {
compiler.plugin("compilation", function(compilation, params) {
var normalModuleFactory = params.normalModuleFactory;
compilation.dependencyFactories.set(PrefetchDependency, normalModuleFactory);
});
compiler.plugin("make", function(compilation, callback) {
compilation.prefetch(this.context, new PrefetchDependency(this.request), callback);
}.bind(this));
};

View File

@ -114,6 +114,7 @@ Stats.prototype.toJson = function toJson(options, forToString) {
size: module.size(), size: module.size(),
cacheable: !!module.cacheable, cacheable: !!module.cacheable,
built: !!module.built, built: !!module.built,
prefetched: !!module.prefetched,
chunks: module.chunks.map(function(chunk) { chunks: module.chunks.map(function(chunk) {
return chunk.id; return chunk.id;
}), }),
@ -406,6 +407,9 @@ Stats.jsonToString = function jsonToString(obj, useColors) {
if(module.built) { if(module.built) {
green(" [built]"); green(" [built]");
} }
if(module.prefetched) {
magenta(" [prefetched]");
}
if(module.chunks) { if(module.chunks) {
module.chunks.forEach(function(chunk) { module.chunks.forEach(function(chunk) {
normal(" {"); normal(" {");
@ -453,6 +457,9 @@ Stats.jsonToString = function jsonToString(obj, useColors) {
if(module.built) { if(module.built) {
green(" [built]"); green(" [built]");
} }
if(module.prefetched) {
magenta(" [prefetched]");
}
if(module.chunks) { if(module.chunks) {
module.chunks.forEach(function(chunk) { module.chunks.forEach(function(chunk) {
normal(" {"); normal(" {");

View File

@ -12,6 +12,7 @@ var EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
var SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); var SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
var LibraryTemplatePlugin = require("./LibraryTemplatePlugin"); var LibraryTemplatePlugin = require("./LibraryTemplatePlugin");
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");
@ -111,6 +112,11 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
compiler.apply(itemToPlugin(options.entry[name], name)); compiler.apply(itemToPlugin(options.entry[name], name));
}); });
} }
if(options.prefetch) {
options.prefetch.map(function(request) {
compiler.apply(new PrefetchPlugin(options.context, request));
});
}
compiler.apply( compiler.apply(
new CompatibilityPlugin(), new CompatibilityPlugin(),
new NodeStuffPlugin(options.node), new NodeStuffPlugin(options.node),

View File

@ -0,0 +1,14 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var ModuleDependency = require("./ModuleDependency");
function PrefetchDependency(request) {
ModuleDependency.call(this, request);
this.Class = PrefetchDependency;
}
module.exports = PrefetchDependency;
PrefetchDependency.prototype = Object.create(ModuleDependency.prototype);
PrefetchDependency.prototype.type = "prefetch";

View File

@ -1,6 +1,6 @@
{ {
"name": "webpack", "name": "webpack",
"version": "0.10.0-beta10", "version": "0.10.0-beta11",
"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": {

View File

@ -34,9 +34,9 @@ var library1 = cp.spawn("node", join(["../../bin/webpack.js", "--output-pathinfo
bindOutput(library1); bindOutput(library1);
library1.on("exit", function(code) { library1.on("exit", function(code) {
if(code === 0) { if(code === 0) {
// node ../../bin/webpack --output-pathinfo --colors --resolve-alias vm=vm-browserify --output-public-path js/ --module-bind json --module-bind css=style!css --module-bind less=style!css!less --module-bind coffee --module-bind jade ./lib/index js/web.js // node ../../bin/webpack --output-pathinfo --colors --resolve-alias vm=vm-browserify --output-public-path js/ --module-bind json --module-bind css=style!css --module-bind less=style!css!less --module-bind coffee --module-bind jade --prefetch ./less/stylesheet.less ./lib/index js/web.js
var main = cp.spawn("node", join(["../../bin/webpack.js", "--output-pathinfo", "--colors", "--resolve-alias", "vm=vm-browserify", "--workers", var main = cp.spawn("node", join(["../../bin/webpack.js", "--output-pathinfo", "--colors", "--resolve-alias", "vm=vm-browserify", "--workers",
"--output-public-path", "js/", "--module-bind", "json", "--module-bind", "css=style!css", "--module-bind", "less=style/url!file?postfix=.css&string!less", "--module-bind", "coffee", "--module-bind", "jade", "./lib/index", "js/web.js", "--progress"], extraArgs)); "--output-public-path", "js/", "--module-bind", "json", "--module-bind", "css=style!css", "--module-bind", "less=style/url!file?postfix=.css&string!less", "--module-bind", "coffee", "--module-bind", "jade", "--prefetch", "./less/stylesheet.less", "./lib/index", "js/web.js", "--progress"], extraArgs));
bindOutput(main); bindOutput(main);
} }
}); });