diff --git a/LICENSE b/LICENSE index 7b27f65df..3f459beda 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ (The MIT License) -Copyright (c) 2012 Tobias Koppers +Copyright (c) 2012 - 2013 Tobias Koppers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/lib/APIPlugin.js b/lib/APIPlugin.js index ee03faade..43905dedc 100644 --- a/lib/APIPlugin.js +++ b/lib/APIPlugin.js @@ -3,6 +3,7 @@ Author Tobias Koppers @sokra */ var ConstDependency = require("./dependencies/ConstDependency"); +var BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); function APIPlugin() { } @@ -14,6 +15,12 @@ var REPLACEMENTS = { __webpack_modules__: "require.modules", __webpack_chunk_load__: "require.e", }; +var REPLACEMENT_TYPES = { + __webpack_public_path__: "string", + __webpack_require__: "function", + __webpack_modules__: "object", + __webpack_chunk_load__: "function", +}; var IGNORES = [ "call require.valueOf", "expression require.onError", @@ -26,6 +33,9 @@ APIPlugin.prototype.apply = function(compiler) { this.state.current.addDependency(dep); return true; }); + compiler.parser.plugin("evaluate typeof "+key, function(expr) { + return new BasicEvaluatedExpression().setString(REPLACEMENT_TYPES[key]).setRange(expr.range); + }); }); IGNORES.forEach(function(key) { compiler.parser.plugin(key, function(expr) { diff --git a/lib/Compilation.js b/lib/Compilation.js index 7c951851b..a15674a6f 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -508,14 +508,14 @@ Compilation.prototype.createHash = function createHash() { var hashFunction = outputOptions.hashFunction; var hashDigest = outputOptions.hashDigest; var hashDigestLength = outputOptions.hashDigestLength; - var hash = new (require("crypto").Hash)(hashFunction); + var hash = require("crypto").createHash(hashFunction); this.mainTemplate.updateHash(hash); this.chunkTemplate.updateHash(hash); this.moduleTemplate.updateHash(hash); var i, chunk; for(i = 0; i < this.chunks.length; i++) { var chunk = this.chunks[i]; - var chunkHash = new (require("crypto").Hash)(hashFunction); + var chunkHash = require("crypto").createHash(hashFunction); chunk.updateHash(chunkHash); this.chunkTemplate.updateHash(chunkHash); chunk.hash = chunkHash.digest(hashDigest); @@ -531,7 +531,7 @@ Compilation.prototype.modifyHash = function modifyHash(update) { var hashFunction = outputOptions.hashFunction; var hashDigest = outputOptions.hashDigest; var hashDigestLength = outputOptions.hashDigestLength; - var hash = new (require("crypto").Hash)(hashFunction); + var hash = require("crypto").createHash(hashFunction); hash.update(this.fullHash); hash.update(update); this.fullHash = hash.digest(hashDigest); diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index de9c1d076..7c86488a8 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -36,7 +36,7 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) { records.moduleHashs = {}; this.modules.forEach(function(module) { var identifier = module.identifier(); - var hash = new (require("crypto")).Hash("md5"); + var hash = require("crypto").createHash("md5"); module.updateHash(hash); records.moduleHashs[identifier] = hash.digest("hex"); }); @@ -70,7 +70,7 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) { var moduleHashs = {}; this.modules.forEach(function(module) { var identifier = module.identifier(); - var hash = new (require("crypto")).Hash("md5"); + var hash = require("crypto").createHash("md5"); module.updateHash(hash); hash = hash.digest("hex"); module.hotUpdate = records.moduleHashs[identifier] !== hash; diff --git a/lib/NormalModule.js b/lib/NormalModule.js index a36220e13..0f132bc97 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -157,7 +157,7 @@ NormalModule.prototype.updateHash = function(hash) { NormalModule.prototype.getSourceHash = function() { if(!this._source) return ""; - var hash = new (require("crypto").Hash)("md5"); + var hash = require("crypto").createHash("md5"); hash.update(this._source.source()); return hash.digest("hex"); }; diff --git a/lib/RequestShortener.js b/lib/RequestShortener.js index 2d0749821..2ee4c2e63 100644 --- a/lib/RequestShortener.js +++ b/lib/RequestShortener.js @@ -6,19 +6,32 @@ var path = require("path"); function RequestShortener(directory) { var parentDirectory = path.dirname(directory); - var buildins = path.join(__dirname, ".."); - var currentDirectoryRegExp = directory.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); - currentDirectoryRegExp = new RegExp("^" + currentDirectoryRegExp + "|(!)" + currentDirectoryRegExp, "g"); - var buildinsAsModule = currentDirectoryRegExp.test(buildins); - var parentDirectoryRegExp = parentDirectory.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); - parentDirectoryRegExp = new RegExp("^" + parentDirectoryRegExp + "|(!)" + parentDirectoryRegExp, "g"); - var buildinsRegExp = buildins.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); - buildinsRegExp = new RegExp("^" + buildinsRegExp + "|(!)" + buildinsRegExp, "g"); + if(/[\/\\]$/.test(directory)) directory = directory.substr(0, directory.length - 1); + if(directory) { + var currentDirectoryRegExp = directory.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + currentDirectoryRegExp = new RegExp("^" + currentDirectoryRegExp + "|(!)" + currentDirectoryRegExp, "g"); + + this.currentDirectoryRegExp = currentDirectoryRegExp; + } + + if(/[\/\\]$/.test(parentDirectory)) parentDirectory = parentDirectory.substr(0, parentDirectory.length - 1); + if(parentDirectory && parentDirectory !== directory) { + var parentDirectoryRegExp = parentDirectory.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + parentDirectoryRegExp = new RegExp("^" + parentDirectoryRegExp + "|(!)" + parentDirectoryRegExp, "g"); + + this.parentDirectoryRegExp = parentDirectoryRegExp; + } + + if(__dirname.length >= 2) { + var buildins = path.join(__dirname, ".."); + var buildinsAsModule = currentDirectoryRegExp.test(buildins); + var buildinsRegExp = buildins.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + buildinsRegExp = new RegExp("^" + buildinsRegExp + "|(!)" + buildinsRegExp, "g"); + + this.buildinsAsModule = buildinsAsModule; + this.buildinsRegExp = buildinsRegExp; + } - this.buildinsAsModule = buildinsAsModule; - this.currentDirectoryRegExp = currentDirectoryRegExp; - this.parentDirectoryRegExp = parentDirectoryRegExp; - this.buildinsRegExp = buildinsRegExp; this.node_modulesRegExp = /\/node_modules\//g; this.index_jsRegExp = /\/index.js(!|\?|\(query\))/g; } @@ -27,11 +40,13 @@ module.exports = RequestShortener; RequestShortener.prototype.shorten = function(request) { if(!request) return request; - if(this.buildinsAsModule) + if(this.buildinsAsModule && this.buildinsRegExp) request = request.replace(this.buildinsRegExp, "!(webpack)"); - request = request.replace(this.currentDirectoryRegExp, "!."); - request = request.replace(this.parentDirectoryRegExp, "!.."); - if(!this.buildinsAsModule) + if(this.currentDirectoryRegExp) + request = request.replace(this.currentDirectoryRegExp, "!."); + if(this.parentDirectoryRegExp) + request = request.replace(this.parentDirectoryRegExp, "!.."); + if(!this.buildinsAsModule && this.buildinsRegExp) request = request.replace(this.buildinsRegExp, "!(webpack)"); request = request.replace(/\\/g, "/"); request = request.replace(this.node_modulesRegExp, "/~/"); diff --git a/lib/Stats.js b/lib/Stats.js index 17e84a5d8..56fb084e8 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -191,6 +191,7 @@ Stats.prototype.toJson = function toJson(options, forToString) { }; Stats.prototype.toString = function toString(options) { + if(!options) options = {}; function d(v, d) { return v === undefined ? d : v } var useColors = d(options.colors, false); diff --git a/lib/WebpackOptionsApply.js b/lib/WebpackOptionsApply.js index acb7245c3..5a5065e5f 100644 --- a/lib/WebpackOptionsApply.js +++ b/lib/WebpackOptionsApply.js @@ -5,19 +5,11 @@ 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 SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); -var LibraryTemplatePlugin = require("./LibraryTemplatePlugin"); -var HotModuleReplacementPlugin = require("./HotModuleReplacementPlugin"); -var NoHotModuleReplacementPlugin = require("./NoHotModuleReplacementPlugin"); -var PrefetchPlugin = require("./PrefetchPlugin"); var SingleEntryPlugin = require("./SingleEntryPlugin"); var MultiEntryPlugin = require("./MultiEntryPlugin"); -var CachePlugin = require("./CachePlugin"); var RecordIdsPlugin = require("./RecordIdsPlugin"); var APIPlugin = require("./APIPlugin"); @@ -25,9 +17,6 @@ var ConstPlugin = require("./ConstPlugin"); var RequireJsStuffPlugin = require("./RequireJsStuffPlugin"); 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"); @@ -36,15 +25,10 @@ var RequireContextPlugin = require("./dependencies/RequireContextPlugin"); var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin"); var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin"); -var UglifyJsPlugin = require("./optimize/UglifyJsPlugin"); -var OccurenceOrderPlugin = require("./optimize/OccurenceOrderPlugin"); -var LimitChunkCountPlugin = require("./optimize/LimitChunkCountPlugin"); -var MinChunkSizePlugin = require("./optimize/MinChunkSizePlugin"); var RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin"); var RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin"); var MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin"); var FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin"); -var DedupePlugin = require("./optimize/DedupePlugin"); var UnsafeCachePlugin = require("enhanced-resolve/lib/UnsafeCachePlugin"); var ModulesInDirectoriesPlugin = require("enhanced-resolve/lib/ModulesInDirectoriesPlugin"); @@ -74,6 +58,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) { compiler.recordsOutputPath = options.recordsOutputPath || options.recordsPath; switch(options.target) { case "web": + var JsonpTemplatePlugin = require("./JsonpTemplatePlugin"); + var NodeSourcePlugin = require("./node/NodeSourcePlugin"); compiler.apply( new JsonpTemplatePlugin(options.output), new FunctionModulePlugin(options.context, options.output), @@ -81,6 +67,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) { ); break; case "webworker": + var WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin"); + var NodeSourcePlugin = require("./node/NodeSourcePlugin"); compiler.apply( new WebWorkerTemplatePlugin(options.output), new FunctionModulePlugin(options.context, options.output), @@ -88,6 +76,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) { ); break; case "node": + var NodeTemplatePlugin = require("./node/NodeTemplatePlugin"); + var NodeTargetPlugin = require("./node/NodeTargetPlugin"); compiler.apply( new NodeTemplatePlugin(options.output), new FunctionModulePlugin(options.context, options.output), @@ -96,12 +86,15 @@ WebpackOptionsApply.prototype.process = function(options, compiler) { break; } if(options.output.library || options.output.libraryTarget != "var") { + var LibraryTemplatePlugin = require("./LibraryTemplatePlugin"); compiler.apply(new LibraryTemplatePlugin(options.output.library, options.output.libraryTarget)); } if(options.hot) { + var HotModuleReplacementPlugin = require("./HotModuleReplacementPlugin"); compiler.apply(new HotModuleReplacementPlugin(options.output)); } else { + var NoHotModuleReplacementPlugin = require("./NoHotModuleReplacementPlugin"); compiler.apply(new NoHotModuleReplacementPlugin()); } @@ -153,6 +146,7 @@ WebpackOptionsApply.prototype.process = function(options, compiler) { } if(options.prefetch) { + var PrefetchPlugin = require("./PrefetchPlugin"); options.prefetch.map(function(request) { compiler.apply(new PrefetchPlugin(options.context, request)); }); @@ -180,27 +174,41 @@ WebpackOptionsApply.prototype.process = function(options, compiler) { compiler.apply(new RecordIdsPlugin()); - if(options.optimize && options.optimize.occurenceOrder) + if(options.optimize && options.optimize.occurenceOrder) { + var OccurenceOrderPlugin = require("./optimize/OccurenceOrderPlugin"); compiler.apply(new OccurenceOrderPlugin(options.optimize.occurenceOrderPreferEntry)); + } - if(options.optimize && options.optimize.minChunkSize) + if(options.optimize && options.optimize.minChunkSize) { + var MinChunkSizePlugin = require("./optimize/MinChunkSizePlugin"); compiler.apply(new MinChunkSizePlugin(options.optimize)); + } - if(options.optimize && options.optimize.maxChunks) + if(options.optimize && options.optimize.maxChunks) { + var LimitChunkCountPlugin = require("./optimize/LimitChunkCountPlugin"); compiler.apply(new LimitChunkCountPlugin(options.optimize)); + } - if(options.optimize.minimize === true) - compiler.apply(new UglifyJsPlugin()); - else if(options.optimize.minimize) - compiler.apply(new UglifyJsPlugin(options.optimize.minimize)); + if(options.optimize.minimize) { + var UglifyJsPlugin = require("./optimize/UglifyJsPlugin"); + if(options.optimize.minimize === true) + compiler.apply(new UglifyJsPlugin()); + else + compiler.apply(new UglifyJsPlugin(options.optimize.minimize)); + } - if(options.optimize.dedupe === true) + if(options.optimize.dedupe === true) { + var DedupePlugin = require("./optimize/DedupePlugin"); compiler.apply(new DedupePlugin()); + } - if(options.cache === undefined ? options.watch : options.cache) + if(options.cache === undefined ? options.watch : options.cache) { + var CachePlugin = require("./CachePlugin"); compiler.apply(new CachePlugin(typeof options.cache == "object" ? options.cache : null)); + } if(typeof options.provide === "object") { + var ProvidePlugin = require("./ProvidePlugin"); for(var name in options.provide) { compiler.apply(new ProvidePlugin(name, options.provide[name])); } diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js index eb3c608dd..8c8312201 100644 --- a/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -15,8 +15,10 @@ module.exports = AbstractPlugin.create({ switch(expr.arguments.length) { case 1: if(expr.arguments[0].type == "FunctionExpression") { + // define(f() {...}) fn = expr.arguments[0]; } else { + // define({...}) var dep = new AMDDefineDependency(expr.range, expr.arguments[0].range); dep.loc = expr.loc; this.state.current.addDependency(dep); @@ -24,14 +26,18 @@ module.exports = AbstractPlugin.create({ } break; case 2: - if(expr.arguments[0].type == "ArrayExpression" && expr.arguments[1].type == "FunctionExpression") { + if(expr.arguments[0].type == "ArrayExpression") { + // define([...], f() {...}) array = expr.arguments[0]; fn = expr.arguments[1]; - } else if(expr.arguments[0].type == "Literal" && expr.arguments[1].type == "FunctionExpression") { - fn = expr.arguments[1]; } else if(expr.arguments[0].type == "Literal" && expr.arguments[1].type == "ArrayExpression") { + // define("...", [...]) array = expr.arguments[1]; + } else if(expr.arguments[0].type == "Literal" && expr.arguments[1].type == "FunctionExpression") { + // define("...", f() {...}) + fn = expr.arguments[1]; } else if(expr.arguments[0].type == "Literal") { + // define("...", {...}) var dep = new AMDDefineDependency(expr.range, expr.arguments[1].range); dep.loc = expr.loc; this.state.current.addDependency(dep); @@ -40,8 +46,8 @@ module.exports = AbstractPlugin.create({ break; case 3: if(expr.arguments[0].type == "Literal" && - expr.arguments[1].type == "ArrayExpression" && - expr.arguments[2].type == "FunctionExpression") { + expr.arguments[1].type == "ArrayExpression") { + // define("...", [...], f() {...}) array = expr.arguments[1]; fn = expr.arguments[2]; } @@ -57,7 +63,7 @@ module.exports = AbstractPlugin.create({ } }, this); } - if(fn) { + if(fn && fn.type === "FunctionExpression") { var inTry = this.scope.inTry; this.inScope(fn.params.filter(function(i) { return ["require", "module", "exports"].indexOf(i.name) < 0; diff --git a/lib/web/WebEnvironmentPlugin.js b/lib/web/WebEnvironmentPlugin.js new file mode 100644 index 000000000..8093c0011 --- /dev/null +++ b/lib/web/WebEnvironmentPlugin.js @@ -0,0 +1,16 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +function WebEnvironmentPlugin(inputFileSystem, outputFileSystem) { + this.inputFileSystem = inputFileSystem; + this.outputFileSystem = outputFileSystem; +} +module.exports = WebEnvironmentPlugin; +WebEnvironmentPlugin.prototype.apply = function(compiler) { + var inputFileSystem = compiler.inputFileSystem = this.inputFileSystem; + compiler.resolvers.normal.fileSystem = compiler.inputFileSystem; + compiler.resolvers.context.fileSystem = compiler.inputFileSystem; + compiler.resolvers.loader.fileSystem = compiler.inputFileSystem; + compiler.outputFileSystem = this.outputFileSystem; +}; \ No newline at end of file diff --git a/lib/webpack.js b/lib/webpack.js index d83aa7875..0b11e51a6 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -13,7 +13,7 @@ function webpack(options, callback) { var compiler = new Compiler(); compiler.options = options; compiler.options = new WebpackOptionsApply().process(options, compiler); - new NodeEnvironmentPlugin(options.separate).apply(compiler); + new NodeEnvironmentPlugin().apply(compiler); if(callback) { if(options.watch) { return compiler.watch(options.watchDelay, callback); diff --git a/lib/webpack.web.js b/lib/webpack.web.js new file mode 100644 index 000000000..ba677443d --- /dev/null +++ b/lib/webpack.web.js @@ -0,0 +1,27 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +var Compiler = require("./Compiler"); +var WebEnvironmentPlugin = require("./web/WebEnvironmentPlugin"); +var WebpackOptionsApply = require("./WebpackOptionsApply"); +var WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter"); + +function webpack(options, callback) { + new WebpackOptionsDefaulter().process(options); + + var compiler = new Compiler(); + compiler.options = options; + compiler.options = new WebpackOptionsApply().process(options, compiler); + new WebEnvironmentPlugin(options.inputFileSystem, options.outputFileSystem).apply(compiler); + if(callback) { + compiler.run(callback); + } + return compiler; +} +module.exports = webpack; + +webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; +webpack.WebpackOptionsApply = WebpackOptionsApply; +webpack.Compiler = Compiler; +webpack.WebEnvironmentPlugin = WebEnvironmentPlugin; diff --git a/package.json b/package.json index 6a28730e0..45152b6d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "0.11.0-beta12", + "version": "0.11.0-beta13", "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.", "dependencies": { @@ -48,6 +48,7 @@ }, "homepage": "http://github.com/webpack/webpack", "main": "lib/webpack.js", + "web": "lib/webpack.web.js", "bin": "./bin/webpack.js", "scripts": { "test": "mocha --reporter spec" diff --git a/web_modules/node-libs-browser.js b/web_modules/node-libs-browser.js new file mode 100644 index 000000000..e69de29bb