Merge branch 'master' into webpack-2

Conflicts:
	lib/NormalModuleFactory.js
This commit is contained in:
Tobias Koppers 2015-05-16 14:59:50 +02:00
commit 11a578a36b
13 changed files with 288 additions and 201 deletions

View File

@ -80,30 +80,37 @@ module.exports = function(optimist, argv, convertOptions) {
}
if(argv["watch"]) {
if(options.watchDelay) {
console.warn("watchDelay is deprecated: Use 'watch.aggregateTimeout' instead.");
options.watch = options.watch || {};
options.watch.aggregateTimeout = options.watchDelay;
// TODO remove this in next major version
if(options.watch && typeof options.watch === "object") {
console.warn("options.watch is deprecated: use options.watchOptions instead");
options.watchOptions = options.watch;
}
options.doWatch = true;
// TODO remove this in next major version
if(options.watchDelay) {
console.warn("options.watchDelay is deprecated: Use 'options.watchOptions.aggregateTimeout' instead");
options.watchOptions = options.watchOptions || {};
options.watchOptions.aggregateTimeout = options.watchDelay;
}
options.watch = true;
}
if(argv["watch-delay"]) {
options.watch = options.watch || {};
options.watch.aggregateTimeout = +argv["watch-delay"];
console.warn("--watch-delay is deprecated: Use '--watch-aggregate-timeout' instead");
options.watchOptions = options.watchOptions || {};
options.watchOptions.aggregateTimeout = +argv["watch-delay"];
}
if(argv["watch-aggregate-timeout"]) {
options.watch = options.watch || {};
options.watch.aggregateTimeout = +argv["watch-aggregate-timeout"];
options.watchOptions = options.watchOptions || {};
options.watchOptions.aggregateTimeout = +argv["watch-aggregate-timeout"];
}
if(argv["watch-poll"]) {
options.watch = options.watch || {};
options.watchOptions = options.watchOptions || {};
if(typeof argv["watch-poll"] !== "boolean")
options.watch.poll = +argv["watch-poll"];
options.watchOptions.poll = +argv["watch-poll"];
else
options.watch.poll = true;
options.watchOptions.poll = true;
}
function processOptions(options) {

View File

@ -145,7 +145,7 @@ Error.stackTrackLimit = 30;
var lastHash = null;
var compiler = webpack(options);
function compilerCallback(err, stats) {
if(!options.doWatch) {
if(!options.watch) {
// Do not keep cache anymore
compiler.purgeInputFileSystem();
}
@ -153,7 +153,7 @@ function compilerCallback(err, stats) {
lastHash = null;
console.error(err.stack || err);
if(err.details) console.error(err.details);
if(!options.doWatch) {
if(!options.watch) {
process.on("exit", function() {
process.exit(1);
});
@ -172,7 +172,9 @@ function compilerCallback(err, stats) {
});
}
}
if(options.doWatch)
compiler.watch(options.watch, compilerCallback);
else
if(options.watch) {
var primaryOptions = !Array.isArray(options) ? options : options[0];
var watchOptions = primaryOptions.watchOptions || primaryOptions.watch || {};
compiler.watch(watchOptions, compilerCallback);
} else
compiler.run(compilerCallback);

View File

@ -3,6 +3,7 @@
Author Tobias Koppers @sokra
*/
var ConcatSource = require("webpack-core/lib/ConcatSource");
var ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
function wrapComment(str) {
if(str.indexOf("\n") < 0) return "/*! " + str + " */";
@ -10,19 +11,20 @@ function wrapComment(str) {
}
function BannerPlugin(banner, options) {
if(!options) options = {};
this.banner = options.raw ? banner : wrapComment(banner);
this.entryOnly = options.entryOnly;
this.options = options || {};
this.banner = this.options.raw ? banner : wrapComment(banner);
}
module.exports = BannerPlugin;
BannerPlugin.prototype.apply = function(compiler) {
var options = this.options;
var banner = this.banner;
var entryOnly = this.entryOnly;
compiler.plugin("compilation", function(compilation) {
compilation.plugin("optimize-chunk-assets", function(chunks, callback) {
chunks.forEach(function(chunk) {
if(entryOnly && !chunk.initial) return;
chunk.files.forEach(function(file) {
if(options.entryOnly && !chunk.initial) return;
chunk.files.filter(ModuleFilenameHelpers.matchObject.bind(undefined, options)).forEach(function(file) {
compilation.assets[file] = new ConcatSource(banner, "\n", compilation.assets[file]);
});
});

View File

@ -1,85 +0,0 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var ExternalModule = require("./ExternalModule");
function ExternalModuleFactoryDecorator(factory, type, externals) {
this.factory = factory;
this.type = type;
this.externals = externals;
}
module.exports = ExternalModuleFactoryDecorator;
ExternalModuleFactoryDecorator.prototype.plugin = function() {
return this.factory.plugin.apply(this.factory, arguments);
};
ExternalModuleFactoryDecorator.prototype.create = function(context, dependency, callback) {
var factory = this.factory;
var globalType = this.type;
function handleExternal(value, type, callback) {
if(typeof type === "function") {
callback = type;
type = undefined;
}
if(value === false) return factory.create(context, dependency, callback);
if(value === true) value = dependency.request;
if(typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) {
var idx = value.indexOf(" ");
type = value.substr(0, idx);
value = value.substr(idx + 1);
}
callback(null, new ExternalModule(value, type || globalType));
return true;
}
(function handleExternals(externals, callback) {
if(typeof externals === "string") {
if(externals === dependency.request) {
return handleExternal(dependency.request, callback);
}
} else if(Array.isArray(externals)) {
var i = 0;
(function next() {
do {
var async = true;
if(i >= externals.length) return callback();
handleExternals(externals[i++], function(err, module) {
if(err) return callback(err);
if(!module) {
if(async) {
async = false;
return;
}
return next();
}
callback(null, module);
});
} while(!async);
async = false;
}());
return;
} else if(externals instanceof RegExp) {
if(externals.test(dependency.request)) {
return handleExternal(dependency.request, callback);
}
} else if(typeof externals === "function") {
externals.call(null, context, dependency.request, function(err, value, type) {
if(err) return callback(err);
if(typeof value !== "undefined") {
handleExternal(value, type, callback);
} else {
callback();
}
});
return;
} else if(typeof externals === "object" && Object.prototype.hasOwnProperty.call(externals, dependency.request)) {
return handleExternal(externals[dependency.request], callback);
}
callback();
}(this.externals, function(err, module) {
if(err) return callback(err);
if(!module) return handleExternal(false, callback);
return callback(null, module);
}));
};

View File

@ -0,0 +1,85 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var ExternalModule = require("./ExternalModule");
function ExternalModuleFactoryPlugin(type, externals) {
this.type = type;
this.externals = externals;
}
module.exports = ExternalModuleFactoryPlugin;
ExternalModuleFactoryPlugin.prototype.apply = function(normalModuleFactory) {
var globalType = this.type;
normalModuleFactory.plugin("factory", function(factory) {
return function(data, callback) {
var context = data.context;
var dependency = data.dependency;
function handleExternal(value, type, callback) {
if(typeof type === "function") {
callback = type;
type = undefined;
}
if(value === false) return factory(data, callback);
if(value === true) value = dependency.request;
if(typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) {
var idx = value.indexOf(" ");
type = value.substr(0, idx);
value = value.substr(idx + 1);
}
callback(null, new ExternalModule(value, type || globalType));
return true;
}
(function handleExternals(externals, callback) {
if(typeof externals === "string") {
if(externals === dependency.request) {
return handleExternal(dependency.request, callback);
}
} else if(Array.isArray(externals)) {
var i = 0;
(function next() {
do {
var async = true;
if(i >= externals.length) return callback();
handleExternals(externals[i++], function(err, module) {
if(err) return callback(err);
if(!module) {
if(async) {
async = false;
return;
}
return next();
}
callback(null, module);
});
} while(!async);
async = false;
}());
return;
} else if(externals instanceof RegExp) {
if(externals.test(dependency.request)) {
return handleExternal(dependency.request, callback);
}
} else if(typeof externals === "function") {
externals.call(null, context, dependency.request, function(err, value, type) {
if(err) return callback(err);
if(typeof value !== "undefined") {
handleExternal(value, type, callback);
} else {
callback();
}
});
return;
} else if(typeof externals === "object" && Object.prototype.hasOwnProperty.call(externals, dependency.request)) {
return handleExternal(externals[dependency.request], callback);
}
callback();
}(this.externals, function(err, module) {
if(err) return callback(err);
if(!module) return handleExternal(false, callback);
return callback(null, module);
}));
}.bind(this);
}.bind(this));
};

View File

@ -2,7 +2,7 @@
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var ExternalModuleFactoryDecorator = require("./ExternalModuleFactoryDecorator");
var ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
function ExternalsPlugin(type, externals) {
this.type = type;
@ -11,6 +11,6 @@ function ExternalsPlugin(type, externals) {
module.exports = ExternalsPlugin;
ExternalsPlugin.prototype.apply = function(compiler) {
compiler.plugin("compile", function(params) {
params.normalModuleFactory = new ExternalModuleFactoryDecorator(params.normalModuleFactory, this.type, this.externals);
params.normalModuleFactory.apply(new ExternalModuleFactoryPlugin(this.type, this.externals));
}.bind(this));
};
};

View File

@ -17,6 +17,119 @@ function NormalModuleFactory(context, resolvers, parser, options) {
this.preLoaders = new LoadersList(options.preLoaders);
this.postLoaders = new LoadersList(options.postLoaders);
this.context = context || "";
this.plugin("factory", function() {
return function(result, callback) {
var resolver = this.applyPluginsWaterfall("resolver", null);
// Ignored
if(!resolver) return callback();
resolver(result, function onDoneResolving(err, data) {
if(err) return callback(err);
// Ignored
if(!data) return callback();
// direct module
if(typeof data.source === "function")
return callback(null, data);
this.applyPluginsAsyncWaterfall("after-resolve", data, function(err, result) {
if(err) return callback(err);
// Ignored
if(!result) return callback();
var createdModule = this.applyPluginsBailResult("create-module", result);
if(!createdModule) {
createdModule = new NormalModule(
result.request,
result.userRequest,
result.rawRequest,
result.loaders,
result.resource,
result.parser
);
}
return callback(null, createdModule);
}.bind(this));
}.bind(this));
}.bind(this);
});
this.plugin("resolver", function() {
return function(data, callback) {
var context = data.context;
var request = data.request;
var noAutoLoaders = /^-?!/.test(request);
var noPrePostAutoLoaders = /^!!/.test(request);
var noPostAutoLoaders = /^-!/.test(request);
var elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!");
var resource = elements.pop();
async.parallel([
function(callback) {
this.resolveRequestArray(context, elements, this.resolvers.loader, callback);
}.bind(this),
function(callback) {
if(resource === "" || resource[0] === "?")
return callback(null, resource);
this.resolvers.normal.resolve(context, resource, callback);
}.bind(this)
], function(err, results) {
if(err) return callback(err);
var loaders = results[0];
resource = results[1];
if(resource === false)
return callback(null,
new RawModule("/* (ignored) */",
"ignored " + context + " " + request,
request + " (ignored)")); // ignored
var userRequest = loaders.concat([resource]).join("!");
var resourcePath = resource;
var queryIndex = resourcePath.indexOf("?");
if(queryIndex >= 0)
resourcePath = resourcePath.substr(0, queryIndex);
if(noPrePostAutoLoaders)
return onDoneResolving.call(this);
if(noAutoLoaders) {
async.parallel([
this.resolveRequestArray.bind(this, context, noPostAutoLoaders ? [] : this.postLoaders.match(resourcePath), this.resolvers.loader),
this.resolveRequestArray.bind(this, context, this.preLoaders.match(resourcePath), this.resolvers.loader)
], function(err, results) {
if(err) return callback(err);
loaders = results[0].concat(loaders).concat(results[1]);
onDoneResolving.call(this);
}.bind(this));
} else {
async.parallel([
this.resolveRequestArray.bind(this, context, noPostAutoLoaders ? [] : this.postLoaders.match(resourcePath), this.resolvers.loader),
this.resolveRequestArray.bind(this, context, this.loaders.match(resourcePath), this.resolvers.loader),
this.resolveRequestArray.bind(this, context, this.preLoaders.match(resourcePath), this.resolvers.loader)
], function(err, results) {
if(err) return callback(err);
loaders = results[0].concat(loaders).concat(results[1]).concat(results[2]);
onDoneResolving.call(this);
}.bind(this));
}
function onDoneResolving() {
callback(null, {
context: context,
request: loaders.concat([resource]).join("!"),
userRequest: userRequest,
rawRequest: request,
loaders: loaders,
resource: resource,
parser: this.parser
});
}
}.bind(this));
}.bind(this);
});
}
module.exports = NormalModuleFactory;
@ -26,99 +139,21 @@ NormalModuleFactory.prototype.create = function(context, dependency, callback) {
var request = dependency.request;
this.applyPluginsAsyncWaterfall("before-resolve", {
context: context,
request: request
request: request,
dependency: dependency
}, function(err, result) {
if(err) return callback(err);
// Ignored
if(!result) return callback();
context = result.context;
request = result.request;
var factory = this.applyPluginsWaterfall("factory", null);
var noAutoLoaders = /^-?!/.test(request);
var noPrePostAutoLoaders = /^!!/.test(request);
var noPostAutoLoaders = /^-!/.test(request);
var elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!");
var resource = elements.pop();
// Ignored
if(!factory) return callback();
async.parallel([
function(callback) {
this.resolveRequestArray(context, elements, this.resolvers.loader, callback);
}.bind(this),
function(callback) {
if(resource === "" || resource[0] === "?")
return callback(null, resource);
this.resolvers.normal.resolve(context, resource, callback);
}.bind(this)
], function(err, results) {
if(err) return callback(err);
var loaders = results[0];
resource = results[1];
factory(result, callback);
if(resource === false)
return callback(null,
new RawModule("/* (ignored) */",
"ignored " + context + " " + request,
request + " (ignored)")); // ignored
var userRequest = loaders.concat([resource]).join("!");
var resourcePath = resource;
var queryIndex = resourcePath.indexOf("?");
if(queryIndex >= 0)
resourcePath = resourcePath.substr(0, queryIndex);
if(noPrePostAutoLoaders)
return onDoneResolving.call(this);
if(noAutoLoaders) {
async.parallel([
this.resolveRequestArray.bind(this, context, noPostAutoLoaders ? [] : this.postLoaders.match(resourcePath), this.resolvers.loader),
this.resolveRequestArray.bind(this, context, this.preLoaders.match(resourcePath), this.resolvers.loader)
], function(err, results) {
if(err) return callback(err);
loaders = results[0].concat(loaders).concat(results[1]);
onDoneResolving.call(this);
}.bind(this));
} else {
async.parallel([
this.resolveRequestArray.bind(this, context, noPostAutoLoaders ? [] : this.postLoaders.match(resource), this.resolvers.loader),
this.resolveRequestArray.bind(this, context, this.loaders.match(resourcePath), this.resolvers.loader),
this.resolveRequestArray.bind(this, context, this.preLoaders.match(resourcePath), this.resolvers.loader)
], function(err, results) {
if(err) return callback(err);
loaders = results[0].concat(loaders).concat(results[1]).concat(results[2]);
onDoneResolving.call(this);
}.bind(this));
}
function onDoneResolving() {
this.applyPluginsAsyncWaterfall("after-resolve", {
context: context,
request: loaders.concat([resource]).join("!"),
userRequest: userRequest,
rawRequest: request,
loaders: loaders,
resource: resource,
parser: this.parser
}, function(err, result) {
if(err) return callback(err);
// Ignored
if(!result) return callback();
return callback(null,
new NormalModule(
result.request,
result.userRequest,
result.rawRequest,
result.loaders,
result.resource,
result.parser
)
);
});
}
}.bind(this));
}.bind(this));
};

View File

@ -29,11 +29,13 @@ function webpack(options, callback) {
if(callback) {
if(typeof callback !== "function") throw new Error("Invalid argument: callback");
if(options.watch === true) {
console.warn("options.watch and options.watchDelay is deprecated: use webpack(options).watch instead");
var watchOptions = options.watch || !Array.isArray(options) ? options : options[0];
watchOptions = {
aggregateTimeout: watchOptions.watchDelay
};
var watchOptions = (!Array.isArray(options) ? options : options[0]).watchOptions || {};
// TODO remove this in next major version
var watchDelay = (!Array.isArray(options) ? options : options[0]).watchDelay;
if(watchDelay) {
console.warn("options.watchDelay is deprecated: Use 'options.watchOptions.aggregateTimeout' instead");
watchOptions.aggregateTimeout = watchDelay;
}
return compiler.watch(watchOptions, callback);
}
compiler.run(callback);

View File

@ -1,6 +1,6 @@
{
"name": "webpack",
"version": "1.9.4",
"version": "1.9.6",
"author": "Tobias Koppers @sokra",
"description": "Packs CommonJs/AMD 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": {

View File

@ -0,0 +1,14 @@
it("should contain banner in bundle0 chunk", function() {
var fs = require("fs");
var source = fs.readFileSync(__filename, "utf-8");
source.should.containEql("A test value");
});
it("should not contain banner in vendors chunk", function() {
var fs = require("fs"),
path = require("path");
var source = fs.readFileSync(path.join(__dirname, "vendors.js"), "utf-8");
source.should.not.containEql("A test value");
});
require.include("./test.js");

View File

@ -0,0 +1,3 @@
var foo = {};
module.exports = foo;

View File

@ -0,0 +1,3 @@
var bar = {};
module.exports = bar;

View File

@ -0,0 +1,19 @@
var webpack = require("../../../../");
module.exports = {
node: {
__dirname: false,
__filename: false
},
entry: {
bundle0: ["./index.js"],
vendors: ["./vendors.js"]
},
output: {
filename: "[name].js"
},
plugins: [
new webpack.BannerPlugin("A test value", {
exclude: ["vendors.js"]
})
]
};