added pre and post loaders

This commit is contained in:
Tobias Koppers 2012-07-11 12:18:31 +02:00
parent 514ad01e97
commit 87f82e5219
10 changed files with 146 additions and 60 deletions

View File

@ -476,6 +476,18 @@ You can also save this options object in a JSON file and use it with the shell c
// same as postprocess.normal but for contextes
}
}
postLoaders: [{test: /\.export.js$/, loader: "export"}],
// default: []
// syntax like resolve.loaders
// all loaders which matches the file are applied after the
// normal loaders. This cannot be overridden in the require call.
preLoaders: [{test: /\.txt$|\.html$/, loader: "normalizeNLs"}],
// default: []
// syntax like resolve.loaders
// all loaders which matches the file are applied before the
// normal loaders. This cannot be overridden in the require call.
}
```

View File

@ -150,20 +150,42 @@ function addModule(depTree, context, modu, options, reason, finalCallback) {
return;
}
// exec the loaders
execLoaders(context, filenameWithLoaders, loaders, [filename], [content], cacheEntry, options, processJs);
var preLoaders = matchLoadersList(options.preLoaders);
var postLoaders = matchLoadersList(options.postLoaders);
resolve.loaders(context, preLoaders, options.resolve, function(err, preLoaders) {
if(err) return callback(err);
resolve.loaders(context, postLoaders, options.resolve, function(err, postLoaders) {
if(err) return callback(err);
execLoaders(context, filenameWithLoaders, preLoaders, [filename], [content], cacheEntry, options,
function(err, result, preLoadersCacheable) {
execLoaders(context, filenameWithLoaders, loaders, [filename], result, cacheEntry, options,
function(err, result, loadersCacheable) {
execLoaders(context, filenameWithLoaders, postLoaders, [filename], result, cacheEntry, options,
function(err, result, postLoadersCacheable) {
if(err) return callback(err);
return processJs(result, loadersCacheable && preLoadersCacheable && postLoadersCacheable)
});
});
});
});
});
});
}
function matchLoadersList(list) {
return list.filter(function(item) {
return (item.test.test(filename));
}).map(function(item) {
return item.loader;
}).join("!");
}
// process the result delivered from loaders or direct from file
// for inclusion into the result
// (static code analysis for requires and other stuff)
// [this step is cached]
function processJs(err, resultBuffers, cacheable) {
if(err) {
callback(err);
return;
}
function processJs(resultBuffers, cacheable) {
var source = resultBuffers[0].toString("utf-8")
var deps;
try {

View File

@ -50,10 +50,62 @@ function resolve(context, identifier, options, type, callback) {
}
function doResolve(context, identifier, options, type, callback) {
if(!callback) {
callback = options;
options = {};
var identifiers = identifier.replace(/^!|!$/g, "").replace(/!!/g, "!").split(/!/g);
var resource = identifiers.pop();
resolve(context, resource, options, type, function(err, resource) {
if(err) return callback(err);
if(identifier.indexOf("!") === -1) {
for(var i = 0; i < options.loaders.length; i++) {
var line = options.loaders[i];
if(line.test.test(resource)) {
Array.prototype.push.apply(identifiers, line.loader.split(/!/g));
break;
}
}
}
resolveLoaders(context, identifiers, options, function(err, identifiers) {
identifiers.push(resource);
var intermediateResult = identifiers.join("!");
var postprocessors = options.postprocess[type].slice(0);
postprocessors.push(function(result) {
callback(null, result);
});
(function next(err, result) {
if(err)
return callback(new Error("File \"" + intermediateResult + "\" is blocked by postprocessors: " + err));
postprocessors.shift()(result, next);
})(null, intermediateResult);
});
});
}
function resolveLoaders(context, identifiers, options, callback) {
var errors = [];
var count = identifiers.length;
function endOne() {
count--;
if(count === 0) {
if(errors.length > 0) {
callback(new Error(errors.join("\n")));
return;
}
callback(null, identifiers);
}
}
if(count == 0) endOne(count++);
identifiers.forEach(function(ident, index) {
resolve(context, ident, options, "loader", function(err, filename) {
if(err) {
errors.push(err);
} else {
identifiers[index] = filename;
}
endOne()
});
});
}
function setupDefaultOptions(options) {
if(!options)
options = {};
if(!options.extensions)
@ -76,53 +128,7 @@ function doResolve(context, identifier, options, type, callback) {
options.postprocess.normal = [];
if(!options.postprocess.context)
options.postprocess.context = [];
var identifiers = identifier.replace(/^!|!$/g, "").replace(/!!/g, "!").split(/!/g);
var resource = identifiers.pop();
resolve(context, resource, options, type, function(err, resource) {
if(err) return callback(err);
if(identifier.indexOf("!") === -1) {
for(var i = 0; i < options.loaders.length; i++) {
var line = options.loaders[i];
if(line.test.test(resource)) {
Array.prototype.push.apply(identifiers, line.loader.split(/!/g));
break;
}
}
}
var errors = [];
var count = identifiers.length;
function endOne() {
count--;
if(count === 0) {
if(errors.length > 0) {
callback(new Error(errors.join("\n")));
return;
}
identifiers.push(resource);
var intermediateResult = identifiers.join("!");
var postprocessors = options.postprocess[type].slice(0);
postprocessors.push(function(result) {
callback(null, result);
});
(function next(err, result) {
if(err)
return callback(new Error("File \"" + intermediateResult + "\" is blocked by postprocessors: " + err));
postprocessors.shift()(result, next);
})(null, intermediateResult);
}
}
if(count == 0) endOne(count++);
identifiers.forEach(function(ident, index) {
resolve(context, ident, options, "loader", function(err, filename) {
if(err) {
errors.push(err);
} else {
identifiers[index] = filename;
}
endOne()
});
});
});
return options;
}
/**
@ -133,13 +139,37 @@ function doResolve(context, identifier, options, type, callback) {
* callback: function(err, absoluteFilename)
*/
module.exports = function(context, identifier, options, callback) {
if(!callback) {
callback = options;
options = {};
}
options = setupDefaultOptions(options);
return doResolve(context, identifier, options, "normal", callback);
}
module.exports.context = function(context, identifier, options, callback) {
if(!callback) {
callback = options;
options = {};
}
options = setupDefaultOptions(options);
return doResolve(context, identifier, options, "context", callback);
}
/**
* callback: function(err, absoluteFilenamesArray)
*/
module.exports.loaders = function(context, identifier, options, callback) {
if(!callback) {
callback = options;
options = {};
}
options = setupDefaultOptions(options);
var identifiers = identifier.replace(/^!|!$/g, "").replace(/!!/g, "!").split(/!/g);
if(identifiers.length == 1 && identifiers[0] == "") return callback(null, []);
return resolveLoaders(context, identifiers, options, callback);
}
function split(a) {
return a.split(/[\/\\]/g);

View File

@ -117,6 +117,9 @@ module.exports = function(context, moduleName, options, callback) {
options.resolve.loaders.push({test: /\.css$/, loader: "style!css"});
options.resolve.loaders.push({test: /\.less$/, loader: "style!css!val/cacheable!less"});
options.preLoaders = options.preLoaders || [];
options.postLoaders = options.postLoaders || [];
options.loader = options.loader || {};
options.loader.emitFile = options.loader.emitFile || function(filename, content) {
options.internal.fileWrites.push([path.join(options.outputDirectory, filename), content]);

View File

@ -1,6 +1,6 @@
{
"name": "webpack",
"version": "0.4.16",
"version": "0.4.17",
"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. Support loading of js, json, jade, coffee, css, ... out of the box and more with custom loaders.",
"dependencies": {

View File

@ -50,6 +50,6 @@ function compile() {
}
});
var libary2 = cp.spawn("node", join(["../../bin/webpack.js", "--colors", "--libary", "libary2",
"--script-src-prefix", "js/", "node_modules/libary2", "js/libary2.js"], extraArgs));
"--script-src-prefix", "js/", "--options", "libary2config.js", "node_modules/libary2", "js/libary2.js"], extraArgs));
bindOutput(libary2);
}

View File

@ -0,0 +1,14 @@
module.exports = {
postLoaders: [
{ test: /extra2\.js/, loader: "raw!extra!val/cacheable" }
],
resolve: {
postprocess: {
normal: [
function(filename, callback) {
callback(null, filename.replace(/extra\.js/, "extra2.js"));
}
]
}
}
}

4
test/browsertest/node_modules/extra.loader.js generated vendored Normal file
View File

@ -0,0 +1,4 @@
module.exports = function(string) {
this.cacheable();
return string + " with post loader";
}

1
test/browsertest/node_modules/libary2/lib/extra2.js generated vendored Normal file
View File

@ -0,0 +1 @@
module.exports = "Lib2 extra2";

View File

@ -7,7 +7,7 @@ require.ensure("./extra", function(require) {
var sameTick = true;
require.ensure([], function(require) {
asnycOk2 = true;
window.test(require("./extra") === "Lib2 extra", "Lib2 extra loaded");
window.test(require("./extra") === "Lib2 extra2 with post loader", "Lib2 extra loaded");
window.test(sameTick, "Lib2 Should be in the same tick, as it is a empty chunk");
});
sameTick = false;