11import { fileURLToPath } from 'node:url'
22import path from 'node:path'
3+ import fs from 'node:fs'
34import { normalizePath } from 'vite'
45import type { PluginOption , ResolvedConfig , ViteDevServer } from 'vite'
56import sirv from 'sirv'
@@ -11,6 +12,7 @@ import { bold, cyan, dim, green, yellow } from 'kolorist'
1112import type { VitePluginInspectorOptions } from 'vite-plugin-vue-inspector'
1213import { DIR_CLIENT } from './dir'
1314import { getRpcFunctions } from './rpc'
15+ import { removeUrlQuery } from './utils'
1416
1517function getVueDevtoolsPath ( ) {
1618 const pluginPath = normalizePath ( path . dirname ( fileURLToPath ( import . meta. url ) ) )
@@ -26,6 +28,8 @@ function normalizeComboKeyPrint(toggleComboKey: string) {
2628 return toggleComboKey . split ( '-' ) . map ( key => toggleComboKeysMap [ key ] || key [ 0 ] . toUpperCase ( ) + key . slice ( 1 ) ) . join ( dim ( '+' ) )
2729}
2830
31+ const devtoolsNextResourceSymbol = '?__vue-devtools-next-resource'
32+
2933export interface VitePluginVueDevToolsOptions {
3034 /**
3135 * append an import to the module id ending with `appendTo` instead of adding a script into body
@@ -118,6 +122,10 @@ export default function VitePluginVueDevTools(options?: VitePluginVueDevToolsOpt
118122 console . log ( ` ${ green ( '➜' ) } ${ bold ( 'Vue DevTools' ) } : ${ green ( `Press ${ yellow ( keys ) } in App to toggle the Vue DevTools` ) } \n` )
119123 }
120124 }
125+
126+ const devtoolsOptionsImportee = 'virtual:vue-devtools-options'
127+ const resolvedDevtoolsOptions = `\0${ devtoolsOptionsImportee } `
128+
121129 const plugin = < PluginOption > {
122130 name : 'vite-plugin-vue-devtools' ,
123131 enforce : 'pre' ,
@@ -129,17 +137,26 @@ export default function VitePluginVueDevTools(options?: VitePluginVueDevToolsOpt
129137 configureServer ( server )
130138 } ,
131139 async resolveId ( importee : string ) {
132- if ( importee . startsWith ( 'virtual:vue-devtools-options' ) ) {
133- return importee
140+ if ( importee === devtoolsOptionsImportee ) {
141+ return resolvedDevtoolsOptions
134142 }
143+ // Why use query instead of vite virtual module on devtools resource?
144+ // Devtools resource will import `@vue/devtools-core` and other packages, which vite cannot analysis correctly on virtual module.
145+ // So we should use absolute path + `query` to mark the resource as devtools resource.
135146 else if ( importee . startsWith ( 'virtual:vue-devtools-path:' ) ) {
136147 const resolved = importee . replace ( 'virtual:vue-devtools-path:' , `${ vueDevtoolsPath } /` )
137- return resolved
148+ return ` ${ resolved } ${ devtoolsNextResourceSymbol } `
138149 }
139150 } ,
140151 async load ( id ) {
141- if ( id === 'virtual:vue-devtools-options' )
152+ if ( id === resolvedDevtoolsOptions ) {
142153 return `export default ${ JSON . stringify ( { base : config . base , componentInspector : pluginOptions . componentInspector } ) } `
154+ }
155+ else if ( id . endsWith ( devtoolsNextResourceSymbol ) ) {
156+ const filename = removeUrlQuery ( id )
157+ // read file ourselves to avoid getting shut out by vite's fs.allow check
158+ return await fs . promises . readFile ( filename , 'utf-8' )
159+ }
143160 } ,
144161 transform ( code , id , options ) {
145162 if ( options ?. ssr )
0 commit comments