@@ -5,41 +5,60 @@ const stylePostLoaderPath = require.resolve('./style-post-loader')
55
66module . exports = code => code
77
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.
1010module . exports . pitch = function ( remainingRequest ) {
1111 const query = qs . parse ( this . resourceQuery . slice ( 1 ) )
1212
1313 if ( query . vue == null ) {
1414 return
1515 }
1616
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+
1732 // Inject style-post-loader before css-loader for scoped CSS and trimming
1833 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 ) )
2035 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 ( [
2439 ...afterLoaders ,
2540 stylePostLoaderPath ,
26- ...beforeLoaders ,
27- this . resourcePath + this . resourceQuery
28- ] . join ( '!' )
41+ ...beforeLoaders
42+ ] )
2943 // 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 } )`
3145 }
3246 }
3347
3448 // for templates: inject the template compiler
3549 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 ( [
3852 templateLoaderPath + `??vue-loader-options` ,
39- ...beforeLoaders ,
40- this . resourcePath + this . resourceQuery
41- ] . join ( '!' )
53+ ...beforeLoaders
54+ ] )
4255 // the template compiler uses esm exports
43- return `export * from ${ loaderUtils . stringifyRequest ( this , request ) } `
56+ return `export * from ${ request } `
4457 }
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 } )`
4564}
0 commit comments