@@ -5,41 +5,60 @@ const stylePostLoaderPath = require.resolve('./style-post-loader')
5
5
6
6
module . exports = code => code
7
7
8
- // This pitching loader is responsible for catching all src import requests
9
- // from within vue files and transform it into appropriate requests
8
+ // This pitching loader is responsible for intercepting all vue block requests
9
+ // and transform it into appropriate requests.
10
10
module . exports . pitch = function ( remainingRequest ) {
11
11
const query = qs . parse ( this . resourceQuery . slice ( 1 ) )
12
12
13
13
if ( query . vue == null ) {
14
14
return
15
15
}
16
16
17
+ const loaders = this . loaders . slice ( 1 ) // remove self
18
+
19
+ // loader.request contains both the resolved loader path and its options
20
+ // query (e.g. ??ref-0)
21
+ const toLoaderString = loader => loader . request
22
+
23
+ const genRequest = loaderStrings => {
24
+ // important: dedupe
25
+ loaderStrings = Array . from ( new Set ( loaderStrings ) )
26
+ return loaderUtils . stringifyRequest ( this , '-!' + [
27
+ ...loaderStrings ,
28
+ this . resourcePath + this . resourceQuery
29
+ ] . join ( '!' ) )
30
+ }
31
+
17
32
// Inject style-post-loader before css-loader for scoped CSS and trimming
18
33
if ( query . type === `style` ) {
19
- const cssLoaderIndex = this . loaders . findIndex ( l => / \/ c s s - l o a d e r / . test ( l . request ) )
34
+ const cssLoaderIndex = loaders . findIndex ( l => / \/ c s s - l o a d e r / . test ( l . request ) )
20
35
if ( cssLoaderIndex ) {
21
- const afterLoaders = this . loaders . slice ( 1 , cssLoaderIndex + 1 ) . map ( l => l . request )
22
- const beforeLoaders = this . loaders . slice ( cssLoaderIndex + 1 ) . map ( l => l . request )
23
- const request = '-!' + [
36
+ const afterLoaders = loaders . slice ( 0 , cssLoaderIndex + 1 ) . map ( toLoaderString )
37
+ const beforeLoaders = loaders . slice ( cssLoaderIndex + 1 ) . map ( toLoaderString )
38
+ const request = genRequest ( [
24
39
...afterLoaders ,
25
40
stylePostLoaderPath ,
26
- ...beforeLoaders ,
27
- this . resourcePath + this . resourceQuery
28
- ] . join ( '!' )
41
+ ...beforeLoaders
42
+ ] )
29
43
// use cjs to ensure exports from (vue-)style-loader/css-loader are intact
30
- return `module.exports = require(${ loaderUtils . stringifyRequest ( this , request ) } )`
44
+ return `module.exports = require(${ request } )`
31
45
}
32
46
}
33
47
34
48
// for templates: inject the template compiler
35
49
if ( query . type === `template` ) {
36
- const beforeLoaders = this . loaders . slice ( 1 ) . map ( l => l . request )
37
- const request = '-!' + [
50
+ const beforeLoaders = loaders . map ( toLoaderString )
51
+ const request = genRequest ( [
38
52
templateLoaderPath + `??vue-loader-options` ,
39
- ...beforeLoaders ,
40
- this . resourcePath + this . resourceQuery
41
- ] . join ( '!' )
53
+ ...beforeLoaders
54
+ ] )
42
55
// the template compiler uses esm exports
43
- return `export * from ${ loaderUtils . stringifyRequest ( this , request ) } `
56
+ return `export * from ${ request } `
44
57
}
58
+
59
+ // When the user defines a rule that has only resourceQuery but no test,
60
+ // both that rule and the cloned rule will match, resulting in duplicated
61
+ // loaders. Therefore it is necessary to perform a dedupe here.
62
+ const dedupedRequest = genRequest ( loaders . map ( toLoaderString ) )
63
+ return `module.exports = require(${ dedupedRequest } )`
45
64
}
0 commit comments