webpack 2.5.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,16 +8,18 @@ const Module = require("./Module");
8
8
  const OriginalSource = require("webpack-sources").OriginalSource;
9
9
  const RawSource = require("webpack-sources").RawSource;
10
10
  const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
11
+ const DepBlockHelpers = require("./dependencies/DepBlockHelpers");
12
+ const Template = require("./Template");
11
13
 
12
14
  class ContextModule extends Module {
13
- constructor(resolveDependencies, context, recursive, regExp, addon, isAsync, chunkName) {
15
+ constructor(resolveDependencies, context, recursive, regExp, addon, asyncMode, chunkName) {
14
16
  super();
15
17
  this.resolveDependencies = resolveDependencies;
16
18
  this.context = context;
17
19
  this.recursive = recursive;
18
20
  this.regExp = regExp;
19
21
  this.addon = addon;
20
- this.async = !!isAsync;
22
+ this.async = asyncMode;
21
23
  this.cacheable = true;
22
24
  this.contextDependencies = [context];
23
25
  this.built = false;
@@ -44,7 +46,7 @@ class ContextModule extends Module {
44
46
  identifier() {
45
47
  let identifier = this.context;
46
48
  if(this.async)
47
- identifier += " async";
49
+ identifier += ` ${this.async}`;
48
50
  if(!this.recursive)
49
51
  identifier += " nonrecursive";
50
52
  if(this.addon)
@@ -58,7 +60,7 @@ class ContextModule extends Module {
58
60
  readableIdentifier(requestShortener) {
59
61
  let identifier = requestShortener.shorten(this.context);
60
62
  if(this.async)
61
- identifier += " async";
63
+ identifier += ` ${this.async}`;
62
64
  if(!this.recursive)
63
65
  identifier += " nonrecursive";
64
66
  if(this.addon)
@@ -72,7 +74,7 @@ class ContextModule extends Module {
72
74
  libIdent(options) {
73
75
  let identifier = this.contextify(options.context, this.context);
74
76
  if(this.async)
75
- identifier += " async";
77
+ identifier += ` ${this.async}`;
76
78
  if(this.recursive)
77
79
  identifier += " recursive";
78
80
  if(this.addon)
@@ -103,42 +105,67 @@ class ContextModule extends Module {
103
105
  this.resolveDependencies(fs, this.context, this.recursive, this.regExp, (err, dependencies) => {
104
106
  if(err) return callback(err);
105
107
 
108
+ // Reset children
109
+ this.dependencies = [];
110
+ this.blocks = [];
111
+
112
+ // abort if something failed
113
+ // this will create an empty context
106
114
  if(!dependencies) {
107
- this.dependencies = [];
108
115
  callback();
109
116
  return;
110
117
  }
111
118
 
112
- // enhance dependencies
119
+ // enhance dependencies with meta info
113
120
  dependencies.forEach(dep => {
114
121
  dep.loc = dep.userRequest;
115
122
  dep.request = this.addon + dep.request;
116
123
  });
117
124
 
118
- // if these we are not a async context
119
- // add dependencies and continue
120
- if(!this.async) {
125
+ if(!this.async || this.async === "eager") {
126
+
127
+ // if we have an sync or eager context
128
+ // just add all dependencies and continue
121
129
  this.dependencies = dependencies;
122
- callback();
123
- return;
124
- }
125
130
 
126
- // if we are async however create a new async dependency block
127
- // and add that block to this context
128
- dependencies.forEach(dep => {
129
- const block = new AsyncDependenciesBlock(this.chunkName, dep.module, dep.loc);
130
- block.addDependency(dep);
131
- this.addBlock(block);
132
- });
131
+ } else if(this.async === "lazy-once") {
132
+
133
+ // for the lazy-once mode create a new async dependency block
134
+ // and add that block to this context
135
+ if(dependencies.length > 0) {
136
+ const block = new AsyncDependenciesBlock(this.chunkName, this);
137
+ dependencies.forEach(dep => {
138
+ block.addDependency(dep);
139
+ });
140
+ this.addBlock(block);
141
+ }
142
+
143
+ } else {
144
+
145
+ // if we are lazy create a new async dependency block per dependency
146
+ // and add all blocks to this context
147
+ dependencies.forEach((dep, idx) => {
148
+ let chunkName = this.chunkName;
149
+ if(chunkName) {
150
+ if(!/\[(index|request)\]/.test(chunkName))
151
+ chunkName += "[index]";
152
+ chunkName = chunkName.replace(/\[index\]/g, idx);
153
+ chunkName = chunkName.replace(/\[request\]/g, Template.toPath(dep.userRequest));
154
+ }
155
+ const block = new AsyncDependenciesBlock(chunkName, dep.module, dep.loc);
156
+ block.addDependency(dep);
157
+ this.addBlock(block);
158
+ });
159
+ }
133
160
  callback();
134
161
  });
135
162
  }
136
163
 
137
- getSourceWithDependencies(dependencies, id) {
164
+ getUserRequestMap(dependencies) {
138
165
  // if we filter first we get a new array
139
166
  // therefor we dont need to create a clone of dependencies explicitly
140
167
  // therefore the order of this is !important!
141
- const map = dependencies
168
+ return dependencies
142
169
  .filter(dependency => dependency.module)
143
170
  .sort((a, b) => {
144
171
  if(a.userRequest === b.userRequest) {
@@ -149,6 +176,10 @@ class ContextModule extends Module {
149
176
  map[dep.userRequest] = dep.module.id;
150
177
  return map;
151
178
  }, Object.create(null));
179
+ }
180
+
181
+ getSyncSource(dependencies, id) {
182
+ const map = this.getUserRequestMap(dependencies);
152
183
  return `var map = ${JSON.stringify(map, null, "\t")};
153
184
  function webpackContext(req) {
154
185
  return __webpack_require__(webpackContextResolve(req));
@@ -167,7 +198,53 @@ module.exports = webpackContext;
167
198
  webpackContext.id = ${JSON.stringify(id)};`;
168
199
  }
169
200
 
170
- getSourceWithBlocks(blocks, id) {
201
+ getEagerSource(dependencies, id) {
202
+ const map = this.getUserRequestMap(dependencies);
203
+ return `var map = ${JSON.stringify(map, null, "\t")};
204
+ function webpackAsyncContext(req) {
205
+ return webpackAsyncContextResolve(req).then(__webpack_require__);
206
+ };
207
+ function webpackAsyncContextResolve(req) {
208
+ return new Promise(function(resolve, reject) {
209
+ var id = map[req];
210
+ if(!(id + 1)) // check for number or string
211
+ reject(new Error("Cannot find module '" + req + "'."));
212
+ else
213
+ resolve(id);
214
+ });
215
+ };
216
+ webpackAsyncContext.keys = function webpackAsyncContextKeys() {
217
+ return Object.keys(map);
218
+ };
219
+ webpackAsyncContext.resolve = webpackAsyncContextResolve;
220
+ module.exports = webpackAsyncContext;
221
+ webpackAsyncContext.id = ${JSON.stringify(id)};`;
222
+ }
223
+
224
+ getLazyOnceSource(block, dependencies, id, outputOptions, requestShortener) {
225
+ const promise = DepBlockHelpers.getDepBlockPromise(block, outputOptions, requestShortener, "lazy-once context");
226
+ const map = this.getUserRequestMap(dependencies);
227
+ return `var map = ${JSON.stringify(map, null, "\t")};
228
+ function webpackAsyncContext(req) {
229
+ return webpackAsyncContextResolve(req).then(__webpack_require__);
230
+ };
231
+ function webpackAsyncContextResolve(req) {
232
+ return ${promise}.then(function() {
233
+ var id = map[req];
234
+ if(!(id + 1)) // check for number or string
235
+ throw new Error("Cannot find module '" + req + "'.");
236
+ return id;
237
+ });
238
+ };
239
+ webpackAsyncContext.keys = function webpackAsyncContextKeys() {
240
+ return Object.keys(map);
241
+ };
242
+ webpackAsyncContext.resolve = webpackAsyncContextResolve;
243
+ module.exports = webpackAsyncContext;
244
+ webpackAsyncContext.id = ${JSON.stringify(id)};`;
245
+ }
246
+
247
+ getLazySource(blocks, id) {
171
248
  let hasMultipleOrNoChunks = false;
172
249
  const map = blocks
173
250
  .filter(block => block.dependencies[0].module)
@@ -219,15 +296,38 @@ module.exports = webpackEmptyContext;
219
296
  webpackEmptyContext.id = ${JSON.stringify(id)};`;
220
297
  }
221
298
 
222
- getSourceString() {
223
- if(this.dependencies && this.dependencies.length > 0) {
224
- return this.getSourceWithDependencies(this.dependencies, this.id);
225
- }
299
+ getSourceForEmptyAsyncContext(id) {
300
+ return `function webpackEmptyAsyncContext(req) {
301
+ return new Promise(function(resolve, reject) { reject(new Error("Cannot find module '" + req + "'.")); });
302
+ }
303
+ webpackEmptyAsyncContext.keys = function() { return []; };
304
+ webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
305
+ module.exports = webpackEmptyAsyncContext;
306
+ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
307
+ }
226
308
 
227
- if(this.blocks && this.blocks.length > 0) {
228
- return this.getSourceWithBlocks(this.blocks, this.id);
309
+ getSourceString(asyncMode, outputOptions, requestShortener) {
310
+ if(asyncMode === "lazy") {
311
+ if(this.blocks && this.blocks.length > 0) {
312
+ return this.getLazySource(this.blocks, this.id);
313
+ }
314
+ return this.getSourceForEmptyAsyncContext(this.id);
315
+ }
316
+ if(asyncMode === "eager") {
317
+ if(this.dependencies && this.dependencies.length > 0) {
318
+ return this.getEagerSource(this.dependencies, this.id);
319
+ }
320
+ return this.getSourceForEmptyAsyncContext(this.id);
321
+ } else if(asyncMode === "lazy-once") {
322
+ const block = this.blocks[0];
323
+ if(block) {
324
+ return this.getLazyOnceSource(block, block.dependencies, this.id, outputOptions, requestShortener);
325
+ }
326
+ return this.getSourceForEmptyAsyncContext(this.id);
327
+ }
328
+ if(this.dependencies && this.dependencies.length > 0) {
329
+ return this.getSyncSource(this.dependencies, this.id);
229
330
  }
230
-
231
331
  return this.getSourceForEmptyContext(this.id);
232
332
  }
233
333
 
@@ -238,9 +338,9 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`;
238
338
  return new RawSource(sourceString);
239
339
  }
240
340
 
241
- source() {
341
+ source(dependencyTemplates, outputOptions, requestShortener) {
242
342
  return this.getSource(
243
- this.getSourceString()
343
+ this.getSourceString(this.async, outputOptions, requestShortener)
244
344
  );
245
345
  }
246
346
 
@@ -578,6 +578,8 @@ module.exports = function() {
578
578
  }
579
579
 
580
580
  hotSetStatus("idle");
581
- return Promise.resolve(outdatedModules);
581
+ return new Promise(function(resolve) {
582
+ resolve(outdatedModules);
583
+ });
582
584
  }
583
585
  };
@@ -19,7 +19,9 @@ class JsonpMainTemplatePlugin {
19
19
  this.indent(
20
20
  chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n")
21
21
  ),
22
- "};"
22
+ "};",
23
+ "",
24
+ "var resolvedPromise = new Promise(function(resolve) { resolve(); });"
23
25
  ]);
24
26
  }
25
27
  return source;
@@ -28,7 +30,7 @@ class JsonpMainTemplatePlugin {
28
30
  const chunkFilename = this.outputOptions.chunkFilename;
29
31
  const chunkMaps = chunk.getChunkMaps();
30
32
  const crossOriginLoading = this.outputOptions.crossOriginLoading;
31
- const chunkLoadTimeout = this.outputOptions.chunkLoadTimeout || 120000;
33
+ const chunkLoadTimeout = this.outputOptions.chunkLoadTimeout;
32
34
  const scriptSrcPath = this.applyPluginsWaterfall("asset-path", JSON.stringify(chunkFilename), {
33
35
  hash: `" + ${this.renderCurrentHashCode(hash)} + "`,
34
36
  hashWithLength: length => `" + ${this.renderCurrentHashCode(hash, length)} + "`,
@@ -81,7 +83,7 @@ class JsonpMainTemplatePlugin {
81
83
  return this.asString([
82
84
  "if(installedChunks[chunkId] === 0) {",
83
85
  this.indent([
84
- "return Promise.resolve();"
86
+ "return resolvedPromise;"
85
87
  ]),
86
88
  "}",
87
89
  "",
package/lib/Parser.js CHANGED
@@ -636,6 +636,9 @@ class Parser extends Tapable {
636
636
  }
637
637
 
638
638
  walkFunctionDeclaration(statement) {
639
+ statement.params.forEach(param => {
640
+ this.walkPattern(param);
641
+ });
639
642
  this.inScope(statement.params, function() {
640
643
  if(statement.body.type === "BlockStatement") {
641
644
  this.prewalkStatement(statement.body);
@@ -797,24 +800,15 @@ class Parser extends Tapable {
797
800
  switch(declarator.type) {
798
801
  case "VariableDeclarator":
799
802
  {
800
- const renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init);
801
- if(renameIdentifier && declarator.id.type === "Identifier" && this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
802
- // renaming with "var a = b;"
803
- if(!this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) {
804
- this.scope.renames["$" + declarator.id.name] = this.scope.renames["$" + renameIdentifier] || renameIdentifier;
805
- const idx = this.scope.definitions.indexOf(declarator.id.name);
806
- if(idx >= 0) this.scope.definitions.splice(idx, 1);
807
- }
808
- } else {
809
- this.enterPattern(declarator.id, (name, decl) => {
810
- if(!this.applyPluginsBailResult1("var-" + declarator.kind + " " + name, decl)) {
811
- if(!this.applyPluginsBailResult1("var " + name, decl)) {
812
- this.scope.renames["$" + name] = undefined;
803
+ this.enterPattern(declarator.id, (name, decl) => {
804
+ if(!this.applyPluginsBailResult1("var-" + declarator.kind + " " + name, decl)) {
805
+ if(!this.applyPluginsBailResult1("var " + name, decl)) {
806
+ this.scope.renames["$" + name] = undefined;
807
+ if(this.scope.definitions.indexOf(name) < 0)
813
808
  this.scope.definitions.push(name);
814
- }
815
809
  }
816
- });
817
- }
810
+ }
811
+ });
818
812
  break;
819
813
  }
820
814
  }
@@ -827,7 +821,14 @@ class Parser extends Tapable {
827
821
  case "VariableDeclarator":
828
822
  {
829
823
  const renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init);
830
- if(!renameIdentifier || declarator.id.type !== "Identifier" || !this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
824
+ if(renameIdentifier && declarator.id.type === "Identifier" && this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
825
+ // renaming with "var a = b;"
826
+ if(!this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) {
827
+ this.scope.renames["$" + declarator.id.name] = this.scope.renames["$" + renameIdentifier] || renameIdentifier;
828
+ const idx = this.scope.definitions.indexOf(declarator.id.name);
829
+ if(idx >= 0) this.scope.definitions.splice(idx, 1);
830
+ }
831
+ } else {
831
832
  this.walkPattern(declarator.id);
832
833
  if(declarator.init)
833
834
  this.walkExpression(declarator.init);
@@ -845,6 +846,11 @@ class Parser extends Tapable {
845
846
  this["walk" + pattern.type](pattern);
846
847
  }
847
848
 
849
+ walkAssignmentPattern(pattern) {
850
+ this.walkExpression(pattern.right);
851
+ this.walkPattern(pattern.left);
852
+ }
853
+
848
854
  walkObjectPattern(pattern) {
849
855
  for(let i = 0, len = pattern.properties.length; i < len; i++) {
850
856
  const prop = pattern.properties[i];
@@ -912,6 +918,9 @@ class Parser extends Tapable {
912
918
  }
913
919
 
914
920
  walkFunctionExpression(expression) {
921
+ expression.params.forEach(param => {
922
+ this.walkPattern(param);
923
+ });
915
924
  this.inScope(expression.params, function() {
916
925
  if(expression.body.type === "BlockStatement") {
917
926
  this.prewalkStatement(expression.body);
@@ -923,6 +932,9 @@ class Parser extends Tapable {
923
932
  }
924
933
 
925
934
  walkArrowFunctionExpression(expression) {
935
+ expression.params.forEach(param => {
936
+ this.walkPattern(param);
937
+ });
926
938
  this.inScope(expression.params, function() {
927
939
  if(expression.body.type === "BlockStatement") {
928
940
  this.prewalkStatement(expression.body);
@@ -993,8 +1005,10 @@ class Parser extends Tapable {
993
1005
  }
994
1006
  } else {
995
1007
  this.walkExpression(expression.right);
996
- this.scope.renames["$" + expression.left.name] = undefined;
997
- this.walkExpression(expression.left);
1008
+ this.walkPattern(expression.left);
1009
+ this.enterPattern(expression.left, (name, decl) => {
1010
+ this.scope.renames["$" + name] = undefined;
1011
+ });
998
1012
  }
999
1013
  }
1000
1014
 
@@ -1191,7 +1205,6 @@ class Parser extends Tapable {
1191
1205
 
1192
1206
  enterAssignmentPattern(pattern, onIdent) {
1193
1207
  this.enterPattern(pattern.left, onIdent);
1194
- this.walkExpression(pattern.right);
1195
1208
  }
1196
1209
 
1197
1210
  evaluateExpression(expression) {
package/lib/Template.js CHANGED
@@ -26,6 +26,11 @@ module.exports = class Template extends Tapable {
26
26
  return str.replace(/^[^a-zA-Z$_]/, "_").replace(/[^a-zA-Z0-9$_]/g, "_");
27
27
  }
28
28
 
29
+ static toPath(str) {
30
+ if(typeof str !== "string") return "";
31
+ return str.replace(/[^a-zA-Z0-9_!§$()=\-\^°]+/g, "-").replace(/^-|-$/, "");
32
+ }
33
+
29
34
  // map number to a single character a-z, A-Z or <_ + number> if number is too big
30
35
  static numberToIdentifer(n) {
31
36
  // lower case
@@ -60,6 +60,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
60
60
  this.set("output.hotUpdateChunkFilename", "[id].[hash].hot-update.js");
61
61
  this.set("output.hotUpdateMainFilename", "[hash].hot-update.json");
62
62
  this.set("output.crossOriginLoading", false);
63
+ this.set("output.chunkLoadTimeout", 120000);
63
64
  this.set("output.hashFunction", "md5");
64
65
  this.set("output.hashDigest", "hex");
65
66
  this.set("output.hashDigestLength", 20);
@@ -33,7 +33,7 @@ DepBlockHelpers.getDepBlockPromise = function(depBlock, outputOptions, requestSh
33
33
  "])";
34
34
  }
35
35
  }
36
- return "Promise.resolve()";
36
+ return "new Promise(function(resolve) { resolve(); })";
37
37
  };
38
38
 
39
39
  function asComment(str) {
@@ -12,7 +12,6 @@ class ImportContextDependency extends ContextDependency {
12
12
  super(request, recursive, regExp);
13
13
  this.range = range;
14
14
  this.valueRange = valueRange;
15
- this.async = true;
16
15
  this.chunkName = chunkName;
17
16
  }
18
17
 
@@ -44,7 +44,7 @@ ImportDependency.Template = class ImportDependencyTemplate {
44
44
 
45
45
  if(dep.module) {
46
46
  const stringifiedId = JSON.stringify(dep.module.id);
47
- return `Promise.resolve(__webpack_require__(${comment}${stringifiedId}))`;
47
+ return `new Promise(function(resolve) { resolve(__webpack_require__(${comment}${stringifiedId})); })`;
48
48
  }
49
49
 
50
50
  return webpackMissingPromiseModule(dep.request);
@@ -0,0 +1,22 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+ const ImportContextDependency = require("./ImportContextDependency");
7
+ const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
8
+
9
+ class ImportEagerContextDependency extends ImportContextDependency {
10
+ constructor(request, recursive, regExp, range, valueRange, chunkName) {
11
+ super(request, recursive, regExp, range, valueRange, chunkName);
12
+ this.async = "eager";
13
+ }
14
+
15
+ get type() {
16
+ return "import() context eager";
17
+ }
18
+ }
19
+
20
+ ImportEagerContextDependency.Template = ContextDependencyTemplateAsRequireCall;
21
+
22
+ module.exports = ImportEagerContextDependency;
@@ -0,0 +1,46 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+ const ModuleDependency = require("./ModuleDependency");
7
+ const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
8
+
9
+ class ImportEagerDependency extends ModuleDependency {
10
+ constructor(request, range) {
11
+ super(request);
12
+ this.range = range;
13
+ }
14
+
15
+ get type() {
16
+ return "import()";
17
+ }
18
+ }
19
+
20
+ ImportEagerDependency.Template = class ImportEagerDependencyTemplate {
21
+ apply(dep, source, outputOptions, requestShortener) {
22
+ const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request));
23
+
24
+ const content = this.getContent(dep, comment);
25
+ source.replace(dep.range[0], dep.range[1] - 1, content);
26
+ }
27
+
28
+ getOptionalComment(pathinfo, shortenedRequest) {
29
+ if(!pathinfo) {
30
+ return "";
31
+ }
32
+
33
+ return `/*! ${shortenedRequest} */ `;
34
+ }
35
+
36
+ getContent(dep, comment) {
37
+ if(dep.module) {
38
+ const stringifiedId = JSON.stringify(dep.module.id);
39
+ return `new Promise(function(resolve) { resolve(__webpack_require__(${comment}${stringifiedId})); })`;
40
+ }
41
+
42
+ return webpackMissingPromiseModule(dep.request);
43
+ }
44
+ };
45
+
46
+ module.exports = ImportEagerDependency;
@@ -0,0 +1,22 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+ const ImportContextDependency = require("./ImportContextDependency");
7
+ const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
8
+
9
+ class ImportLazyContextDependency extends ImportContextDependency {
10
+ constructor(request, recursive, regExp, range, valueRange, chunkName) {
11
+ super(request, recursive, regExp, range, valueRange, chunkName);
12
+ this.async = "lazy";
13
+ }
14
+
15
+ get type() {
16
+ return "import() context lazy";
17
+ }
18
+ }
19
+
20
+ ImportLazyContextDependency.Template = ContextDependencyTemplateAsRequireCall;
21
+
22
+ module.exports = ImportLazyContextDependency;
@@ -0,0 +1,22 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+ const ImportContextDependency = require("./ImportContextDependency");
7
+ const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
8
+
9
+ class ImportLazyOnceContextDependency extends ImportContextDependency {
10
+ constructor(request, recursive, regExp, range, valueRange, chunkName) {
11
+ super(request, recursive, regExp, range, valueRange, chunkName);
12
+ this.async = "lazy-once";
13
+ }
14
+
15
+ get type() {
16
+ return "import() context lazy-once";
17
+ }
18
+ }
19
+
20
+ ImportLazyOnceContextDependency.Template = ContextDependencyTemplateAsRequireCall;
21
+
22
+ module.exports = ImportLazyOnceContextDependency;
@@ -4,9 +4,13 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
- const ImportContextDependency = require("./ImportContextDependency");
7
+ const ImportEagerContextDependency = require("./ImportEagerContextDependency");
8
+ const ImportLazyOnceContextDependency = require("./ImportLazyOnceContextDependency");
9
+ const ImportLazyContextDependency = require("./ImportLazyContextDependency");
8
10
  const ImportDependenciesBlock = require("./ImportDependenciesBlock");
11
+ const ImportEagerDependency = require("./ImportEagerDependency");
9
12
  const ContextDependencyHelpers = require("./ContextDependencyHelpers");
13
+ const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
10
14
 
11
15
  class ImportParserPlugin {
12
16
  constructor(options) {
@@ -23,22 +27,49 @@ class ImportParserPlugin {
23
27
  const param = parser.evaluateExpression(expr.arguments[0]);
24
28
 
25
29
  let chunkName = null;
30
+ let mode = "lazy";
26
31
 
27
32
  const importOptions = parser.getCommentOptions(expr.range);
28
33
  if(importOptions) {
29
34
  if(typeof importOptions.webpackChunkName !== "undefined") {
30
35
  if(typeof importOptions.webpackChunkName !== "string")
31
- throw new Error(`\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`);
32
- chunkName = importOptions.webpackChunkName;
36
+ parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`));
37
+ else
38
+ chunkName = importOptions.webpackChunkName;
39
+ }
40
+ if(typeof importOptions.webpackMode !== "undefined") {
41
+ if(typeof importOptions.webpackMode !== "string")
42
+ parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`));
43
+ else
44
+ mode = importOptions.webpackMode;
33
45
  }
34
46
  }
35
47
 
36
48
  if(param.isString()) {
37
- const depBlock = new ImportDependenciesBlock(param.string, expr.range, chunkName, parser.state.module, expr.loc);
38
- parser.state.current.addBlock(depBlock);
49
+ if(mode !== "lazy" && mode !== "eager") {
50
+ parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy' or 'eager', but received: ${mode}.`));
51
+ }
52
+
53
+ if(mode === "eager") {
54
+ const dep = new ImportEagerDependency(param.string, expr.range);
55
+ parser.state.current.addDependency(dep);
56
+ } else {
57
+ const depBlock = new ImportDependenciesBlock(param.string, expr.range, chunkName, parser.state.module, expr.loc);
58
+ parser.state.current.addBlock(depBlock);
59
+ }
39
60
  return true;
40
61
  } else {
41
- const dep = ContextDependencyHelpers.create(ImportContextDependency, expr.range, param, expr, options, chunkName);
62
+ if(mode !== "lazy" && mode !== "lazy-once" && mode !== "eager") {
63
+ parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'lazy-once' or 'eager', but received: ${mode}.`));
64
+ }
65
+
66
+ let Dep = ImportLazyContextDependency;
67
+ if(mode === "eager") {
68
+ Dep = ImportEagerContextDependency;
69
+ } else if(mode === "lazy-once") {
70
+ Dep = ImportLazyOnceContextDependency;
71
+ }
72
+ const dep = ContextDependencyHelpers.create(Dep, expr.range, param, expr, options, chunkName);
42
73
  if(!dep) return;
43
74
  dep.loc = expr.loc;
44
75
  dep.optional = !!parser.scope.inTry;
@@ -5,7 +5,10 @@
5
5
  "use strict";
6
6
 
7
7
  const ImportDependency = require("./ImportDependency");
8
- const ImportContextDependency = require("./ImportContextDependency");
8
+ const ImportEagerDependency = require("./ImportEagerDependency");
9
+ const ImportEagerContextDependency = require("./ImportEagerContextDependency");
10
+ const ImportLazyOnceContextDependency = require("./ImportLazyOnceContextDependency");
11
+ const ImportLazyContextDependency = require("./ImportLazyContextDependency");
9
12
  const ImportParserPlugin = require("./ImportParserPlugin");
10
13
 
11
14
  class ImportPlugin {
@@ -22,8 +25,17 @@ class ImportPlugin {
22
25
  compilation.dependencyFactories.set(ImportDependency, normalModuleFactory);
23
26
  compilation.dependencyTemplates.set(ImportDependency, new ImportDependency.Template());
24
27
 
25
- compilation.dependencyFactories.set(ImportContextDependency, contextModuleFactory);
26
- compilation.dependencyTemplates.set(ImportContextDependency, new ImportContextDependency.Template());
28
+ compilation.dependencyFactories.set(ImportEagerDependency, normalModuleFactory);
29
+ compilation.dependencyTemplates.set(ImportEagerDependency, new ImportEagerDependency.Template());
30
+
31
+ compilation.dependencyFactories.set(ImportEagerContextDependency, contextModuleFactory);
32
+ compilation.dependencyTemplates.set(ImportEagerContextDependency, new ImportEagerContextDependency.Template());
33
+
34
+ compilation.dependencyFactories.set(ImportLazyOnceContextDependency, contextModuleFactory);
35
+ compilation.dependencyTemplates.set(ImportLazyOnceContextDependency, new ImportLazyOnceContextDependency.Template());
36
+
37
+ compilation.dependencyFactories.set(ImportLazyContextDependency, contextModuleFactory);
38
+ compilation.dependencyTemplates.set(ImportLazyContextDependency, new ImportLazyContextDependency.Template());
27
39
 
28
40
  params.normalModuleFactory.plugin("parser", (parser, parserOptions) => {
29
41
 
@@ -2,83 +2,85 @@
2
2
  MIT License http://www.opensource.org/licenses/mit-license.php
3
3
  Author Tobias Koppers @sokra
4
4
  */
5
- var AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
6
- var ParserHelpers = require("../ParserHelpers");
7
- var nodeLibsBrowser = require("node-libs-browser");
5
+ "use strict";
6
+ const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
7
+ const ParserHelpers = require("../ParserHelpers");
8
+ const nodeLibsBrowser = require("node-libs-browser");
8
9
 
9
- function NodeSourcePlugin(options) {
10
- this.options = options;
11
- }
12
- module.exports = NodeSourcePlugin;
13
- NodeSourcePlugin.prototype.apply = function(compiler) {
14
- var options = this.options;
15
-
16
- function getPathToModule(module, type) {
17
- if(type === true || (type === undefined && nodeLibsBrowser[module])) {
18
- if(!nodeLibsBrowser[module]) throw new Error("No browser version for node.js core module '" + module + "' available");
19
- return nodeLibsBrowser[module];
20
- } else if(type === "mock") {
21
- return require.resolve("node-libs-browser/mock/" + module);
22
- } else if(type === "empty") {
23
- return require.resolve("node-libs-browser/mock/empty");
24
- } else return module;
10
+ module.exports = class NodeSourcePlugin {
11
+ constructor(options) {
12
+ this.options = options;
25
13
  }
14
+ apply(compiler) {
15
+ const options = this.options;
26
16
 
27
- function addExpression(parser, name, module, type, suffix) {
28
- suffix = suffix || "";
29
- parser.plugin("expression " + name, function() {
30
- if(this.state.module && this.state.module.resource === getPathToModule(module, type)) return;
31
- var mockModule = ParserHelpers.requireFileAsExpression(this.state.module.context, getPathToModule(module, type));
32
- return ParserHelpers.addParsedVariableToModule(this, name, mockModule + suffix);
33
- });
34
- }
17
+ function getPathToModule(module, type) {
18
+ if(type === true || (type === undefined && nodeLibsBrowser[module])) {
19
+ if(!nodeLibsBrowser[module]) throw new Error(`No browser version for node.js core module ${module} available`);
20
+ return nodeLibsBrowser[module];
21
+ } else if(type === "mock") {
22
+ return require.resolve(`node-libs-browser/mock/${module}`);
23
+ } else if(type === "empty") {
24
+ return require.resolve("node-libs-browser/mock/empty");
25
+ } else return module;
26
+ }
35
27
 
36
- compiler.plugin("compilation", function(compilation, params) {
37
- params.normalModuleFactory.plugin("parser", function(parser, parserOptions) {
28
+ function addExpression(parser, name, module, type, suffix) {
29
+ suffix = suffix || "";
30
+ parser.plugin(`expression ${name}`, function() {
31
+ if(this.state.module && this.state.module.resource === getPathToModule(module, type)) return;
32
+ const mockModule = ParserHelpers.requireFileAsExpression(this.state.module.context, getPathToModule(module, type));
33
+ return ParserHelpers.addParsedVariableToModule(this, name, mockModule + suffix);
34
+ });
35
+ }
38
36
 
39
- if(parserOptions.node === false)
40
- return;
37
+ compiler.plugin("compilation", function(compilation, params) {
38
+ params.normalModuleFactory.plugin("parser", function(parser, parserOptions) {
41
39
 
42
- var localOptions = options;
43
- if(parserOptions.node)
44
- localOptions = Object.assign({}, localOptions, parserOptions.node);
40
+ if(parserOptions.node === false)
41
+ return;
45
42
 
46
- if(localOptions.global) {
47
- parser.plugin("expression global", function() {
48
- var retrieveGlobalModule = ParserHelpers.requireFileAsExpression(this.state.module.context, require.resolve("../../buildin/global.js"));
49
- return ParserHelpers.addParsedVariableToModule(this, "global", retrieveGlobalModule);
50
- });
51
- }
52
- if(localOptions.process) {
53
- var processType = localOptions.process;
54
- addExpression(parser, "process", "process", processType);
55
- }
56
- if(localOptions.console) {
57
- var consoleType = localOptions.console;
58
- addExpression(parser, "console", "console", consoleType);
59
- }
60
- var bufferType = localOptions.Buffer;
61
- if(bufferType) {
62
- addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer");
63
- }
64
- if(localOptions.setImmediate) {
65
- var setImmediateType = localOptions.setImmediate;
66
- addExpression(parser, "setImmediate", "timers", setImmediateType, ".setImmediate");
67
- addExpression(parser, "clearImmediate", "timers", setImmediateType, ".clearImmediate");
68
- }
43
+ let localOptions = options;
44
+ if(parserOptions.node)
45
+ localOptions = Object.assign({}, localOptions, parserOptions.node);
46
+
47
+ if(localOptions.global) {
48
+ parser.plugin("expression global", function() {
49
+ const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(this.state.module.context, require.resolve("../../buildin/global.js"));
50
+ return ParserHelpers.addParsedVariableToModule(this, "global", retrieveGlobalModule);
51
+ });
52
+ }
53
+ if(localOptions.process) {
54
+ const processType = localOptions.process;
55
+ addExpression(parser, "process", "process", processType);
56
+ }
57
+ if(localOptions.console) {
58
+ const consoleType = localOptions.console;
59
+ addExpression(parser, "console", "console", consoleType);
60
+ }
61
+ const bufferType = localOptions.Buffer;
62
+ if(bufferType) {
63
+ addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer");
64
+ }
65
+ if(localOptions.setImmediate) {
66
+ const setImmediateType = localOptions.setImmediate;
67
+ addExpression(parser, "setImmediate", "timers", setImmediateType, ".setImmediate");
68
+ addExpression(parser, "clearImmediate", "timers", setImmediateType, ".clearImmediate");
69
+ }
70
+ });
69
71
  });
70
- });
71
- compiler.plugin("after-resolvers", function(compiler) {
72
- Object.keys(nodeLibsBrowser).forEach(function(lib) {
73
- if(options[lib] !== false) {
74
- compiler.resolvers.normal.apply(
75
- new AliasPlugin("described-resolve", {
76
- name: lib,
77
- onlyModule: true,
78
- alias: getPathToModule(lib, options[lib])
79
- }, "resolve")
80
- );
81
- }
72
+ compiler.plugin("after-resolvers", (compiler) => {
73
+ Object.keys(nodeLibsBrowser).forEach((lib) => {
74
+ if(options[lib] !== false) {
75
+ compiler.resolvers.normal.apply(
76
+ new AliasPlugin("described-resolve", {
77
+ name: lib,
78
+ onlyModule: true,
79
+ alias: getPathToModule(lib, options[lib])
80
+ }, "resolve")
81
+ );
82
+ }
83
+ });
82
84
  });
83
- });
85
+ }
84
86
  };
@@ -21,7 +21,9 @@ class WebWorkerMainTemplatePlugin {
21
21
  return id + ": 1";
22
22
  }).join(",\n")
23
23
  ),
24
- "};"
24
+ "};",
25
+ "",
26
+ "var resolvedPromise = new Promise(function(resolve) { resolve(); });"
25
27
  ]);
26
28
  }
27
29
  return source;
@@ -44,7 +46,7 @@ class WebWorkerMainTemplatePlugin {
44
46
  }) + ");"
45
47
  ]),
46
48
  "}",
47
- "return Promise.resolve();"
49
+ "return resolvedPromise;"
48
50
  ]);
49
51
  });
50
52
  mainTemplate.plugin("bootstrap", function(source, chunk, hash) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack",
3
- "version": "2.5.1",
3
+ "version": "2.6.0",
4
4
  "author": "Tobias Koppers @sokra",
5
5
  "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, jsx, es7, css, less, ... and your custom stuff.",
6
6
  "dependencies": {
@@ -21,7 +21,7 @@
21
21
  "source-map": "^0.5.3",
22
22
  "supports-color": "^3.1.0",
23
23
  "tapable": "~0.2.5",
24
- "uglify-js": "^2.8.5",
24
+ "uglify-js": "^2.8.27",
25
25
  "watchpack": "^1.3.1",
26
26
  "webpack-sources": "^0.2.3",
27
27
  "yargs": "^6.0.0"
@@ -270,6 +270,10 @@
270
270
  "use-credentials"
271
271
  ]
272
272
  },
273
+ "chunkLoadTimeout": {
274
+ "description": "Number of milliseconds before chunk request expires",
275
+ "type": "number"
276
+ },
273
277
  "devtoolFallbackModuleFilenameTemplate": {
274
278
  "description": "Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.",
275
279
  "anyOf": [