Skip to content

Commit e45e874

Browse files
committed
feat(kit): use virtual module to host import scripts
1 parent 30ad870 commit e45e874

File tree

6 files changed

+94
-23
lines changed

6 files changed

+94
-23
lines changed

packages/core/playground/vite.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export default defineConfig({
3939
id: 'local',
4040
type: 'iframe',
4141
url: 'https://antfu.me',
42-
4342
})
4443

4544
ctx.docks.register({

packages/core/src/client/webcomponents/.generated/css.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

packages/core/src/client/webcomponents/components/Dock.vue

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
2-
import type { ClientScriptEntry, DevToolsDockEntry } from '@vitejs/devtools-kit'
2+
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
3+
import type { ImportScriptContext } from '@vitejs/devtools-kit/client'
34
import type { DockProps } from './DockProps'
45
import { useEventListener, useScreenSafeArea } from '@vueuse/core'
56
import { computed, onMounted, reactive, ref, toRefs, useTemplateRef, watchEffect } from 'vue'
@@ -215,28 +216,46 @@ const panelStyle = computed(() => {
215216
})
216217
217218
// TODO: use a visual module to host all the imports
218-
function importScript(entry: ClientScriptEntry) {
219-
return import(/* @vite-ignore */ entry.importFrom)
219+
function importScript(entry: DevToolsDockEntry): Promise<(context: ImportScriptContext) => void | Promise<void>> {
220+
const id = entry.id
221+
return import(/* vite-ignore */ ['/.devtools', 'imports'].join('-'))
220222
.then((module) => {
221-
return module[entry.importName || 'default']
223+
const importsMap = module.importsMap as Record<string, () => Promise<() => void>>
224+
const importFn = importsMap[id]
225+
if (!importFn) {
226+
return Promise.reject(new Error(`[VITE DEVTOOLS] No import found for id: ${id}`))
227+
}
228+
return importFn()
222229
})
223230
.catch((error) => {
224231
// TODO: maybe popup a error toast here?
225-
console.error('[VITE DEVTOOLS] Error importing action', error)
232+
console.error('[VITE DEVTOOLS] Error executing import action', error)
226233
return Promise.reject(error)
227234
})
228235
}
229236
230237
function onSelected(entry: DevToolsDockEntry) {
231-
if (entry?.type === 'action') {
232-
return importScript(entry.import).then(fn => fn())
233-
}
234-
235-
state.value.dockEntry = entry
238+
const context: ImportScriptContext = reactive({
239+
dockEntry: entry,
240+
// @ts-expect-error cast for unwraping
241+
dockState: computed<'active' | 'inactive'>({
242+
get() {
243+
return state.value.dockEntry?.id === entry.id ? 'active' : 'inactive'
244+
},
245+
set(val) {
246+
if (val === 'active')
247+
state.value.dockEntry = entry
248+
else if (state.value.dockEntry?.id === entry.id)
249+
state.value.dockEntry = undefined
250+
},
251+
}),
252+
hidePanel() {
253+
state.value.open = false
254+
},
255+
})
236256
237-
// TODO: handle for each type of entry
238-
if ('import' in entry && entry.import) {
239-
importScript(entry.import)
257+
if (entry?.type === 'action') {
258+
return importScript(entry).then(fn => fn(context))
240259
}
241260
}
242261

packages/core/src/client/webcomponents/components/DockIcon.vue

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<script setup lang="ts">
2-
defineProps<{
2+
import { computed } from 'vue'
3+
4+
const props = defineProps<{
35
icon: string
46
title?: string
57
}>()
@@ -14,12 +16,23 @@ function getIconUrl(str: string, color: 'dark' | 'light') {
1416
}
1517
return str
1618
}
19+
20+
const icon = computed(() => {
21+
return {
22+
dark: getIconUrl(props.icon, 'dark'),
23+
light: getIconUrl(props.icon, 'light'),
24+
}
25+
})
1726
</script>
1827

1928
<template>
20-
<img
21-
:src="getIconUrl(icon, 'dark')"
22-
:alt="title"
23-
draggable="false"
24-
>
29+
<picture>
30+
<source :srcset="icon.dark" media="(prefers-color-scheme: dark)">
31+
<source :srcset="icon.light" media="(prefers-color-scheme: light)">
32+
<img
33+
:src="icon.light"
34+
:alt="title"
35+
draggable="false"
36+
>
37+
</picture>
2538
</template>

packages/core/src/node/plugins/server.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { DevToolsNodeContext } from '@vitejs/devtools-kit'
12
import type { Plugin } from 'vite'
23
import { createDevToolsContext } from '../context'
34
import { createDevToolsMiddleware } from '../server'
@@ -7,17 +8,37 @@ import '../rpc'
78
* Core plugin for enabling Vite DevTools
89
*/
910
export function DevToolsServer(): Plugin {
11+
let context: DevToolsNodeContext
1012
return {
1113
name: 'vite:devtools:server',
1214
enforce: 'post',
1315
apply: 'serve',
1416
async configureServer(viteDevServer) {
15-
const context = await createDevToolsContext(viteDevServer.config, viteDevServer)
17+
context = await createDevToolsContext(viteDevServer.config, viteDevServer)
1618
const { middleware } = await createDevToolsMiddleware({
1719
cwd: viteDevServer.config.root,
1820
context,
1921
})
2022
viteDevServer.middlewares.use('/.devtools/', middleware)
2123
},
24+
resolveId(id) {
25+
if (id === '/.devtools-imports') {
26+
return id
27+
}
28+
},
29+
load(id) {
30+
if (id === '/.devtools-imports') {
31+
if (!context) {
32+
throw new Error('DevTools context is not initialized')
33+
}
34+
const docks = Array.from(context.docks.values())
35+
const imports = docks.map(i => i.import ? { id: i.id, ...i.import } : undefined).filter(x => !!x)
36+
return [
37+
`export const importsMap = {`,
38+
...imports.map(i => ` ${JSON.stringify(i.id)}: () => import(${JSON.stringify(i.importFrom)}).then(r => r[${JSON.stringify(i.importName)}]),`),
39+
'}',
40+
].join('\n')
41+
}
42+
},
2243
}
2344
}

packages/kit/src/client/index.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { WebSocketRpcClientOptions } from '@vitejs/devtools-rpc/presets/ws/client'
22
import type { BirpcOptions, BirpcReturn } from 'birpc'
3-
import type { ConnectionMeta, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from '../types'
3+
import type { ConnectionMeta, DevToolsDockEntry, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from '../types'
44
import { createRpcClient } from '@vitejs/devtools-rpc'
55
import { createWsRpcPreset } from '@vitejs/devtools-rpc/presets/ws/client'
66

@@ -17,6 +17,25 @@ export interface DevToolsRpcClientOptions {
1717
rpcOptions?: Partial<BirpcOptions<DevToolsRpcServerFunctions>>
1818
}
1919

20+
export interface ImportScriptContext {
21+
/**
22+
* The dock entry info of the current dock item
23+
*/
24+
dockEntry: DevToolsDockEntry
25+
/**
26+
* The current state of the dock
27+
*/
28+
dockState: 'active' | 'inactive'
29+
/**
30+
* Function to hide the panel, if applicable
31+
*/
32+
hidePanel: () => void
33+
/**
34+
* The panel element to mount into, if applicable
35+
*/
36+
elPanel?: HTMLElement | null
37+
}
38+
2039
export async function getDevToolsRpcClient(
2140
options: DevToolsRpcClientOptions = {},
2241
): Promise<{

0 commit comments

Comments
 (0)