@@ -22,7 +22,12 @@ import { formatError } from './formatError'
22
22
import VueLoaderPlugin from './plugin'
23
23
import { canInlineTemplate } from './resolveScript'
24
24
import { setDescriptor } from './descriptorCache'
25
- import { getOptions , stringifyRequest as _stringifyRequest } from './util'
25
+ import {
26
+ getOptions ,
27
+ stringifyRequest as _stringifyRequest ,
28
+ genMatchResource ,
29
+ testWebpack5 ,
30
+ } from './util'
26
31
27
32
export { VueLoaderPlugin }
28
33
@@ -53,6 +58,7 @@ export interface VueLoaderOptions {
53
58
exposeFilename ?: boolean
54
59
appendExtension ?: boolean
55
60
enableTsInTemplate ?: boolean
61
+ experimentalInlineMatchResource ?: boolean
56
62
57
63
isServerBuild ?: boolean
58
64
}
@@ -64,7 +70,7 @@ const exportHelperPath = require.resolve('./exportHelper')
64
70
65
71
export default function loader (
66
72
this : LoaderContext < VueLoaderOptions > ,
67
- source : string
73
+ source : string ,
68
74
) {
69
75
const loaderContext = this
70
76
@@ -77,8 +83,8 @@ export default function loader(
77
83
loaderContext . emitError (
78
84
new Error (
79
85
`vue-loader was used without the corresponding plugin. ` +
80
- `Make sure to include VueLoaderPlugin in your webpack config.`
81
- )
86
+ `Make sure to include VueLoaderPlugin in your webpack config.` ,
87
+ ) ,
82
88
)
83
89
errorEmitted = true
84
90
}
@@ -92,18 +98,23 @@ export default function loader(
92
98
rootContext,
93
99
resourcePath,
94
100
resourceQuery : _resourceQuery = '' ,
101
+ _compiler,
95
102
} = loaderContext
96
103
104
+ const isWebpack5 = testWebpack5 ( _compiler )
97
105
const rawQuery = _resourceQuery . slice ( 1 )
98
106
const incomingQuery = qs . parse ( rawQuery )
99
107
const resourceQuery = rawQuery ? `&${ rawQuery } ` : ''
100
108
const options = ( getOptions ( loaderContext ) || { } ) as VueLoaderOptions
109
+ const enableInlineMatchResource =
110
+ isWebpack5 && Boolean ( options . experimentalInlineMatchResource )
101
111
102
112
const isServer = options . isServerBuild ?? target === 'node'
103
113
const isProduction =
104
114
mode === 'production' || process . env . NODE_ENV === 'production'
105
115
106
116
const filename = resourcePath . replace ( / \? .* $ / , '' )
117
+
107
118
const { descriptor, errors } = parse ( source , {
108
119
filename,
109
120
sourceMap,
@@ -133,7 +144,7 @@ export default function loader(
133
144
const id = hash (
134
145
isProduction
135
146
? shortFilePath + '\n' + source . replace ( / \r \n / g, '\n' )
136
- : shortFilePath
147
+ : shortFilePath ,
137
148
)
138
149
139
150
// if the query has a type field, this is a language block request
@@ -146,7 +157,7 @@ export default function loader(
146
157
options ,
147
158
loaderContext ,
148
159
incomingQuery ,
149
- ! ! options . appendExtension
160
+ ! ! options . appendExtension ,
150
161
)
151
162
}
152
163
@@ -169,10 +180,23 @@ export default function loader(
169
180
if ( script || scriptSetup ) {
170
181
const lang = script ?. lang || scriptSetup ?. lang
171
182
isTS = ! ! ( lang && / t s x ? / . test ( lang ) )
183
+ const externalQuery = Boolean ( script && ! scriptSetup && script . src )
184
+ ? `&external`
185
+ : ``
172
186
const src = ( script && ! scriptSetup && script . src ) || resourcePath
173
187
const attrsQuery = attrsToQuery ( ( scriptSetup || script ) ! . attrs , 'js' )
174
- const query = `?vue&type=script${ attrsQuery } ${ resourceQuery } `
175
- const scriptRequest = stringifyRequest ( src + query )
188
+ const query = `?vue&type=script${ attrsQuery } ${ resourceQuery } ${ externalQuery } `
189
+
190
+ let scriptRequest : string
191
+
192
+ if ( enableInlineMatchResource ) {
193
+ scriptRequest = stringifyRequest (
194
+ genMatchResource ( this , src , query , lang || 'js' ) ,
195
+ )
196
+ } else {
197
+ scriptRequest = stringifyRequest ( src + query )
198
+ }
199
+
176
200
scriptImport =
177
201
`import script from ${ scriptRequest } \n` +
178
202
// support named exports
@@ -186,13 +210,27 @@ export default function loader(
186
210
const useInlineTemplate = canInlineTemplate ( descriptor , isProduction )
187
211
if ( descriptor . template && ! useInlineTemplate ) {
188
212
const src = descriptor . template . src || resourcePath
213
+ const externalQuery = Boolean ( descriptor . template . src ) ? `&external` : ``
189
214
const idQuery = `&id=${ id } `
190
215
const scopedQuery = hasScoped ? `&scoped=true` : ``
191
216
const attrsQuery = attrsToQuery ( descriptor . template . attrs )
192
217
const tsQuery =
193
218
options . enableTsInTemplate !== false && isTS ? `&ts=true` : ``
194
- const query = `?vue&type=template${ idQuery } ${ scopedQuery } ${ tsQuery } ${ attrsQuery } ${ resourceQuery } `
195
- templateRequest = stringifyRequest ( src + query )
219
+ const query = `?vue&type=template${ idQuery } ${ scopedQuery } ${ tsQuery } ${ attrsQuery } ${ resourceQuery } ${ externalQuery } `
220
+
221
+ if ( enableInlineMatchResource ) {
222
+ templateRequest = stringifyRequest (
223
+ genMatchResource (
224
+ this ,
225
+ src ,
226
+ query ,
227
+ options . enableTsInTemplate !== false && isTS ? 'ts' : 'js' ,
228
+ ) ,
229
+ )
230
+ } else {
231
+ templateRequest = stringifyRequest ( src + query )
232
+ }
233
+
196
234
templateImport = `import { ${ renderFnName } } from ${ templateRequest } `
197
235
propsToAttach . push ( [ renderFnName , renderFnName ] )
198
236
}
@@ -209,19 +247,29 @@ export default function loader(
209
247
. forEach ( ( style , i ) => {
210
248
const src = style . src || resourcePath
211
249
const attrsQuery = attrsToQuery ( style . attrs , 'css' )
250
+ const lang = String ( style . attrs . lang || 'css' )
212
251
// make sure to only pass id when necessary so that we don't inject
213
252
// duplicate tags when multiple components import the same css file
214
253
const idQuery = ! style . src || style . scoped ? `&id=${ id } ` : ``
215
254
const inlineQuery = asCustomElement ? `&inline` : ``
216
- const query = `?vue&type=style&index=${ i } ${ idQuery } ${ inlineQuery } ${ attrsQuery } ${ resourceQuery } `
217
- const styleRequest = stringifyRequest ( src + query )
255
+ const externalQuery = Boolean ( style . src ) ? `&external` : ``
256
+ const query = `?vue&type=style&index=${ i } ${ idQuery } ${ inlineQuery } ${ attrsQuery } ${ resourceQuery } ${ externalQuery } `
257
+
258
+ let styleRequest
259
+ if ( enableInlineMatchResource ) {
260
+ styleRequest = stringifyRequest (
261
+ genMatchResource ( this , src , query , lang ) ,
262
+ )
263
+ } else {
264
+ styleRequest = stringifyRequest ( src + query )
265
+ }
218
266
219
267
if ( style . module ) {
220
268
if ( asCustomElement ) {
221
269
loaderContext . emitError (
222
270
new Error (
223
- `<style module> is not supported in custom element mode.`
224
- )
271
+ `<style module> is not supported in custom element mode.` ,
272
+ ) ,
225
273
)
226
274
}
227
275
if ( ! hasCSSModules ) {
@@ -234,7 +282,7 @@ export default function loader(
234
282
i ,
235
283
styleRequest ,
236
284
style . module ,
237
- needsHotReload
285
+ needsHotReload ,
238
286
)
239
287
} else {
240
288
if ( ! isServer ) {
@@ -300,9 +348,27 @@ export default function loader(
300
348
const issuerQuery = block . attrs . src
301
349
? `&issuerPath=${ qs . escape ( resourcePath ) } `
302
350
: ''
303
- const query = `?vue&type=custom&index=${ i } ${ blockTypeQuery } ${ issuerQuery } ${ attrsQuery } ${ resourceQuery } `
351
+
352
+ const externalQuery = Boolean ( block . attrs . src ) ? `&external` : ``
353
+ const query = `?vue&type=custom&index=${ i } ${ blockTypeQuery } ${ issuerQuery } ${ attrsQuery } ${ resourceQuery } ${ externalQuery } `
354
+
355
+ let customRequest
356
+
357
+ if ( enableInlineMatchResource ) {
358
+ customRequest = stringifyRequest (
359
+ genMatchResource (
360
+ this ,
361
+ src as string ,
362
+ query ,
363
+ block . attrs . lang as string ,
364
+ ) ,
365
+ )
366
+ } else {
367
+ customRequest = stringifyRequest ( src + query )
368
+ }
369
+
304
370
return (
305
- `import block${ i } from ${ stringifyRequest ( src + query ) } \n` +
371
+ `import block${ i } from ${ customRequest } \n` +
306
372
`if (typeof block${ i } === 'function') block${ i } (script)`
307
373
)
308
374
} )
@@ -332,7 +398,9 @@ export default function loader(
332
398
if ( ! propsToAttach . length ) {
333
399
code += `\n\nconst __exports__ = script;`
334
400
} else {
335
- code += `\n\nimport exportComponent from ${ stringifyRequest ( exportHelperPath ) } `
401
+ code += `\n\nimport exportComponent from ${ stringifyRequest (
402
+ exportHelperPath ,
403
+ ) } `
336
404
code += `\nconst __exports__ = /*#__PURE__*/exportComponent(script, [${ propsToAttach
337
405
. map ( ( [ key , val ] ) => `['${ key } ',${ val } ]` )
338
406
. join ( ',' ) } ])`
0 commit comments