@@ -152,6 +152,8 @@ function VitePluginInspector(options: VitePluginInspectorOptions = DEFAULT_INSPE
152152 ...options ,
153153 }
154154 let config : ResolvedConfig
155+ let isBundledDev = false
156+ const htmlEntryModules = new Set < string > ( )
155157
156158 const {
157159 vue,
@@ -205,11 +207,15 @@ function VitePluginInspector(options: VitePluginInspectorOptions = DEFAULT_INSPE
205207 if ( isJsx || isTpl )
206208 return compileSFCTemplate ( { code, id : filename , type : isJsx ? 'jsx' : 'template' } )
207209
208- if ( ! appendTo )
210+ if ( appendTo ) {
211+ if ( ( typeof appendTo === 'string' && filename . endsWith ( appendTo ) )
212+ || ( appendTo instanceof RegExp && appendTo . test ( filename ) ) )
213+ return { code : `${ code } \nimport 'virtual:vue-inspector-path:load.js'` }
209214 return
215+ }
210216
211- if ( ( typeof appendTo === 'string' && filename . endsWith ( appendTo ) )
212- || ( appendTo instanceof RegExp && appendTo . test ( filename ) ) )
217+ // bundledDev: inject into HTML entry modules since transformIndexHtml URLs aren't bundled
218+ if ( isBundledDev && htmlEntryModules . has ( normalizePath ( filename ) ) )
213219 return { code : `${ code } \nimport 'virtual:vue-inspector-path:load.js'` }
214220 } ,
215221 configureServer ( server ) {
@@ -223,7 +229,7 @@ function VitePluginInspector(options: VitePluginInspectorOptions = DEFAULT_INSPE
223229 } )
224230 } ,
225231 transformIndexHtml ( html ) {
226- if ( appendTo )
232+ if ( appendTo || isBundledDev )
227233 return
228234 return {
229235 html,
@@ -241,6 +247,38 @@ function VitePluginInspector(options: VitePluginInspectorOptions = DEFAULT_INSPE
241247 } ,
242248 configResolved ( resolvedConfig ) {
243249 config = resolvedConfig
250+ isBundledDev = ! ! ( config as any ) . experimental ?. bundledDev
251+
252+ if ( isBundledDev && ! appendTo ) {
253+ // Find HTML entry files from rollupOptions.input or default index.html
254+ let htmlFiles : string [ ] = [ ]
255+ const inputs = resolvedConfig . build ?. rollupOptions ?. input
256+ if ( inputs ) {
257+ const files = typeof inputs === 'string'
258+ ? [ inputs ]
259+ : Array . isArray ( inputs )
260+ ? inputs
261+ : Object . values ( inputs )
262+ htmlFiles = files . filter ( f => f . endsWith ( '.html' ) )
263+ }
264+ if ( htmlFiles . length === 0 )
265+ htmlFiles = [ path . resolve ( config . root , 'index.html' ) ]
266+
267+ // Parse <script type="module" src="..."> from each HTML file
268+ const scriptModuleRE = / < s c r i p t \b (? = [ ^ > ] * \b t y p e \s * = \s * [ " ' ] m o d u l e [ " ' ] ) (? = [ ^ > ] * \b s r c \s * = \s * [ " ' ] ( [ ^ " ' ] + ) [ " ' ] ) [ ^ > ] * > / gi
269+ for ( const htmlFile of htmlFiles ) {
270+ const resolved = path . isAbsolute ( htmlFile ) ? htmlFile : path . resolve ( config . root , htmlFile )
271+ if ( ! fs . existsSync ( resolved ) )
272+ continue
273+ const html = fs . readFileSync ( resolved , 'utf-8' )
274+ let match : RegExpExecArray | null
275+ // eslint-disable-next-line no-cond-assign
276+ while ( ( match = scriptModuleRE . exec ( html ) ) !== null ) {
277+ const absPath = normalizePath ( path . resolve ( config . root , match [ 1 ] . replace ( / ^ \/ / , '' ) ) )
278+ htmlEntryModules . add ( absPath )
279+ }
280+ }
281+ }
244282 } ,
245283 } ,
246284 {
0 commit comments