11const qs = require ( 'querystring' )
22const RuleSet = require ( 'webpack/lib/RuleSet' )
3+ const { resolveCompiler } = require ( './compiler' )
34
45const id = 'vue-loader-plugin'
56const NS = 'vue-loader'
@@ -38,7 +39,7 @@ class VueLoaderPlugin {
3839 if ( ! vueRule ) {
3940 throw new Error (
4041 `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` +
41- `Make sure there is at least one root-level rule that matches .vue or .vue.html files.`
42+ `Make sure there is at least one root-level rule that matches .vue or .vue.html files.`
4243 )
4344 }
4445
@@ -58,7 +59,7 @@ class VueLoaderPlugin {
5859 if ( vueLoaderUseIndex < 0 ) {
5960 throw new Error (
6061 `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` +
61- `Make sure the rule matching .vue files include vue-loader in its use.`
62+ `Make sure the rule matching .vue files include vue-loader in its use.`
6263 )
6364 }
6465
@@ -71,9 +72,30 @@ class VueLoaderPlugin {
7172
7273 // for each user rule (except the vue rule), create a cloned rule
7374 // that targets the corresponding language blocks in *.vue files.
74- const clonedRules = rules
75- . filter ( r => r !== vueRule )
76- . map ( cloneRule )
75+ const clonedRules = rules . filter ( r => r !== vueRule ) . map ( cloneRule )
76+
77+ // rule for template compiler
78+ const templateCompilerRule = {
79+ loader : require . resolve ( './loaders/templateLoader' ) ,
80+ resourceQuery : query => {
81+ const parsed = qs . parse ( query . slice ( 1 ) )
82+ return parsed . vue != null && parsed . type === 'template'
83+ } ,
84+ options : vueLoaderUse . options
85+ }
86+
87+ // for each rule that matches plain .js/.ts files, also create a clone and
88+ // match it against the compiled template code inside *.vue files, so that
89+ // compiled vue render functions receive the same treatment as user code
90+ // (mostly babel)
91+ let jsRulesForRenderFn = [ ]
92+ if ( resolveCompiler ( compiler . options . context ) . is27 ) {
93+ const matchesJS = createMatcher ( `test.js` )
94+ // const matchesTS = createMatcher(`test.ts`)
95+ jsRulesForRenderFn = rules
96+ . filter ( r => r !== vueRule && matchesJS ( r ) )
97+ . map ( cloneRuleForRenderFn )
98+ }
7799
78100 // global pitcher (responsible for injecting template compiler loader & CSS
79101 // post loader)
@@ -92,6 +114,8 @@ class VueLoaderPlugin {
92114 // replace original rules
93115 compiler . options . module . rules = [
94116 pitcher ,
117+ ...jsRulesForRenderFn ,
118+ templateCompilerRule ,
95119 ...clonedRules ,
96120 ...rules
97121 ]
@@ -104,11 +128,7 @@ function createMatcher (fakeFile) {
104128 const clone = Object . assign ( { } , rule )
105129 delete clone . include
106130 const normalized = RuleSet . normalizeRule ( clone , { } , '' )
107- return (
108- ! rule . enforce &&
109- normalized . resource &&
110- normalized . resource ( fakeFile )
111- )
131+ return ! rule . enforce && normalized . resource && normalized . resource ( fakeFile )
112132 }
113133}
114134
@@ -157,5 +177,42 @@ function cloneRule (rule) {
157177 return res
158178}
159179
180+ function cloneRuleForRenderFn ( rule ) {
181+ const resource = rule . resource
182+ const resourceQuery = rule . resourceQuery
183+ let currentResource
184+ const res = {
185+ ...rule ,
186+ resource : resource => {
187+ currentResource = resource
188+ return true
189+ } ,
190+ resourceQuery : query => {
191+ const parsed = qs . parse ( query . slice ( 1 ) )
192+ if ( parsed . vue == null || parsed . type !== 'template' ) {
193+ return false
194+ }
195+ const fakeResourcePath = `${ currentResource } .${ parsed . ts ? `ts` : `js` } `
196+ if ( resource && ! resource ( fakeResourcePath ) ) {
197+ return false
198+ }
199+ if ( resourceQuery && ! resourceQuery ( query ) ) {
200+ return false
201+ }
202+ return true
203+ }
204+ }
205+
206+ if ( rule . rules ) {
207+ res . rules = rule . rules . map ( cloneRuleForRenderFn )
208+ }
209+
210+ if ( rule . oneOf ) {
211+ res . oneOf = rule . oneOf . map ( cloneRuleForRenderFn )
212+ }
213+
214+ return res
215+ }
216+
160217VueLoaderPlugin . NS = NS
161218module . exports = VueLoaderPlugin
0 commit comments