@@ -51,6 +51,8 @@ export interface VueLoaderOptions {
5151
5252let errorEmitted = false
5353
54+ const exportHelperPath = JSON . stringify ( require . resolve ( './exportHelper' ) )
55+
5456export default function loader (
5557 this : webpack . loader . LoaderContext ,
5658 source : string
@@ -154,6 +156,10 @@ export default function loader(
154156 ! ! ( descriptor . script || descriptor . scriptSetup || descriptor . template ) &&
155157 options . hotReload !== false
156158
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+
157163 // script
158164 let scriptImport = `const script = {}`
159165 let isTS = false
@@ -185,6 +191,7 @@ export default function loader(
185191 const query = `?vue&type=template${ idQuery } ${ scopedQuery } ${ tsQuery } ${ attrsQuery } ${ resourceQuery } `
186192 templateRequest = stringifyRequest ( src + query )
187193 templateImport = `import { ${ renderFnName } } from ${ templateRequest } `
194+ propsToAttach . push ( [ renderFnName , renderFnName ] )
188195 }
189196
190197 // styles
@@ -210,7 +217,8 @@ export default function loader(
210217 )
211218 }
212219 if ( ! hasCSSModules ) {
213- stylesCode += `\nconst cssModules = script.__cssModules = {}`
220+ stylesCode += `\nconst cssModules = {}`
221+ propsToAttach . push ( [ `__cssModules` , `cssModules` ] )
214222 hasCSSModules = true
215223 }
216224 stylesCode += genCSSModulesCode (
@@ -230,24 +238,20 @@ export default function loader(
230238 // TODO SSR critical CSS collection
231239 } )
232240 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+ ] )
236245 }
237246 }
238247
239- let code = [
240- templateImport ,
241- scriptImport ,
242- stylesCode ,
243- templateImport ? `script.${ renderFnName } = ${ renderFnName } ` : `` ,
244- ]
248+ let code = [ templateImport , scriptImport , stylesCode ]
245249 . filter ( Boolean )
246250 . join ( '\n' )
247251
248252 // attach scope Id for runtime use
249253 if ( hasScoped ) {
250- code += `\nscript. __scopeId = "data-v-${ id } "`
254+ propsToAttach . push ( [ ` __scopeId` , ` "data-v-${ id } "`] )
251255 }
252256
253257 if ( needsHotReload ) {
@@ -258,13 +262,14 @@ export default function loader(
258262 if ( ! isProduction ) {
259263 // Expose the file's full path in development, so that it can be opened
260264 // 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+ ] )
264269 } else if ( options . exposeFilename ) {
265270 // Libraries can opt-in to expose their components' filenames in production builds.
266271 // 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 ) ) ] )
268273 }
269274
270275 // custom blocks
@@ -282,14 +287,21 @@ export default function loader(
282287 const query = `?vue&type=custom&index=${ i } ${ blockTypeQuery } ${ issuerQuery } ${ attrsQuery } ${ resourceQuery } `
283288 return (
284289 `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)`
286291 )
287292 } )
288293 . join ( `\n` ) + `\n`
289294 }
290295
291296 // 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+ }
293305 return code
294306}
295307
0 commit comments