UNPKG

webpack

Version:

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.

272 lines (254 loc) 9.19 kB
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ var Module = require("./Module"); var NormalModuleMixin = require("webpack-core/lib/NormalModuleMixin"); var SourceMapSource = require("webpack-core/lib/SourceMapSource"); var OriginalSource = require("webpack-core/lib/OriginalSource"); var RawSource = require("webpack-core/lib/RawSource"); var ReplaceSource = require("webpack-core/lib/ReplaceSource"); var ModuleParseError = require("./ModuleParseError"); var TemplateArgumentDependency = require("./dependencies/TemplateArgumentDependency"); var path = require("path"); function NormalModule(request, userRequest, rawRequest, loaders, resource, parser) { Module.call(this); this.request = request; this.userRequest = userRequest; this.rawRequest = rawRequest; this.parser = parser; NormalModuleMixin.call(this, loaders, resource); this.meta = {}; this.assets = {}; this.built = false; this._cachedSource = null; } module.exports = NormalModule; NormalModule.prototype = Object.create(Module.prototype); NormalModuleMixin.mixin(NormalModule.prototype); NormalModule.prototype.identifier = function() { return this.request; }; NormalModule.prototype.readableIdentifier = function(requestShortener) { return requestShortener.shorten(this.userRequest); }; NormalModule.prototype.fillLoaderContext = function fillLoaderContext(loaderContext, options, compilation) { loaderContext.webpack = true; loaderContext.sourceMap = !!this.useSourceMap; loaderContext.emitFile = function(name, content, sourceMap) { if(typeof sourceMap === "string") { this.assets[name] = new OriginalSource(content, sourceMap); } else if(sourceMap) { this.assets[name] = new SourceMapSource(content, name, sourceMap); } else { this.assets[name] = new RawSource(content); } }.bind(this); loaderContext._module = this; loaderContext._compilation = compilation; loaderContext._compiler = compilation.compiler; compilation.applyPlugins("normal-module-loader", loaderContext, this); }; NormalModule.prototype.disconnect = function disconnect() { this.built = false; Module.prototype.disconnect.call(this); }; NormalModule.prototype.build = function build(options, compilation, resolver, fs, callback) { this.buildTimestamp = new Date().getTime(); this.built = true; return this.doBuild(options, compilation, resolver, fs, function(err) { if(err) return callback(err); this.dependencies.length = 0; this.variables.length = 0; this.blocks.length = 0; this._cachedSource = null; if(options.module && options.module.noParse) { if(Array.isArray(options.module.noParse)) { if(options.module.noParse.some(function(regExp) { return typeof regExp === "string" ? this.request.indexOf(regExp) === 0 : regExp.test(this.request); }, this)) return callback(); } else if(typeof regExp === "string" ? this.request.indexOf(options.module.noParse) === 0 : options.module.noParse.test(this.request)) { return callback(); } } try { this.parser.parse(this._source.source(), { current: this, module: this, compilation: compilation, options: options }); } catch(e) { var source = this._source.source(); this._source = null; return callback(new ModuleParseError(this, source, e)); } return callback(); }.bind(this)); }; NormalModule.prototype.source = function(dependencyTemplates, outputOptions, requestShortener) { var hash = require("crypto").createHash("md5"); this.updateHash(hash); hash = hash.digest("hex"); if(this._cachedSource && this._cachedSource.hash === hash) { return this._cachedSource.source; } var _source = this._source; if(!_source) return new RawSource("throw new Error('No source availible');"); var source = new ReplaceSource(_source); this._cachedSource = { source: source, hash: hash }; var topLevelBlock = this; function doDep(dep) { var template = dependencyTemplates.get(dep.Class); if(!template) throw new Error("No template for dependency: " + dep.Class.name); template.apply(dep, source, outputOptions, requestShortener, dependencyTemplates); } function doVariable(vars, variable) { var name = variable.name; var expr = variable.expressionSource(dependencyTemplates, outputOptions, requestShortener); vars.push({name: name, expression: expr}); } function doBlock(block) { block.dependencies.forEach(doDep); block.blocks.forEach(doBlock); if(block.variables.length > 0) { var vars = []; block.variables.forEach(doVariable.bind(null, vars)); var varNames = []; var varExpressions = []; var varStartCode = ""; var varEndCode = ""; function emitFunction() { if(varNames.length === 0) return; varStartCode += "/* WEBPACK VAR INJECTION */(function(" + varNames.join(", ") + ") {"; // exports === this in the topLevelBlock, but exports do compress better... varEndCode = (topLevelBlock === block ? "}.call(exports, " : "}.call(this, ") + varExpressions.map(function(e) {return e.source()}).join(", ") + "))" + varEndCode; varNames.length = 0; varExpressions.length = 0; } vars.forEach(function(v) { if(varNames.indexOf(v.name) >= 0) emitFunction(); varNames.push(v.name); varExpressions.push(v.expression); }); emitFunction(); var start = block.range ? block.range[0] : 0; var end = block.range ? block.range[1] : _source.size(); if(varStartCode) source.insert(start + 0.5, varStartCode); if(varEndCode) source.insert(end + 0.5, "\n/* WEBPACK VAR INJECTION */" + varEndCode); } } doBlock(this); return source; }; NormalModule.prototype.needRebuild = function needRebuild(fileTimestamps, contextTimestamps) { var timestamp = 0; this.fileDependencies.forEach(function(file) { var ts = fileTimestamps[file]; if(!ts) timestamp = Infinity; if(ts > timestamp) timestamp = ts; }); this.contextDependencies.forEach(function(context) { var ts = contextTimestamps[context]; if(!ts) timestamp = Infinity; if(ts > timestamp) timestamp = ts; }); return timestamp >= this.buildTimestamp; }; NormalModule.prototype.size = function() { return this._source ? this._source.size() : -1; }; NormalModule.prototype.updateHash = function(hash) { if(this._source) { hash.update("source"); this._source.updateHash(hash); } else hash.update("null"); Module.prototype.updateHash.call(this, hash); }; NormalModule.prototype.getSourceHash = function() { if(!this._source) return ""; var hash = require("crypto").createHash("md5"); hash.update(this._source.source()); return hash.digest("hex"); }; NormalModule.prototype.getAllModuleDependencies = function() { var list = []; function doDep(dep) { if(dep.module && list.indexOf(dep.module) < 0) list.push(dep.module); } function doVariable(variable) { variable.dependencies.forEach(doDep); } function doBlock(block) { block.variables.forEach(doVariable); block.dependencies.forEach(doDep); block.blocks.forEach(doBlock); } doBlock(this); return list; }; NormalModule.prototype.createTemplate = function(keepModules) { var template = new NormalModule("", "", "", [], "", null); template._source = this._source; template.built = this.built; template.templateModules = keepModules; template._templateOrigin = this; template.readableIdentifier = function() { return "template of " + this._templateOrigin.id + " referencing " + keepModules.map(function(m) { return m.id; }).join(", "); }; var args = template.arguments = []; function doDeps(deps) { return deps.map(function(dep) { if(dep.module && keepModules.indexOf(dep.module) < 0) { var argName = "__webpack_module_template_argument_" + args.length + "__"; args.push(argName); return new TemplateArgumentDependency(argName, dep); } else { return dep; } }); } function doVariable(variable, newVariable) { variable.dependencies.forEach(doDep); } function doBlock(block, newBlock) { block.variables.forEach(function(variable) { var newDependencies = doDeps(variable.dependencies); newBlock.addVariable(variable.name, variable.expression, newDependencies); }); newBlock.dependencies = doDeps(block.dependencies); block.blocks.forEach(function(childBlock) { var newChildBlock = new AsyncDependenciesBlock(childBlock.name, childBlock.module, childBlock.loc); newBlock.addBlock(newChildBlock); doBlock(childBlock, newChildBlock); }); } doBlock(this, template); return template; }; NormalModule.prototype.getTemplateArguments = function(keepModules) { var list = []; function doDep(dep) { if(dep.module && keepModules.indexOf(dep.module) < 0) list.push(dep.module); } function doVariable(variable) { variable.dependencies.forEach(doDep); } function doBlock(block) { block.variables.forEach(doVariable); block.dependencies.forEach(doDep); block.blocks.forEach(doBlock); } doBlock(this); return list; };