@@ -14,6 +14,7 @@ import { createRollupError } from './utils/error'
1414import  {  resolveScript  }  from  './script' 
1515import  {  transformTemplateInMain  }  from  './template' 
1616import  {  isOnlyTemplateChanged  }  from  './handleHotUpdate' 
17+ import  {  RawSourceMap ,  SourceMapConsumer ,  SourceMapGenerator  }  from  'source-map' 
1718
1819export  async  function  genSfcFacade ( 
1920  code : string , 
@@ -30,7 +31,6 @@ export async function genSfcFacade(
3031  const  {  descriptor,  errors }  =  parse ( code ,  { 
3132    sourceMap : true , 
3233    filename, 
33-     sourceRoot, 
3434  } ) 
3535  setDescriptor ( filename ,  descriptor ) 
3636
@@ -68,9 +68,17 @@ export async function genSfcFacade(
6868    ! ( descriptor . template  &&  descriptor . template . src ) 
6969  const  hasTemplateImport  =  descriptor . template  &&  ! useInlineTemplate 
7070
71-   const  templateCode  =  hasTemplateImport 
72-     ? genTemplateCode ( descriptor ,  scopeId ,  options ,  isServer ,  pluginContext ) 
73-     : '' 
71+   let  templateCode  =  '' 
72+   let  templateMap 
73+   if  ( hasTemplateImport )  { 
74+     ; ( {  code : templateCode ,  map : templateMap  }  =  genTemplateCode ( 
75+       descriptor , 
76+       scopeId , 
77+       options , 
78+       isServer , 
79+       pluginContext 
80+     ) ) 
81+   } 
7482
7583  const  renderReplace  =  hasTemplateImport 
7684    ? isServer 
@@ -128,9 +136,34 @@ export async function genSfcFacade(
128136    ) 
129137  } 
130138
139+   // if the template is inlined into the main module (indicated by the presence 
140+   // of templateMap, we need to concatenate the two source maps. 
141+   let  resolvedMap  =  map 
142+   if  ( map  &&  templateMap )  { 
143+     const  generator  =  SourceMapGenerator . fromSourceMap ( 
144+       new  SourceMapConsumer ( map ) 
145+     ) 
146+     const  offset  =  scriptCode . match ( / \r ? \n / g) ?. length  ||  1 
147+     const  templateMapConsumer  =  new  SourceMapConsumer ( templateMap ) 
148+     templateMapConsumer . eachMapping ( ( m )  =>  { 
149+       generator . addMapping ( { 
150+         source : m . source , 
151+         original : {  line : m . originalLine ,  column : m . originalColumn  } , 
152+         generated : { 
153+           line : m . generatedLine  +  offset , 
154+           column : m . generatedColumn , 
155+         } , 
156+       } ) 
157+     } ) 
158+     resolvedMap  =  ( generator  as  any ) . toJSON ( ) 
159+     // if this is a template only update, we will be reusing a cached version 
160+     // of the main module compile result, which has outdated sourcesContent. 
161+     resolvedMap . sourcesContent  =  templateMap . sourcesContent 
162+   } 
163+ 
131164  return  { 
132165    code : output . join ( '\n' ) , 
133-     map : map  ||  { 
166+     map : resolvedMap  ||  { 
134167      mappings : '' , 
135168    } , 
136169  } 
@@ -146,6 +179,9 @@ function genTemplateCode(
146179  const  renderFnName  =  isServer  ? 'ssrRender'  : 'render' 
147180  const  template  =  descriptor . template ! 
148181
182+   // If the template is not using pre-processor AND is not using external src, 
183+   // compile and inline it directly in the main module. When served in vite this 
184+   // saves an extra request per SFC which can improve load performance. 
149185  if  ( ! template . lang  &&  ! template . src )  { 
150186    return  transformTemplateInMain ( 
151187      template . content , 
@@ -160,9 +196,12 @@ function genTemplateCode(
160196    const  srcQuery  =  template . src  ? `&src`  : `` 
161197    const  attrsQuery  =  attrsToQuery ( template . attrs ,  'js' ,  true ) 
162198    const  query  =  `?vue&type=template${ idQuery } ${ srcQuery } ${ attrsQuery }  ` 
163-     return  `import { ${ renderFnName }   as _sfc_${ renderFnName }   } from ${ JSON . stringify (  
164-       src  +  query  
165-     ) }  `
199+     return  { 
200+       code : `import { ${ renderFnName }   as _sfc_${ renderFnName }   } from ${ JSON . stringify (  
201+         src  +  query  
202+       ) }  `, 
203+       map : undefined , 
204+     } 
166205  } 
167206} 
168207
@@ -173,7 +212,10 @@ async function genScriptCode(
173212  isServer : boolean , 
174213  options : Options , 
175214  pluginContext : TransformPluginContext 
176- )  { 
215+ ) : Promise < { 
216+   code : string 
217+   map : RawSourceMap 
218+ } >  { 
177219  let  scriptCode  =  `const _sfc_main = {}` 
178220  let  map 
179221  const  script  =  resolveScript ( 
@@ -185,7 +227,8 @@ async function genScriptCode(
185227    pluginContext 
186228  ) 
187229  if  ( script )  { 
188-     // js or ts can be directly placed in the main module 
230+     // If the script is js/ts and has no external src, it can be directly placed 
231+     // in the main module. 
189232    if  ( 
190233      ( ! script . lang  || 
191234        ( script . lang  ===  'ts'  &&  ( pluginContext  as  any ) . server ) )  && 
0 commit comments