@@ -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 ( ! / \[ ( i n d e x | r e q u e s t ) \] / . test ( chunkName ) )
151
+ chunkName += "[index]" ;
152
+ chunkName = chunkName . replace ( / \[ i n d e x \] / g, idx ) ;
153
+ chunkName = chunkName . replace ( / \[ r e q u e s t \] / 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
0 commit comments