diff --git a/lib/Compilation.js b/lib/Compilation.js index d7f8bfe70..9802bed40 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -96,6 +96,7 @@ Compilation.prototype.addModule = function(module, cacheGroup) { module.lastId = cacheModule.id; } } + module.unbuild(); this._modules[identifier] = module; if(this.cache) { this.cache[cacheGroup + identifier] = module; @@ -190,7 +191,7 @@ Compilation.prototype.addModuleDependencies = function(module, dependencies, bai } factories[i] = [factory, dependencies[i]]; } - async.forEach(factories, function(item, callback) { + async.forEach(factories, function iteratorFactory(item, callback) { var dependencies = item[1]; var errorAndCallback = function errorAndCallback(err) { @@ -215,7 +216,7 @@ Compilation.prototype.addModuleDependencies = function(module, dependencies, bai }, context: module.context, dependencies: dependencies - }, function(err, dependentModule) { + }, function factoryCallback(err, dependentModule) { function isOptional() { return dependencies.filter(function(d) { return !d.optional; @@ -322,7 +323,7 @@ Compilation.prototype.addModuleDependencies = function(module, dependencies, bai }); }); - }, function(err) { + }, function finalCallbackAddModuleDependencies(err) { // In V8, the Error objects keep a reference to the functions on the stack. These warnings & // errors are created inside closures that keep a reference to the Compilation, so errors are // leaking the Compilation object. Setting _this to null workarounds the following issue in V8. @@ -333,7 +334,7 @@ Compilation.prototype.addModuleDependencies = function(module, dependencies, bai return callback(err); } - return callback(); + return process.nextTick(callback); }); }; @@ -501,7 +502,7 @@ Compilation.prototype.rebuildModule = function(module, thisCallback) { }; Compilation.prototype.finish = function finish() { - this.applyPlugins("finish-modules", this.modules); + this.applyPlugins1("finish-modules", this.modules); this.modules.forEach(function(m) { this.reportDependencyWarnings(m, [m]); }, this); @@ -520,7 +521,7 @@ Compilation.prototype.unseal = function unseal() { Compilation.prototype.seal = function seal(callback) { var self = this; - self.applyPlugins("seal"); + self.applyPlugins0("seal"); self.nextFreeModuleIndex = 0; self.nextFreeModuleIndex2 = 0; self.preparedChunks.forEach(function(preparedChunk) { @@ -541,71 +542,71 @@ Compilation.prototype.seal = function seal(callback) { } }, self); self.sortModules(self.modules); - self.applyPlugins("optimize"); + self.applyPlugins0("optimize"); - while(self.applyPluginsBailResult("optimize-modules-basic", self.modules) || - self.applyPluginsBailResult("optimize-modules", self.modules) || - self.applyPluginsBailResult("optimize-modules-advanced", self.modules)); // eslint-disable-line no-extra-semi - self.applyPlugins("after-optimize-modules", self.modules); + while(self.applyPluginsBailResult1("optimize-modules-basic", self.modules) || + self.applyPluginsBailResult1("optimize-modules", self.modules) || + self.applyPluginsBailResult1("optimize-modules-advanced", self.modules)); // eslint-disable-line no-extra-semi + self.applyPlugins1("after-optimize-modules", self.modules); - while(self.applyPluginsBailResult("optimize-chunks-basic", self.chunks) || - self.applyPluginsBailResult("optimize-chunks", self.chunks) || - self.applyPluginsBailResult("optimize-chunks-advanced", self.chunks)); // eslint-disable-line no-extra-semi - self.applyPlugins("after-optimize-chunks", self.chunks); + while(self.applyPluginsBailResult1("optimize-chunks-basic", self.chunks) || + self.applyPluginsBailResult1("optimize-chunks", self.chunks) || + self.applyPluginsBailResult1("optimize-chunks-advanced", self.chunks)); // eslint-disable-line no-extra-semi + self.applyPlugins1("after-optimize-chunks", self.chunks); - self.applyPluginsAsync("optimize-tree", self.chunks, self.modules, function(err) { + self.applyPluginsAsyncSeries("optimize-tree", self.chunks, self.modules, function sealPart2(err) { if(err) { return callback(err); } - self.applyPlugins("after-optimize-tree", self.chunks, self.modules); + self.applyPlugins2("after-optimize-tree", self.chunks, self.modules); var shouldRecord = self.applyPluginsBailResult("should-record") !== false; self.sortItemsBeforeIds(); - self.applyPlugins("revive-modules", self.modules, self.records); - self.applyPlugins("optimize-module-order", self.modules); - self.applyPlugins("advanced-optimize-module-order", self.modules); - self.applyPlugins("before-module-ids", self.modules); - self.applyPlugins("module-ids", self.modules); + self.applyPlugins2("revive-modules", self.modules, self.records); + self.applyPlugins1("optimize-module-order", self.modules); + self.applyPlugins1("advanced-optimize-module-order", self.modules); + self.applyPlugins1("before-module-ids", self.modules); + self.applyPlugins1("module-ids", self.modules); self.applyModuleIds(); - self.applyPlugins("optimize-module-ids", self.modules); - self.applyPlugins("after-optimize-module-ids", self.modules); + self.applyPlugins1("optimize-module-ids", self.modules); + self.applyPlugins1("after-optimize-module-ids", self.modules); self.sortItemsWithModuleIds(); - self.applyPlugins("revive-chunks", self.chunks, self.records); - self.applyPlugins("optimize-chunk-order", self.chunks); - self.applyPlugins("before-chunk-ids", self.chunks); + self.applyPlugins2("revive-chunks", self.chunks, self.records); + self.applyPlugins1("optimize-chunk-order", self.chunks); + self.applyPlugins1("before-chunk-ids", self.chunks); self.applyChunkIds(); - self.applyPlugins("optimize-chunk-ids", self.chunks); - self.applyPlugins("after-optimize-chunk-ids", self.chunks); + self.applyPlugins1("optimize-chunk-ids", self.chunks); + self.applyPlugins1("after-optimize-chunk-ids", self.chunks); self.sortItemswithChunkIds(); if(shouldRecord) - self.applyPlugins("record-modules", self.modules, self.records); + self.applyPlugins2("record-modules", self.modules, self.records); if(shouldRecord) - self.applyPlugins("record-chunks", self.chunks, self.records); + self.applyPlugins2("record-chunks", self.chunks, self.records); - self.applyPlugins("before-hash"); + self.applyPlugins0("before-hash"); self.createHash(); - self.applyPlugins("after-hash"); + self.applyPlugins0("after-hash"); if(shouldRecord) - self.applyPlugins("record-hash", self.records); + self.applyPlugins1("record-hash", self.records); - self.applyPlugins("before-module-assets"); + self.applyPlugins0("before-module-assets"); self.createModuleAssets(); if(self.applyPluginsBailResult("should-generate-chunk-assets") !== false) { - self.applyPlugins("before-chunk-assets"); + self.applyPlugins0("before-chunk-assets"); self.createChunkAssets(); } - self.applyPlugins("additional-chunk-assets", self.chunks); + self.applyPlugins1("additional-chunk-assets", self.chunks); self.summarizeDependencies(); if(shouldRecord) - self.applyPlugins("record", self, self.records); + self.applyPlugins2("record", self, self.records); self.applyPluginsAsync("additional-assets", function(err) { if(err) { @@ -615,12 +616,12 @@ Compilation.prototype.seal = function seal(callback) { if(err) { return callback(err); } - self.applyPlugins("after-optimize-chunk-assets", self.chunks); + self.applyPlugins1("after-optimize-chunk-assets", self.chunks); self.applyPluginsAsync("optimize-assets", self.assets, function(err) { if(err) { return callback(err); } - self.applyPlugins("after-optimize-assets", self.assets); + self.applyPlugins1("after-optimize-assets", self.assets); if(self.applyPluginsBailResult("need-additional-seal")) { self.unseal(); return self.seal(callback); diff --git a/lib/Compiler.js b/lib/Compiler.js index 426470056..2f084ab83 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -337,7 +337,7 @@ Compiler.prototype.emitAssets = function(compilation, callback) { } function afterEmit() { - this.applyPluginsAsync("after-emit", compilation, function(err) { + this.applyPluginsAsyncSeries1("after-emit", compilation, function(err) { if(err) return callback(err); return callback(); diff --git a/lib/ContextModule.js b/lib/ContextModule.js index cb189f4a5..3874a510c 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -87,9 +87,9 @@ ContextModule.prototype.needRebuild = function(fileTimestamps, contextTimestamps return ts >= this.builtTime; }; -ContextModule.prototype.disconnect = function disconnect() { +ContextModule.prototype.unbuild = function unbuild() { this.built = false; - Module.prototype.disconnect.call(this); + Module.prototype.unbuild.call(this); }; ContextModule.prototype.build = function(options, compilation, resolver, fs, callback) { diff --git a/lib/DelegatedModule.js b/lib/DelegatedModule.js index 3f1571117..2f0bc1b06 100644 --- a/lib/DelegatedModule.js +++ b/lib/DelegatedModule.js @@ -16,8 +16,7 @@ function DelegatedModule(sourceRequest, data, type, userRequest) { this.type = type; this.userRequest = userRequest; this.built = false; - this.usedExports = true; - this.providedExports = data.exports || true; + this.delegateData = data; } module.exports = DelegatedModule; @@ -39,12 +38,20 @@ DelegatedModule.prototype.needRebuild = function() { }; DelegatedModule.prototype.build = function(options, compilation, resolver, fs, callback) { + this.built = true; this.builtTime = new Date().getTime(); + this.usedExports = true; + this.providedExports = this.delegateData.exports || true; this.dependencies.length = 0; this.addDependency(new DelegatedSourceDependency(this.sourceRequest)); callback(); }; +DelegatedModule.prototype.unbuild = function() { + this.built = false; + Module.prototype.unbuild.call(this); +} + DelegatedModule.prototype.source = function() { var sourceModule = this.dependencies[0].module; var str; diff --git a/lib/Module.js b/lib/Module.js index 73ece8286..077d9e929 100644 --- a/lib/Module.js +++ b/lib/Module.js @@ -172,6 +172,10 @@ Module.prototype.sortItems = function() { }); }; +Module.prototype.unbuild = function() { + this.disconnect(); +}; + Module.prototype.identifier = null; Module.prototype.readableIdentifier = null; Module.prototype.build = null; diff --git a/lib/NormalModuleFactory.js b/lib/NormalModuleFactory.js index 65ef32beb..00d5f9bf3 100644 --- a/lib/NormalModuleFactory.js +++ b/lib/NormalModuleFactory.js @@ -45,6 +45,7 @@ function NormalModuleFactory(context, resolvers, options) { Tapable.call(this); this.resolvers = resolvers; this.ruleSet = new RuleSet(options.rules || options.loaders); + this.cachePredicate = typeof options.unsafeCache === "function" ? options.unsafeCache : Boolean.bind(null, options.unsafeCache); this.context = context || ""; this.parserCache = {}; this.plugin("factory", function() { @@ -101,6 +102,7 @@ function NormalModuleFactory(context, resolvers, options) { var contextInfo = data.contextInfo; var context = data.context; var request = data.request; + var resolveContextInfo = {}; var noAutoLoaders = /^-?!/.test(request); var noPrePostAutoLoaders = /^!!/.test(request); @@ -111,12 +113,12 @@ function NormalModuleFactory(context, resolvers, options) { async.parallel([ function(callback) { - _this.resolveRequestArray(contextInfo, context, elements, _this.resolvers.loader, callback); + _this.resolveRequestArray(resolveContextInfo, context, elements, _this.resolvers.loader, callback); }, function(callback) { if(resource === "" || resource[0] === "?") return callback(null, resource); - _this.resolvers.normal.resolve(contextInfo, context, resource, function(err, result) { + _this.resolvers.normal.resolve(resolveContextInfo, context, resource, function(err, result) { if(err) return callback(err); callback(null, result); }); @@ -175,9 +177,9 @@ function NormalModuleFactory(context, resolvers, options) { } }); async.parallel([ - _this.resolveRequestArray.bind(_this, contextInfo, _this.context, useLoadersPost, _this.resolvers.loader), - _this.resolveRequestArray.bind(_this, contextInfo, _this.context, useLoaders, _this.resolvers.loader), - _this.resolveRequestArray.bind(_this, contextInfo, _this.context, useLoadersPre, _this.resolvers.loader) + _this.resolveRequestArray.bind(_this, resolveContextInfo, _this.context, useLoadersPost, _this.resolvers.loader), + _this.resolveRequestArray.bind(_this, resolveContextInfo, _this.context, useLoaders, _this.resolvers.loader), + _this.resolveRequestArray.bind(_this, resolveContextInfo, _this.context, useLoadersPre, _this.resolvers.loader) ], function(err, results) { if(err) return callback(err); loaders = results[0].concat(loaders).concat(results[1]).concat(results[2]); @@ -207,8 +209,10 @@ NormalModuleFactory.prototype.constructor = NormalModuleFactory; NormalModuleFactory.prototype.create = function(data, callback) { var _this = this; - var context = data.context || this.context; var dependencies = data.dependencies; + var cacheEntry = dependencies[0].__NormalModuleFactoryCache; + if(cacheEntry) return callback(null, cacheEntry); + var context = data.context || this.context; var request = dependencies[0].request; var contextInfo = data.contextInfo || {}; _this.applyPluginsAsyncWaterfall("before-resolve", { @@ -227,7 +231,17 @@ NormalModuleFactory.prototype.create = function(data, callback) { // Ignored if(!factory) return callback(); - factory(result, callback); + factory(result, function(err, module) { + if(err) return callback(err); + + if(module && _this.cachePredicate(module)) { + dependencies.forEach(function(d) { + d.__NormalModuleFactoryCache = module; + }); + } + + callback(null, module); + }); }); }; @@ -272,6 +286,6 @@ NormalModuleFactory.prototype.getParser = function getParser(parserOptions) { NormalModuleFactory.prototype.createParser = function createParser(parserOptions) { var parser = new Parser(); - this.applyPlugins("parser", parser, parserOptions || {}); + this.applyPlugins2("parser", parser, parserOptions || {}); return parser; }; diff --git a/lib/Parser.js b/lib/Parser.js index 91d6a639e..5dcb6461d 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -178,7 +178,7 @@ Parser.prototype.initializeEvaluating = function() { if(expr.argument.type === "Identifier") { var name = this.scope.renames["$" + expr.argument.name] || expr.argument.name; if(this.scope.definitions.indexOf(name) === -1) { - res = this.applyPluginsBailResult("evaluate typeof " + name, expr); + res = this.applyPluginsBailResult1("evaluate typeof " + name, expr); if(res !== undefined) return res; } } @@ -193,7 +193,7 @@ Parser.prototype.initializeEvaluating = function() { exprName.unshift(this.scope.renames["$" + expression.name] || expression.name); if(this.scope.definitions.indexOf(name) === -1) { exprName = exprName.join("."); - res = this.applyPluginsBailResult("evaluate typeof " + exprName, expr); + res = this.applyPluginsBailResult1("evaluate typeof " + exprName, expr); if(res !== undefined) return res; } } @@ -224,11 +224,11 @@ Parser.prototype.initializeEvaluating = function() { this.plugin("evaluate Identifier", function(expr) { var name = this.scope.renames["$" + expr.name] || expr.name; if(this.scope.definitions.indexOf(expr.name) === -1) { - var result = this.applyPluginsBailResult("evaluate Identifier " + name, expr); + var result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr); if(result) return result; return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range); } else { - return this.applyPluginsBailResult("evaluate defined Identifier " + name, expr); + return this.applyPluginsBailResult1("evaluate defined Identifier " + name, expr); } }); this.plugin("evaluate MemberExpression", function(expression) { @@ -246,11 +246,11 @@ Parser.prototype.initializeEvaluating = function() { exprName.unshift(name); exprName = exprName.join("."); if(this.scope.definitions.indexOf(expr.name) === -1) { - var result = this.applyPluginsBailResult("evaluate Identifier " + exprName, expression); + var result = this.applyPluginsBailResult1("evaluate Identifier " + exprName, expression); if(result) return result; return new BasicEvaluatedExpression().setIdentifier(exprName).setRange(expression.range); } else { - return this.applyPluginsBailResult("evaluate defined Identifier " + exprName, expression); + return this.applyPluginsBailResult1("evaluate defined Identifier " + exprName, expression); } } } @@ -427,7 +427,7 @@ Parser.prototype.isHoistedStatement = function isHoistedStatement(statement) { }; Parser.prototype.walkStatement = function walkStatement(statement) { - if(this.applyPluginsBailResult("statement", statement) !== undefined) return; + if(this.applyPluginsBailResult1("statement", statement) !== undefined) return; if(this["walk" + statement.type]) this["walk" + statement.type](statement); }; @@ -442,7 +442,7 @@ Parser.prototype.walkExpressionStatement = function walkExpressionStatement(stat }; Parser.prototype.walkIfStatement = function walkIfStatement(statement) { - var result = this.applyPluginsBailResult("statement if", statement); + var result = this.applyPluginsBailResult1("statement if", statement); if(result === undefined) { this.walkExpression(statement.test); this.walkStatement(statement.consequent); @@ -457,7 +457,7 @@ Parser.prototype.walkIfStatement = function walkIfStatement(statement) { }; Parser.prototype.walkLabeledStatement = function walkLabeledStatement(statement) { - var result = this.applyPluginsBailResult("label " + statement.label.name, statement); + var result = this.applyPluginsBailResult1("label " + statement.label.name, statement); if(result !== true) this.walkStatement(statement.body); }; @@ -568,7 +568,7 @@ Parser.prototype.walkExportNamedDeclaration = function walkExportNamedDeclaratio var source = statement.source.value; this.applyPluginsBailResult("export import", statement, source); } else { - this.applyPluginsBailResult("export", statement); + this.applyPluginsBailResult1("export", statement); } if(statement.declaration) { if(/Expression$/.test(statement.declaration.type)) { @@ -600,7 +600,7 @@ Parser.prototype.walkExportNamedDeclaration = function walkExportNamedDeclaratio }; Parser.prototype.walkExportDefaultDeclaration = function walkExportDefaultDeclaration(statement) { - this.applyPluginsBailResult("export", statement); + this.applyPluginsBailResult1("export", statement); if(/Declaration$/.test(statement.declaration.type)) { if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) { var pos = this.scope.definitions.length; @@ -657,16 +657,16 @@ Parser.prototype.walkVariableDeclarators = function walkVariableDeclarators(decl switch(declarator.type) { case "VariableDeclarator": var renameIdentifier = declarator.init && _this.getRenameIdentifier(declarator.init); - if(renameIdentifier && declarator.id.type === "Identifier" && _this.applyPluginsBailResult("can-rename " + renameIdentifier, declarator.init)) { + if(renameIdentifier && declarator.id.type === "Identifier" && _this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) { // renaming with "var a = b;" - if(!_this.applyPluginsBailResult("rename " + renameIdentifier, declarator.init)) { + if(!_this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) { _this.scope.renames["$" + declarator.id.name] = _this.scope.renames["$" + renameIdentifier] || renameIdentifier; var idx = _this.scope.definitions.indexOf(declarator.id.name); if(idx >= 0) _this.scope.definitions.splice(idx, 1); } } else { _this.enterPattern(declarator.id, function(name, decl) { - if(!_this.applyPluginsBailResult("var " + name, decl)) { + if(!_this.applyPluginsBailResult1("var " + name, decl)) { _this.scope.renames["$" + name] = undefined; _this.scope.definitions.push(name); } @@ -759,7 +759,7 @@ Parser.prototype.walkUnaryExpression = function walkUnaryExpression(expression) if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) { exprName.unshift(this.scope.renames["$" + expr.name] || expr.name); exprName = exprName.join("."); - var result = this.applyPluginsBailResult("typeof " + exprName, expression); + var result = this.applyPluginsBailResult1("typeof " + exprName, expression); if(result === true) return; } @@ -775,19 +775,19 @@ Parser.prototype.walkBinaryExpression = Parser.prototype.walkAssignmentExpression = function walkAssignmentExpression(expression) { var renameIdentifier = this.getRenameIdentifier(expression.right); - if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult("can-rename " + renameIdentifier, expression.right)) { + if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, expression.right)) { // renaming "a = b;" - if(!this.applyPluginsBailResult("rename " + renameIdentifier, expression.right)) { + if(!this.applyPluginsBailResult1("rename " + renameIdentifier, expression.right)) { this.scope.renames["$" + expression.left.name] = renameIdentifier; var idx = this.scope.definitions.indexOf(expression.left.name); if(idx >= 0) this.scope.definitions.splice(idx, 1); } } else if(expression.left.type === "Identifier") { - if(!this.applyPluginsBailResult("assigned " + expression.left.name, expression)) { + if(!this.applyPluginsBailResult1("assigned " + expression.left.name, expression)) { this.walkExpression(expression.right); } this.scope.renames["$" + expression.left.name] = undefined; - if(!this.applyPluginsBailResult("assign " + expression.left.name, expression)) { + if(!this.applyPluginsBailResult1("assign " + expression.left.name, expression)) { this.walkExpression(expression.left); } } else { @@ -798,7 +798,7 @@ Parser.prototype.walkAssignmentExpression = function walkAssignmentExpression(ex }; Parser.prototype.walkConditionalExpression = function walkConditionalExpression(expression) { - var result = this.applyPluginsBailResult("expression ?:", expression); + var result = this.applyPluginsBailResult1("expression ?:", expression); if(result === undefined) { this.walkExpression(expression.test); this.walkExpression(expression.consequent); @@ -846,8 +846,8 @@ Parser.prototype.walkCallExpression = function walkCallExpression(expression) { var params = functionExpression.params; args = args.map(function(arg) { var renameIdentifier = this.getRenameIdentifier(arg); - if(renameIdentifier && this.applyPluginsBailResult("can-rename " + renameIdentifier, arg)) { - if(!this.applyPluginsBailResult("rename " + renameIdentifier, arg)) + if(renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, arg)) { + if(!this.applyPluginsBailResult1("rename " + renameIdentifier, arg)) return renameIdentifier; } this.walkExpression(arg); @@ -890,7 +890,7 @@ Parser.prototype.walkCallExpression = function walkCallExpression(expression) { var callee = this.evaluateExpression(expression.callee); if(callee.isIdentifier()) { - result = this.applyPluginsBailResult("call " + callee.identifier, expression); + result = this.applyPluginsBailResult1("call " + callee.identifier, expression); if(result === true) return; } @@ -913,11 +913,11 @@ Parser.prototype.walkMemberExpression = function walkMemberExpression(expression } if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) { exprName.unshift(this.scope.renames["$" + expr.name] || expr.name); - var result = this.applyPluginsBailResult("expression " + exprName.join("."), expression); + var result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression); if(result === true) return; exprName[exprName.length - 1] = "*"; - result = this.applyPluginsBailResult("expression " + exprName.join("."), expression); + result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression); if(result === true) return; } @@ -928,7 +928,7 @@ Parser.prototype.walkMemberExpression = function walkMemberExpression(expression Parser.prototype.walkIdentifier = function walkIdentifier(expression) { if(this.scope.definitions.indexOf(expression.name) === -1) { - var result = this.applyPluginsBailResult("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression); + var result = this.applyPluginsBailResult1("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression); if(result === true) return; } diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index 47793e992..14197f2ea 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -25,6 +25,8 @@ function WebpackOptionsDefaulter() { this.set("module.wrappedContextRecursive", true); this.set("module.wrappedContextCritical", false); + this.set("module.unsafeCache", true); + this.set("output", "call", function(value, options) { if(typeof value === "string") { return { diff --git a/lib/optimize/OccurrenceOrderPlugin.js b/lib/optimize/OccurrenceOrderPlugin.js index 258f1497e..0c3969c87 100644 --- a/lib/optimize/OccurrenceOrderPlugin.js +++ b/lib/optimize/OccurrenceOrderPlugin.js @@ -23,16 +23,19 @@ OccurrenceOrderPlugin.prototype.apply = function(compiler) { } function occursInEntry(m) { - return m.reasons.map(function(r) { + if(typeof m.__OccurenceOrderPlugin_occursInEntry === "number") return m.__OccurenceOrderPlugin_occursInEntry; + var result = m.reasons.map(function(r) { if(!r.module) return 0; return entryChunks(r.module); }).reduce(function(a, b) { return a + b; }, 0) + entryChunks(m); + return m.__OccurenceOrderPlugin_occursInEntry = result; } function occurs(m) { - return m.reasons.map(function(r) { + if(typeof m.__OccurenceOrderPlugin_occurs === "number") return m.__OccurenceOrderPlugin_occurs; + var result = m.reasons.map(function(r) { if(!r.module) return 0; return r.module.chunks.length; }).reduce(function(a, b) { @@ -40,6 +43,7 @@ OccurrenceOrderPlugin.prototype.apply = function(compiler) { }, 0) + m.chunks.length + m.chunks.filter(function(c) { c.entryModule === m; }).length; + return m.__OccurenceOrderPlugin_occurs = result; } modules.sort(function(a, b) { if(preferEntry) { @@ -56,12 +60,19 @@ OccurrenceOrderPlugin.prototype.apply = function(compiler) { if(a.identifier() < b.identifier()) return -1; return 0; }); + // TODO refactor to Map + modules.forEach(function(m) { + delete m.__OccurenceOrderPlugin_occursInEntry; + delete m.__OccurenceOrderPlugin_occurs; + }); }); compilation.plugin("optimize-chunk-order", function(chunks) { function occursInEntry(c) { - return c.parents.filter(function(p) { + if(typeof c.__OccurenceOrderPlugin_occursInEntry === "number") return c.__OccurenceOrderPlugin_occursInEntry; + var result = c.parents.filter(function(p) { return p.isInitial(); }).length; + return c.__OccurenceOrderPlugin_occursInEntry = result; } function occurs(c) { @@ -91,6 +102,10 @@ OccurrenceOrderPlugin.prototype.apply = function(compiler) { } return 0; }); + // TODO refactor to Map + chunks.forEach(function(c) { + delete c.__OccurenceOrderPlugin_occursInEntry; + }); }); }); }; diff --git a/package.json b/package.json index 1de2538af..4d09cfc95 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "ajv": "^4.7.0", "ajv-keywords": "^1.1.1", "async": "^2.1.2", - "enhanced-resolve": "^2.2.0", + "enhanced-resolve": "^3.0.0", "interpret": "^1.0.0", "json-loader": "^0.5.4", "loader-runner": "^2.2.0", @@ -20,7 +20,7 @@ "object-assign": "^4.0.1", "source-map": "^0.5.3", "supports-color": "^3.1.0", - "tapable": "~0.2.3", + "tapable": "~0.2.5", "uglify-js": "~2.7.3", "watchpack": "^1.0.0", "webpack-sources": "^0.1.0", diff --git a/schemas/webpackOptionsSchema.json b/schemas/webpackOptionsSchema.json index f8095fd53..1baad605c 100644 --- a/schemas/webpackOptionsSchema.json +++ b/schemas/webpackOptionsSchema.json @@ -187,6 +187,16 @@ "unknownContextRequest": { "type": "string" }, + "unsafeCache": { + "anyOf": [ + { + "type": "boolean" + }, + { + "instanceof": "Function" + } + ] + }, "wrappedContextCritical": { "type": "boolean" },