moved webworker template, added node.js template #57

This commit is contained in:
Tobias Koppers 2013-02-13 17:00:07 +01:00
parent 9252254149
commit 3dc62749a2
18 changed files with 363 additions and 30 deletions

35
lib/NodeStuffPlugin.js Normal file
View File

@ -0,0 +1,35 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var path = require("path");
var ModuleAliasPlugin = require("enhanced-resolve/lib/ModuleAliasPlugin");
var ModuleParserHelpers = require("./ModuleParserHelpers");
var ConstDependency = require("./dependencies/ConstDependency");
function NodeStuffPlugin() {
}
module.exports = NodeStuffPlugin;
NodeStuffPlugin.prototype.apply = function(compiler) {
function ignore() { return true; }
compiler.parser.plugin("expression __filename", function(expr) {
this.state.current.addVariable("__filename", JSON.stringify("/index.js"));
return true;
});
compiler.parser.plugin("expression __dirname", function(expr) {
this.state.current.addVariable("__dirname", JSON.stringify("/"));
return true;
});
compiler.parser.plugin("expression require.main", function(expr) {
var dep = new ConstDependency("require.cache[0]", expr.range);
dep.loc = expr.loc;
this.state.current.addDependency(dep);
return true;
});
compiler.parser.plugin("expression module.exports", ignore);
compiler.parser.plugin("expression module.loaded", ignore);
compiler.parser.plugin("expression module.id", ignore);
compiler.parser.plugin("expression module", function(expr) {
return ModuleParserHelpers.addParsedVariable(this, "module", "require(" + JSON.stringify(path.join(__dirname, "..", "buildin", "module.js")) + ")(module)");
});
};

View File

@ -4,12 +4,12 @@
*/
var path = require("path");
function NodeSourceRealPathsPlugin(context, onlyIfInContext) {
function NodeStuffRealPathsPlugin(context, onlyIfInContext) {
this.context = context;
this.onlyIfInContext = onlyIfInContext;
}
module.exports = NodeSourceRealPathsPlugin;
NodeSourceRealPathsPlugin.prototype.apply = function(compiler) {
module.exports = NodeStuffRealPathsPlugin;
NodeStuffRealPathsPlugin.prototype.apply = function(compiler) {
var context = this.context;
var onlyIfInContext = this.onlyIfInContext;
compiler.parser.plugin("expression __filename", function(expr) {

View File

@ -6,6 +6,8 @@ var OptionsApply = require("./OptionsApply");
var FunctionModulePlugin = require("./FunctionModulePlugin");
var JsonpTemplatePlugin = require("./JsonpTemplatePlugin");
var WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin");
var NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
var EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
var LibraryTemplatePlugin = require("./LibraryTemplatePlugin");
@ -18,8 +20,11 @@ var UglifyJsPlugin = require("./optimize/UglifyJsPlugin");
var ConsolePlugin = require("./ConsolePlugin");
var APIPlugin = require("./APIPlugin");
var ConstPlugin = require("./ConstPlugin");
var NodeStuffPlugin = require("./NodeStuffPlugin");
var CompatibilityPlugin = require("./CompatibilityPlugin");
var ProvidePlugin = require("./ProvidePlugin");
var NodeSourcePlugin = require("./node/NodeSourcePlugin");
var NodeTargetPlugin = require("./node/NodeTargetPlugin");
var CommonJsPlugin = require("./dependencies/CommonJsPlugin");
var AMDPlugin = require("./dependencies/AMDPlugin");
@ -55,10 +60,29 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
compiler.apply.apply(compiler, options.plugins);
}
compiler.outputPath = options.output.path;
compiler.apply(
new JsonpTemplatePlugin(options.output),
new FunctionModulePlugin(options.context, options.output)
);
switch(options.target) {
case "web":
compiler.apply(
new JsonpTemplatePlugin(options.output),
new FunctionModulePlugin(options.context, options.output),
new NodeSourcePlugin()
);
break;
case "webworker":
compiler.apply(
new WebWorkerTemplatePlugin(options.output),
new FunctionModulePlugin(options.context, options.output),
new NodeSourcePlugin()
);
break;
case "node":
compiler.apply(
new NodeTemplatePlugin(options.output),
new FunctionModulePlugin(options.context, options.output),
new NodeTargetPlugin()
);
break;
}
if(options.output.library || options.output.libraryTarget != "var")
compiler.apply(new LibraryTemplatePlugin(options.output.library, options.output.libraryTarget));
if(options.devtool == "eval")
@ -77,6 +101,7 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
});
}
compiler.apply(
new NodeStuffPlugin(),
new CompatibilityPlugin(),
new APIPlugin(),
new ConstPlugin(),

View File

@ -12,6 +12,7 @@ function WebpackOptionsDefaulter(str) {
this.set("minimize", true);
this.set("context", process.cwd());
this.set("target", "web");
this.set("output", {});
this.set("optimize", {});
this.set("resolve", {});

View File

@ -0,0 +1,28 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var RawSource = require("webpack-core/lib/RawSource");
function NodeChunkTemplate(outputOptions) {
this.outputOptions = outputOptions || {};
}
module.exports = NodeChunkTemplate;
NodeChunkTemplate.prototype.render = function(chunk, moduleTemplate, dependencyTemplates) {
var buf = [];
buf.push("module.exports = ({\n");
chunk.modules.forEach(function(module, idx) {
if(idx != 0) buf.push(",\n");
buf.push("\n/***/ " + module.id + ":\n");
var source = moduleTemplate.render(module, dependencyTemplates);
buf.push(source.source());
});
buf.push("\n\n})");
return new RawSource(buf.join(""));
};
NodeChunkTemplate.prototype.updateHash = function(hash) {
hash.update("node");
hash.update("1");
};

View File

@ -0,0 +1,80 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var StringSource = require("webpack-core/lib/RawSource");
function NodeMainTemplate(outputOptions) {
this.outputOptions = outputOptions || {};
}
module.exports = NodeMainTemplate;
var REGEXP_HASH = /\[hash\]/i;
var REGEXP_NAME = /\[name\]/g;
var REGEXP_ID = /\[id\]/i;
NodeMainTemplate.prototype.render = function(hash, chunk, moduleTemplate, dependencyTemplates) {
var filename = this.outputOptions.filename || "bundle.js";
var chunkFilename = this.outputOptions.chunkFilename || "[id]." + filename;
var buf = [];
function addLine(indent, line) {
buf.push("/******/ ");
for(var i = 0; i < indent; i++)
buf.push("\t");
buf.push(line);
buf.push("\n");
}
function addRequireFunc(i) {
addLine(i+0, "function __require(moduleId) {");
addLine(i+1, "if(typeof moduleId !== \"number\") throw new Error(\"Cannot find module '\"+moduleId+\"'\");");
addLine(i+1, "if(installedModules[moduleId])");
addLine(i+2, "return installedModules[moduleId].exports;");
addLine(i+1, "var module = installedModules[moduleId] = {");
addLine(i+2, "exports: {},");
addLine(i+2, "id: moduleId,");
addLine(i+2, "loaded: false");
addLine(i+1, "};");
addLine(i+1, "modules[moduleId].call(null, module, module.exports, __require);");
addLine(i+1, "module.loaded = true;");
addLine(i+1, "return module.exports;");
addLine(i+0, "}");
}
addLine(0, "(function webpackBootstrap(modules) {");
addLine(1, "var installedModules = {};");
addRequireFunc(1);
addLine(1, "__require.e = function requireEnsure(chunkId, callback) {");
if(chunk.chunks.length == 0) {
addLine(2, "callback.call(null, __require);");
} else {
addLine(2, "if(installedChunks[chunkId] === 1) return callback.call(null, __require);");
addLine(2, "var moreModules = require(" + JSON.stringify("./" + chunkFilename.replace(REGEXP_HASH, hash).replace(REGEXP_NAME, "")).replace(REGEXP_ID, "\"+chunkId+\"") + ");");
addLine(2, "for(var moduleId in moreModules)");
addLine(3, "modules[moduleId] = moreModules[moduleId];");
addLine(2, "callback.call(null, __require);");
}
addLine(1, "};");
addLine(1, "__require.modules = modules;");
addLine(1, "__require.cache = installedModules;");
addLine(1, "__require.parentRequire = require;");
if(chunk.chunks.length > 0) {
addLine(1, "var installedChunks = {0:1};");
}
addLine(1, "return __require(0);");
addLine(0, "})({");
addLine(0, "c: __dirname,");
chunk.modules.forEach(function(module, idx) {
if(idx != 0) buf.push(",\n");
buf.push("\n/***/ " + module.id + ":\n");
var source = moduleTemplate.render(module, dependencyTemplates);
buf.push(source.source());
});
buf.push("\n");
addLine(0, "})");
return new StringSource(buf.join(""));
};
NodeMainTemplate.prototype.updateHash = function(hash) {
hash.update("node");
hash.update("1");
hash.update(this.outputOptions.filename + "");
hash.update(this.outputOptions.chunkFilename + "");
};

View File

@ -19,26 +19,6 @@ NodeSourcePlugin.prototype.apply = function(compiler) {
this.state.current.addVariable("global", "this");
return true;
});
compiler.parser.plugin("expression __filename", function(expr) {
this.state.current.addVariable("__filename", JSON.stringify("/index.js"));
return true;
});
compiler.parser.plugin("expression __dirname", function(expr) {
this.state.current.addVariable("__dirname", JSON.stringify("/"));
return true;
});
compiler.parser.plugin("expression require.main", function(expr) {
var dep = new ConstDependency("require.cache[0]", expr.range);
dep.loc = expr.loc;
this.state.current.addDependency(dep);
return true;
});
compiler.parser.plugin("expression module.exports", ignore);
compiler.parser.plugin("expression module.loaded", ignore);
compiler.parser.plugin("expression module.id", ignore);
compiler.parser.plugin("expression module", function(expr) {
return ModuleParserHelpers.addParsedVariable(this, "module", "require(" + JSON.stringify(path.join(__dirname, "..", "..", "buildin", "module.js")) + ")(module)");
});
compiler.resolvers.normal.apply(
new ModuleAliasPlugin((function() {
return [

View File

@ -0,0 +1,113 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var Dependency = require("../Dependency");
var Module = require("../Module");
var RawSource = require("webpack-core/lib/RawSource");
function NodeNativeDependency(request, range) {
Dependency.call(this);
this.Class = NodeNativeDependency;
this.userRequest = request;
this.request = request;
this.range = range;
}
NodeNativeDependency.prototype = Object.create(Dependency.prototype);
NodeNativeDependency.prototype.type = "native module";
NodeNativeDependency.prototype.isEqualResource = function isEqualResource(other) {
if(!(other instanceof NodeNativeDependency))
return false;
return this.request == other.request;
};
NodeNativeDependency.Template = require("../dependencies/ModuleDependencyTemplateAsRequireId");
function NodeNativeCommonJsDependency(request, range) {
NodeNativeDependency.call(this, request, range);
this.Class = NodeNativeCommonJsDependency;
}
NodeNativeCommonJsDependency.prototype = Object.create(NodeNativeDependency.prototype);
NodeNativeCommonJsDependency.Template = require("../dependencies/ModuleDependencyTemplateAsId");
function NodeNativeModule(request) {
Module.call(this);
this.request = request;
this.built = false;
this.cacheable = true;
}
NodeNativeModule.prototype = Object.create(Module.prototype);
NodeNativeModule.prototype.identifier = NodeNativeModule.prototype.readableIdentifier = function() {
return this.request;
};
NodeNativeModule.prototype.build = function(options, compilation, resolver, fs, callback) {callback()};
NodeNativeModule.prototype.source = function() {
return new RawSource("module.exports = require.parentRequire(" + JSON.stringify(this.request) + ");");
};
NodeNativeModule.prototype.needRebuild = function() {
return false;
};
NodeNativeModule.prototype.size = function() {
return 42 + this.request.length;
};
function NodeNativeModuleFactory() {
}
NodeNativeModuleFactory.prototype.create = function(context, dependency, callback) {
return callback(null, new NodeNativeModule(dependency.request));
}
function NodeTargetPlugin() {
}
module.exports = NodeTargetPlugin;
NodeTargetPlugin.prototype.apply = function(compiler) {
compiler.plugin("compilation", function(compilation, params) {
compilation.dependencyFactories.set(NodeNativeDependency, new NodeNativeModuleFactory());
compilation.dependencyTemplates.set(NodeNativeDependency, new NodeNativeDependency.Template());
compilation.dependencyFactories.set(NodeNativeCommonJsDependency, new NodeNativeModuleFactory());
compilation.dependencyTemplates.set(NodeNativeCommonJsDependency, new NodeNativeCommonJsDependency.Template());
});
var natives = Object.keys(process.binding("natives"));
compiler.parser.plugin("call require:commonjs:item", function(expr, param) {
if(param.isString() && natives.indexOf(param.string) >= 0) {
var dep = new NodeNativeCommonJsDependency(param.string, param.range);
this.state.current.addDependency(dep);
return true;
}
});
compiler.parser.plugin("call define:amd:item", function(expr, param) {
if(param.isString() && natives.indexOf(param.string) >= 0) {
var dep = new NodeNativeDependency(param.string, param.range);
this.state.current.addDependency(dep);
return true;
}
});
compiler.parser.plugin("call require:amd:item", function(expr, param) {
if(param.isString() && natives.indexOf(param.string) >= 0) {
var dep = new NodeNativeDependency(param.string, param.range);
this.state.current.addDependency(dep);
return true;
}
});
};

View File

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var NodeMainTemplate = require("./NodeMainTemplate");
var NodeChunkTemplate = require("./NodeChunkTemplate");
function WebWorkerTemplatePlugin(options) {
this.options = options;
}
module.exports = WebWorkerTemplatePlugin;
WebWorkerTemplatePlugin.prototype.apply = function(compiler) {
var options = this.options;
compiler.mainTemplate = new NodeMainTemplate(options);
compiler.chunkTemplate = new NodeChunkTemplate(options);
compiler.plugin("compilation", function(compilation) {
compilation.plugin("normal-module-loader", function(loaderContext) {
loaderContext.target = "node";
});
});
};

View File

@ -4,7 +4,6 @@
*/
var Compiler = require("./Compiler");
var NodeEnvironmentPlugin = require("./node/NodeEnvironmentPlugin");
var NodeSourcePlugin = require("./node/NodeSourcePlugin");
var WebpackOptionsApply = require("./WebpackOptionsApply");
var WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter");
@ -15,7 +14,6 @@ function webpack(options, callback) {
compiler.options = options;
compiler.options = new WebpackOptionsApply().process(options, compiler);
new NodeEnvironmentPlugin(options.separate).apply(compiler);
new NodeSourcePlugin().apply(compiler);
if(callback) {
if(options.watch) {
return compiler.watch(options.watchDelay, callback);

View File

@ -1,6 +1,6 @@
{
"name": "webpack",
"version": "0.9.0-beta20",
"version": "0.9.0-beta21",
"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,41 @@
var should = require("should");
var path = require("path");
var webpack = require("../lib/webpack");
describe("NodeTemplatePlugin", function() {
it("should compile and run a simple module", function(done) {
webpack({
context: path.join(__dirname, "fixtures", "nodetest"),
target: "node",
output: {
path: path.join(__dirname, "js"),
filename: "result.js",
chunkFilename: "[hash].result[id].js",
libraryTarget: "commonjs2",
},
entry: "./entry",
}, function(err, stats) {
if(err) return err;
// console.log(stats.toString({colors: true}));
stats.hasErrors().should.be.not.ok;
stats.hasWarnings().should.be.not.ok;
var result = require("./js/result");
result.nextTick.should.be.equal(process.nextTick);
result.fs.should.be.equal(require("fs"));
result.loadChunk(456, function(chunk) {
chunk.should.be.eql(123);
var sameTick = true;
result.loadChunk(567, function(chunk) {
chunk.should.be.eql({a: 1});
sameTick.should.be.eql(true);
done();
});
sameTick = false;
});
});
});
});

7
test/fixtures/nodetest/entry.js vendored Normal file
View File

@ -0,0 +1,7 @@
exports.loadChunk = function(id, cb) {
require(["./file" + id], function(result) {
cb(result);
});
};
exports.nextTick = process.nextTick;
exports.fs = require("fs");

1
test/fixtures/nodetest/file456.js vendored Normal file
View File

@ -0,0 +1 @@
module.exports = 123;

3
test/fixtures/nodetest/file567.js vendored Normal file
View File

@ -0,0 +1,3 @@
define({
a: 1
});