@@ -51,6 +51,8 @@ export interface VueLoaderOptions {
51
51
52
52
let errorEmitted = false
53
53
54
+ const exportHelperPath = JSON . stringify ( require . resolve ( './exportHelper' ) )
55
+
54
56
export default function loader (
55
57
this : webpack . loader . LoaderContext ,
56
58
source : string
@@ -154,6 +156,10 @@ export default function loader(
154
156
! ! ( descriptor . script || descriptor . scriptSetup || descriptor . template ) &&
155
157
options . hotReload !== false
156
158
159
+ // extra properties to attach to the script object
160
+ // we need to do this in a tree-shaking friendly manner
161
+ const propsToAttach : [ string , string ] [ ] = [ ]
162
+
157
163
// script
158
164
let scriptImport = `const script = {}`
159
165
let isTS = false
@@ -185,6 +191,7 @@ export default function loader(
185
191
const query = `?vue&type=template${ idQuery } ${ scopedQuery } ${ tsQuery } ${ attrsQuery } ${ resourceQuery } `
186
192
templateRequest = stringifyRequest ( src + query )
187
193
templateImport = `import { ${ renderFnName } } from ${ templateRequest } `
194
+ propsToAttach . push ( [ renderFnName , renderFnName ] )
188
195
}
189
196
190
197
// styles
@@ -210,7 +217,8 @@ export default function loader(
210
217
)
211
218
}
212
219
if ( ! hasCSSModules ) {
213
- stylesCode += `\nconst cssModules = script.__cssModules = {}`
220
+ stylesCode += `\nconst cssModules = {}`
221
+ propsToAttach . push ( [ `__cssModules` , `cssModules` ] )
214
222
hasCSSModules = true
215
223
}
216
224
stylesCode += genCSSModulesCode (
@@ -230,24 +238,20 @@ export default function loader(
230
238
// TODO SSR critical CSS collection
231
239
} )
232
240
if ( asCustomElement ) {
233
- stylesCode += `\nscript.styles = [${ descriptor . styles . map (
234
- ( _ , i ) => `_style_${ i } `
235
- ) } ]`
241
+ propsToAttach . push ( [
242
+ `styles` ,
243
+ `[${ descriptor . styles . map ( ( _ , i ) => `_style_${ i } ` ) } ]` ,
244
+ ] )
236
245
}
237
246
}
238
247
239
- let code = [
240
- templateImport ,
241
- scriptImport ,
242
- stylesCode ,
243
- templateImport ? `script.${ renderFnName } = ${ renderFnName } ` : `` ,
244
- ]
248
+ let code = [ templateImport , scriptImport , stylesCode ]
245
249
. filter ( Boolean )
246
250
. join ( '\n' )
247
251
248
252
// attach scope Id for runtime use
249
253
if ( hasScoped ) {
250
- code += `\nscript. __scopeId = "data-v-${ id } "`
254
+ propsToAttach . push ( [ ` __scopeId` , ` "data-v-${ id } "`] )
251
255
}
252
256
253
257
if ( needsHotReload ) {
@@ -258,13 +262,14 @@ export default function loader(
258
262
if ( ! isProduction ) {
259
263
// Expose the file's full path in development, so that it can be opened
260
264
// from the devtools.
261
- code += `\nscript.__file = ${ JSON . stringify (
262
- rawShortFilePath . replace ( / \\ / g, '/' )
263
- ) } `
265
+ propsToAttach . push ( [
266
+ `__file` ,
267
+ JSON . stringify ( rawShortFilePath . replace ( / \\ / g, '/' ) ) ,
268
+ ] )
264
269
} else if ( options . exposeFilename ) {
265
270
// Libraries can opt-in to expose their components' filenames in production builds.
266
271
// For security reasons, only expose the file's basename in production.
267
- code += `\nscript. __file = ${ JSON . stringify ( path . basename ( resourcePath ) ) } `
272
+ propsToAttach . push ( [ ` __file` , JSON . stringify ( path . basename ( resourcePath ) ) ] )
268
273
}
269
274
270
275
// custom blocks
@@ -282,14 +287,21 @@ export default function loader(
282
287
const query = `?vue&type=custom&index=${ i } ${ blockTypeQuery } ${ issuerQuery } ${ attrsQuery } ${ resourceQuery } `
283
288
return (
284
289
`import block${ i } from ${ stringifyRequest ( src + query ) } \n` +
285
- `if (typeof block${ i } === 'function') block${ i } (script)`
290
+ `if (typeof block${ i } === 'function') /*#__PURE__*/ block${ i } (script)`
286
291
)
287
292
} )
288
293
. join ( `\n` ) + `\n`
289
294
}
290
295
291
296
// finalize
292
- code += `\n\nexport default script`
297
+ if ( ! propsToAttach . length ) {
298
+ code += `\n\nexport default script`
299
+ } else {
300
+ code += `\n\nimport exportComponent from ${ exportHelperPath } `
301
+ code += `\nexport default /*#__PURE__*/exportComponent(script, [${ propsToAttach
302
+ . map ( ( [ key , val ] ) => `['${ key } ',${ val } ]` )
303
+ . join ( ',' ) } ])`
304
+ }
293
305
return code
294
306
}
295
307
0 commit comments