@@ -25,29 +25,16 @@ class VueLoaderPlugin {
2525 } )
2626 }
2727
28- // get a hold of the raw rules
29- const rawRules = compiler . options . module . rules . slice ( )
3028 // use webpack's RuleSet utility to normalize user rules
31- const rawNormalizedRules = new RuleSet ( rawRules ) . rules
32-
33- const createMatcher = fakeFile => ( rule , i ) => {
34- // #1201 we need to skip the `include` check when locating the vue rule
35- const clone = Object . assign ( { } , rule )
36- delete clone . include
37- const normalized = RuleSet . normalizeRule ( clone , { } , '' )
38- return (
39- ! rule . enforce &&
40- normalized . resource &&
41- normalized . resource ( fakeFile )
42- )
43- }
29+ const rawRules = compiler . options . module . rules
30+ const { rules } = new RuleSet ( rawRules )
4431
4532 // find the rule that applies to vue files
4633 let vueRuleIndex = rawRules . findIndex ( createMatcher ( `foo.vue` ) )
4734 if ( vueRuleIndex < 0 ) {
4835 vueRuleIndex = rawRules . findIndex ( createMatcher ( `foo.vue.html` ) )
4936 }
50- const vueRule = rawRules [ vueRuleIndex ]
37+ const vueRule = rules [ vueRuleIndex ]
5138
5239 if ( ! vueRule ) {
5340 throw new Error (
@@ -62,12 +49,10 @@ class VueLoaderPlugin {
6249 )
6350 }
6451
65- // find the normalized version of the vue rule
66- const normalizedVueRule = rawNormalizedRules [ vueRuleIndex ]
6752 // get the normlized "use" for vue files
68- const normalizedVueUse = normalizedVueRule . use
53+ const vueUse = vueRule . use
6954 // get vue-loader options
70- const vueLoaderUseIndex = normalizedVueUse . findIndex ( u => {
55+ const vueLoaderUseIndex = vueUse . findIndex ( u => {
7156 return / ^ v u e - l o a d e r | ( \/ | \\ ) v u e - l o a d e r / . test ( u . loader )
7257 } )
7358
@@ -81,76 +66,69 @@ class VueLoaderPlugin {
8166 // make sure vue-loader options has a known ident so that we can share
8267 // options by reference in the template-loader by using a ref query like
8368 // template-loader??vue-loader-options
84- const ident = 'vue-loader-options'
85- const vueLoaderUse = normalizedVueUse [ vueLoaderUseIndex ]
86- // has options, just set ident
87- if ( vueLoaderUse . options ) {
88- vueLoaderUse . options . ident = ident
89- } else {
90- // user provided no options, but we must ensure the options is present
91- // otherwise RuleSet throws error if no option for a given ref is found.
92- if ( vueRule . loader || vueRule . loaders ) {
93- vueRule . options = { ident }
94- } else if ( Array . isArray ( vueRule . use ) ) {
95- const use = vueRule . use [ vueLoaderUseIndex ]
96- if ( typeof use === 'string' ) {
97- vueRule . use [ vueLoaderUseIndex ] = { loader : use , options : { ident } }
98- } else {
99- use . options = { ident }
100- }
101- } else if ( typeof vueRule . use === 'string' ) {
102- vueRule . use = [ { loader : vueRule . use , options : { ident } } ]
103- } else {
104- throw new Error (
105- `VueLoaderPlugin Error: this should not happen. Please open an issue ` +
106- `with your webpack config.`
107- )
108- }
109- }
110-
111- // get new rules without the vue rule
112- const baseRules = rawRules . filter ( r => r !== vueRule )
113- const normalizedRules = rawNormalizedRules . filter ( r => r !== normalizedVueRule )
114-
115- // for each user rule, inject a cloned rule by checking if the rule
116- // matches the lang specified in the resourceQuery.
117- rawRules . unshift . apply ( rawRules , baseRules . map ( ( rule , i ) => {
118- return cloneRule ( rule , normalizedRules [ i ] )
119- } ) )
120-
121- // inject global pitcher (responsible for injecting template compiler
122- // loader & CSS post loader)
123- rawRules . unshift ( {
69+ const vueLoaderUse = vueUse [ vueLoaderUseIndex ]
70+ vueLoaderUse . ident = 'vue-loader-options'
71+ vueLoaderUse . options = vueLoaderUse . options || { }
72+
73+ // for each user rule (expect the vue rule), create a cloned rule
74+ // that targets the corresponding language blocks in *.vue files.
75+ const clonedRules = rules
76+ . filter ( r => r !== vueRule )
77+ . map ( cloneRule )
78+
79+ // global pitcher (responsible for injecting template compiler loader & CSS
80+ // post loader)
81+ const pitcher = {
12482 loader : require . resolve ( './loaders/pitcher' ) ,
12583 resourceQuery : query => {
12684 const parsed = qs . parse ( query . slice ( 1 ) )
12785 return parsed . vue != null
12886 }
129- } )
87+ }
13088
13189 // replace original rules
132- compiler . options . module . rules = rawRules
90+ compiler . options . module . rules = [
91+ pitcher ,
92+ ...clonedRules ,
93+ ...rules
94+ ]
95+ }
96+ }
97+
98+ function createMatcher ( fakeFile ) {
99+ return ( rule , i ) => {
100+ // #1201 we need to skip the `include` check when locating the vue rule
101+ const clone = Object . assign ( { } , rule )
102+ delete clone . include
103+ const normalized = RuleSet . normalizeRule ( clone , { } , '' )
104+ return (
105+ ! rule . enforce &&
106+ normalized . resource &&
107+ normalized . resource ( fakeFile )
108+ )
133109 }
134110}
135111
136- function cloneRule ( rule , normalizedRule ) {
112+ function cloneRule ( rule ) {
113+ const { resource, resourceQuery } = rule
137114 // Assuming `test` and `resourceQuery` tests are executed in series and
138115 // synchronously (which is true based on RuleSet's implementation), we can
139116 // save the current resource being matched from `test` so that we can access
140117 // it in `resourceQuery`. This ensures when we use the normalized rule's
141118 // resource check, include/exclude are matched correctly.
142119 let currentResource
143120 const res = Object . assign ( { } , rule , {
144- test : resource => {
145- currentResource = resource
146- return true
121+ resource : {
122+ test : resource => {
123+ currentResource = resource
124+ return true
125+ }
147126 } ,
148127 resourceQuery : query => {
149128 const parsed = qs . parse ( query . slice ( 1 ) )
150129 if ( parsed . vue == null ) {
151130 return false
152131 }
153- const { resource, resourceQuery } = normalizedRule
154132 if ( resource && parsed . lang == null ) {
155133 return false
156134 }
@@ -162,50 +140,15 @@ function cloneRule (rule, normalizedRule) {
162140 return false
163141 }
164142 return true
165- } ,
166- use : normalizedRule . use ? normalizedRule . use . map ( cleanIdent ) : undefined
143+ }
167144 } )
168145
169- // delete shorthand since we have normalized use
170- delete res . loader
171- delete res . loaders
172- delete res . options
173-
174- // these are included in the normalized resource() check
175- delete res . resource
176- delete res . include
177- delete res . exclude
178-
179146 if ( rule . oneOf ) {
180- res . oneOf = rule . oneOf . map ( ( r , i ) => {
181- return cloneRule ( r , normalizedRule . oneOf [ i ] )
182- } )
147+ res . oneOf = rule . oneOf . map ( cloneRule )
183148 }
184149
185150 return res
186151}
187152
188- const reuseIdentWhitelist = [
189- 'css-loader' ,
190- '(vue-)?style-loader' ,
191- 'postcss-loader' ,
192- 'extract-text-webpack-plugin' ,
193- 'mini-css-extract-plugin'
194- ]
195-
196- const reuseIdentPattern = new RegExp ( `(${ reuseIdentWhitelist . join ( '|' ) } )` )
197-
198- function cleanIdent ( use ) {
199- if ( use . ident ) {
200- if ( reuseIdentPattern . test ( use . loader ) ) {
201- // Reuse options ident, so that imports from within css-loader would get the
202- // exact same request prefixes, avoiding duplicated modules (#1199)
203- use . options . ident = use . ident
204- }
205- delete use . ident
206- }
207- return use
208- }
209-
210153VueLoaderPlugin . NS = NS
211154module . exports = VueLoaderPlugin
0 commit comments