From b45bf94450effbb01bb3a4fe78e2871026ebef27 Mon Sep 17 00:00:00 2001 From: Alex <49969959+alexzhang1030@users.noreply.github.com> Date: Tue, 23 Jul 2024 22:49:58 +0800 Subject: [PATCH] refactor(vite): load devtools resource (#521) --- packages/vite/src/utils.ts | 3 +++ packages/vite/src/vite.ts | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 packages/vite/src/utils.ts diff --git a/packages/vite/src/utils.ts b/packages/vite/src/utils.ts new file mode 100644 index 000000000..4e4580c28 --- /dev/null +++ b/packages/vite/src/utils.ts @@ -0,0 +1,3 @@ +export function removeUrlQuery(url: string): string { + return url.replace(/\?.*$/, '') +} diff --git a/packages/vite/src/vite.ts b/packages/vite/src/vite.ts index 2f65cc31a..3d463f827 100644 --- a/packages/vite/src/vite.ts +++ b/packages/vite/src/vite.ts @@ -1,5 +1,6 @@ import { fileURLToPath } from 'node:url' import path from 'node:path' +import fs from 'node:fs' import { normalizePath } from 'vite' import type { PluginOption, ResolvedConfig, ViteDevServer } from 'vite' import sirv from 'sirv' @@ -11,6 +12,7 @@ import { bold, cyan, dim, green, yellow } from 'kolorist' import type { VitePluginInspectorOptions } from 'vite-plugin-vue-inspector' import { DIR_CLIENT } from './dir' import { getRpcFunctions } from './rpc' +import { removeUrlQuery } from './utils' function getVueDevtoolsPath() { const pluginPath = normalizePath(path.dirname(fileURLToPath(import.meta.url))) @@ -26,6 +28,8 @@ function normalizeComboKeyPrint(toggleComboKey: string) { return toggleComboKey.split('-').map(key => toggleComboKeysMap[key] || key[0].toUpperCase() + key.slice(1)).join(dim('+')) } +const devtoolsNextResourceSymbol = '?__vue-devtools-next-resource' + export interface VitePluginVueDevToolsOptions { /** * 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 console.log(` ${green('➜')} ${bold('Vue DevTools')}: ${green(`Press ${yellow(keys)} in App to toggle the Vue DevTools`)}\n`) } } + + const devtoolsOptionsImportee = 'virtual:vue-devtools-options' + const resolvedDevtoolsOptions = `\0${devtoolsOptionsImportee}` + const plugin = { name: 'vite-plugin-vue-devtools', enforce: 'pre', @@ -129,17 +137,26 @@ export default function VitePluginVueDevTools(options?: VitePluginVueDevToolsOpt configureServer(server) }, async resolveId(importee: string) { - if (importee.startsWith('virtual:vue-devtools-options')) { - return importee + if (importee === devtoolsOptionsImportee) { + return resolvedDevtoolsOptions } + // Why use query instead of vite virtual module on devtools resource? + // Devtools resource will import `@vue/devtools-core` and other packages, which vite cannot analysis correctly on virtual module. + // So we should use absolute path + `query` to mark the resource as devtools resource. else if (importee.startsWith('virtual:vue-devtools-path:')) { const resolved = importee.replace('virtual:vue-devtools-path:', `${vueDevtoolsPath}/`) - return resolved + return `${resolved}${devtoolsNextResourceSymbol}` } }, async load(id) { - if (id === 'virtual:vue-devtools-options') + if (id === resolvedDevtoolsOptions) { return `export default ${JSON.stringify({ base: config.base, componentInspector: pluginOptions.componentInspector })}` + } + else if (id.endsWith(devtoolsNextResourceSymbol)) { + const filename = removeUrlQuery(id) + // read file ourselves to avoid getting shut out by vite's fs.allow check + return await fs.promises.readFile(filename, 'utf-8') + } }, transform(code, id, options) { if (options?.ssr)