diff --git a/examples/code-splitted-dedupe/README.md b/examples/code-splitted-dedupe/README.md index f4691c773..d9c30b2cb 100644 --- a/examples/code-splitted-dedupe/README.md +++ b/examples/code-splitted-dedupe/README.md @@ -87,11 +87,15 @@ require(["../dedupe/b"]); /******/ } /******/ for(moduleId in moreModules) { /******/ var _m = moreModules[moduleId]; +/******/ +/******/ // Check if module is deduplicated /******/ switch(typeof _m) { /******/ case "number": +/******/ // Module is a copy of another module /******/ modules[moduleId] = modules[_m]; /******/ break; /******/ case "object": +/******/ // Module can be created from a template /******/ modules[moduleId] = (function(_m) { /******/ var args = _m.slice(1), fn = modules[_m[0]]; /******/ return function (a,b,c) { @@ -100,6 +104,7 @@ require(["../dedupe/b"]); /******/ }(_m)); /******/ break; /******/ default: +/******/ // Normal module /******/ modules[moduleId] = _m; /******/ } /******/ } @@ -112,12 +117,15 @@ require(["../dedupe/b"]); /******/ }) /************************************************************************/ /******/ ((function(modules) { + // Check all modules for deduplicated modules for(var i in modules) { switch(typeof modules[i]) { case "number": + // Module is a copy of another module modules[i] = modules[modules[i]]; break; case "object": + // Module can be created from a template modules[i] = (function(_m) { var args = _m.slice(1), fn = modules[_m[0]]; return function (a,b,c) { @@ -360,10 +368,10 @@ webpackJsonp([4], ``` Hash: 46d170ad35acc40bf3ea -Version: webpack 0.10.0-beta20 -Time: 101ms +Version: webpack 0.10.0-beta22 +Time: 95ms Asset Size Chunks Chunk Names - output.js 4645 0 [emitted] main + output.js 4972 0 [emitted] main 1.output.js 1485 1, 3 [emitted] 2.output.js 877 2, 4 [emitted] 3.output.js 875 3 [emitted] @@ -377,8 +385,8 @@ chunk {1} 1.output.js 492 {0} [rendered] [3] (webpack)/~/bundle-loader?lazy!../dedupe/b/index.js 207 {1} [built] amd require bundle?lazy!../dedupe/b [0] ./example.js 2:0-51 [4] ../dedupe/z.js 34 {1} {2} {3} [built] - cjs require ../z [2] ../dedupe/b/index.js 4:4-19 cjs require ../z [1] ../dedupe/a/index.js 4:4-19 + cjs require ../z [2] ../dedupe/b/index.js 4:4-19 [5] ../dedupe/a/x.js 34 {1} {3} [built] cjs require ./x [1] ../dedupe/a/index.js 2:4-18 [6] ../dedupe/a/y.js 49 {1} {3} [built] @@ -391,8 +399,8 @@ chunk {2} 2.output.js 201 {0} [rendered] amd require ../dedupe/b [0] ./example.js 6:0-24 cjs require !!(webpack)\examples\dedupe\b\index.js [3] (webpack)/~/bundle-loader?lazy!../dedupe/b/index.js 3:5-126 [4] ../dedupe/z.js 34 {1} {2} {3} [built] - cjs require ../z [2] ../dedupe/b/index.js 4:4-19 cjs require ../z [1] ../dedupe/a/index.js 4:4-19 + cjs require ../z [2] ../dedupe/b/index.js 4:4-19 [7] ../dedupe/b/x.js 34 {2} {4} [built] cjs require ./x [2] ../dedupe/b/index.js 2:4-18 [8] ../dedupe/b/y.js 49 {2} {4} [built] @@ -402,8 +410,8 @@ chunk {3} 3.output.js 201 {0} [rendered] amd require ../dedupe/a [0] ./example.js 2:0-51 amd require ../dedupe/a [0] ./example.js 5:0-24 [4] ../dedupe/z.js 34 {1} {2} {3} [built] - cjs require ../z [2] ../dedupe/b/index.js 4:4-19 cjs require ../z [1] ../dedupe/a/index.js 4:4-19 + cjs require ../z [2] ../dedupe/b/index.js 4:4-19 [5] ../dedupe/a/x.js 34 {1} {3} [built] cjs require ./x [1] ../dedupe/a/index.js 2:4-18 [6] ../dedupe/a/y.js 49 {1} {3} [built] @@ -422,8 +430,8 @@ chunk {4} 4.output.js 167 {1} [rendered] ``` Hash: 46d170ad35acc40bf3ea -Version: webpack 0.10.0-beta20 -Time: 273ms +Version: webpack 0.10.0-beta22 +Time: 267ms Asset Size Chunks Chunk Names output.js 1151 0 [emitted] main 1.output.js 294 1, 3 [emitted] diff --git a/examples/dedupe/README.md b/examples/dedupe/README.md index 537e289a9..2c898382d 100644 --- a/examples/dedupe/README.md +++ b/examples/dedupe/README.md @@ -105,12 +105,15 @@ module.exports = {"this is": "z"}; /******/ }) /************************************************************************/ /******/ ((function(modules) { + // Check all modules for deduplicated modules for(var i in modules) { switch(typeof modules[i]) { case "number": + // Module is a copy of another module modules[i] = modules[modules[i]]; break; case "object": + // Module can be created from a template modules[i] = (function(_m) { var args = _m.slice(1), fn = modules[_m[0]]; return function (a,b,c) { @@ -207,29 +210,29 @@ module.exports = {"this is": "z"}; ## Uncompressed ``` -Hash: 4afc9f4631bed4b86de9 -Version: webpack 0.10.0-beta20 -Time: 42ms +Hash: 15b13398a7aae2eaaec9 +Version: webpack 0.10.0-beta22 +Time: 54ms Asset Size Chunks Chunk Names -output.js 3223 0 [emitted] main -chunk {0} output.js (main) 513 [rendered] - [0] ./example.js 73 {0} [built] +output.js 3362 0 [emitted] main +chunk {0} output.js (main) 528 [rendered] + [0] ./example.js 76 {0} [built] [1] ./z.js 34 {0} [built] cjs require ../z [2] ./a/index.js 4:4-19 cjs require ../z [5] ./b/index.js 4:4-19 - [2] ./a/index.js 80 {0} [built] + [2] ./a/index.js 84 {0} [built] cjs require ./a [0] ./example.js 1:8-22 [3] ./a/x.js 34 {0} [built] cjs require ./x [2] ./a/index.js 2:4-18 [4] ./a/y.js 49 {0} [built] cjs require ./y [2] ./a/index.js 3:4-18 - [5] ./b/index.js 80 {0} [built] + [5] ./b/index.js 84 {0} [built] cjs require ./b [0] ./example.js 2:8-22 [6] ./b/x.js 34 {0} [built] cjs require ./x [5] ./b/index.js 2:4-18 [7] ./b/y.js 49 {0} [built] cjs require ./y [5] ./b/index.js 3:4-18 - [8] 80 {0} [not cacheable] [built] + [8] 84 {0} [not cacheable] [built] template 1 [2] ./a/index.js template 1 [5] ./b/index.js ``` @@ -237,29 +240,29 @@ chunk {0} output.js (main) 513 [rendered] ## Minimized (uglify-js, no zip) ``` -Hash: 4afc9f4631bed4b86de9 -Version: webpack 0.10.0-beta20 -Time: 98ms +Hash: 15b13398a7aae2eaaec9 +Version: webpack 0.10.0-beta22 +Time: 137ms Asset Size Chunks Chunk Names -output.js 776 0 [emitted] main -chunk {0} output.js (main) 513 [rendered] - [0] ./example.js 73 {0} [built] +output.js 777 0 [emitted] main +chunk {0} output.js (main) 528 [rendered] + [0] ./example.js 76 {0} [built] [1] ./z.js 34 {0} [built] cjs require ../z [2] ./a/index.js 4:4-19 cjs require ../z [5] ./b/index.js 4:4-19 - [2] ./a/index.js 80 {0} [built] + [2] ./a/index.js 84 {0} [built] cjs require ./a [0] ./example.js 1:8-22 [3] ./a/x.js 34 {0} [built] cjs require ./x [2] ./a/index.js 2:4-18 [4] ./a/y.js 49 {0} [built] cjs require ./y [2] ./a/index.js 3:4-18 - [5] ./b/index.js 80 {0} [built] + [5] ./b/index.js 84 {0} [built] cjs require ./b [0] ./example.js 2:8-22 [6] ./b/x.js 34 {0} [built] cjs require ./x [5] ./b/index.js 2:4-18 [7] ./b/y.js 49 {0} [built] cjs require ./y [5] ./b/index.js 3:4-18 - [8] 80 {0} [not cacheable] [built] + [8] 84 {0} [not cacheable] [built] template 1 [2] ./a/index.js template 1 [5] ./b/index.js ``` \ No newline at end of file diff --git a/lib/optimize/DedupePlugin.js b/lib/optimize/DedupePlugin.js index 5c4931c66..3104ee91f 100644 --- a/lib/optimize/DedupePlugin.js +++ b/lib/optimize/DedupePlugin.js @@ -36,6 +36,7 @@ DedupePlugin.prototype.apply = function(compiler) { compilation.plugin("after-optimize-chunks", function(chunks) { var entryChunks = chunks.filter(function(c) { return c.entry; }); entryChunks.forEach(function(chunk) { // for each entry chunk + var hasDeduplicatedModules = false; (function x(dups, roots, visited, chunk) { var currentDups = []; var currentRoots = []; @@ -51,6 +52,7 @@ DedupePlugin.prototype.apply = function(compiler) { module.rootDuplicates[chunkIndex].push(module); module.rootDuplicates[chunkIndex].commonModules = mergeCommonModules(module.rootDuplicates[chunkIndex].commonModules, module.getAllModuleDependencies()); + hasDeduplicatedModules = true; } else { idx = dups.indexOf(module.duplicates); if(idx < 0) { @@ -65,6 +67,7 @@ DedupePlugin.prototype.apply = function(compiler) { module.rootDuplicates[chunkIndex] = roots[idx]; module.rootDuplicates[chunkIndex].commonModules = mergeCommonModules(module.rootDuplicates[chunkIndex].commonModules, module.getAllModuleDependencies()); + hasDeduplicatedModules = true; } } } @@ -83,9 +86,12 @@ DedupePlugin.prototype.apply = function(compiler) { chunk.addModule(template); template.addChunk(chunk); compilation.modules.push(template); + hasDeduplicatedModules = true; } }); }([], [], [], chunk)); + if(hasDeduplicatedModules) + chunk._DedupePlugin_hasDeduplicatedModules = true; }); }); function mergeCommonModules(commonModules, newModules) { @@ -96,17 +102,25 @@ DedupePlugin.prototype.apply = function(compiler) { }); compiler.moduleTemplate = new DedupModuleTemplateDecorator(compiler.moduleTemplate); compiler.mainTemplate = Object.create(compiler.mainTemplate); + var oldRenderAddModule = compiler.mainTemplate.renderAddModule; compiler.mainTemplate.renderAddModule = function(hash, chunk, varModuleId, varModule) { + if(!chunk._DedupePlugin_hasDeduplicatedModules) { + return oldRenderAddModule.call(this, hash, chunk, varModuleId, varModule); + } return [ "var _m = " + varModule + ";", + "", + "// Check if module is deduplicated", "switch(typeof _m) {", "case \"number\":", this.indent([ + "// Module is a copy of another module", "modules[" + varModuleId + "] = modules[_m];", "break;" ]), "case \"object\":", this.indent([ + "// Module can be created from a template", "modules[" + varModuleId + "] = (function(_m) {", this.indent([ "var args = _m.slice(1), fn = modules[_m[0]];", @@ -120,25 +134,34 @@ DedupePlugin.prototype.apply = function(compiler) { "break;" ]), "default:", - this.indent("modules[" + varModuleId + "] = _m;"), + this.indent([ + "// Normal module", + "modules[" + varModuleId + "] = _m;" + ]), "}" ] }; var oldRenderModules = compiler.mainTemplate.renderModules; compiler.mainTemplate.renderModules = function renderModules(hash, chunk, moduleTemplate, dependencyTemplates) { + if(!chunk._DedupePlugin_hasDeduplicatedModules) { + return oldRenderModules.call(this, hash, chunk, moduleTemplate, dependencyTemplates); + } var source = new ConcatSource(); source.add("(function(modules) {\n"); source.add(this.indent([ + "// Check all modules for deduplicated modules", "for(var i in modules) {", this.indent([ "switch(typeof modules[i]) {", "case \"number\":", this.indent([ + "// Module is a copy of another module", "modules[i] = modules[modules[i]];", "break;" ]), "case \"object\":", this.indent([ + "// Module can be created from a template", "modules[i] = (function(_m) {", this.indent([ "var args = _m.slice(1), fn = modules[_m[0]];", @@ -177,6 +200,10 @@ DedupModuleTemplateDecorator.prototype.render = function(module, dependencyTempl request: module.request, templateModules: rootDuplicates.template.templateModules }); + rootDuplicates.template.reasons.sort(function(a, b) { + if(a.request == b.request) return 0; + return a.request < b.request ? -1 : 1; + }); var array = [rootDuplicates.template.id].concat(module.getTemplateArguments(rootDuplicates.template.templateModules).map(function(module) { if(typeof module.id !== "number") return "(function webpackMissingModule() { throw new Error(" + JSON.stringify("Cannot find module") + "); }())" diff --git a/package.json b/package.json index ee405a008..7c7b421be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "0.10.0-beta21", + "version": "0.10.0-beta22", "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": {