8000 perf(kit): enable plugin timeline on-demand · vuejs/devtools@809e204 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 809e204

Browse files
committed
perf(kit): enable plugin timeline on-demand
1 parent f98da4f commit 809e204

File tree

6 files changed

+59
-9
lines changed

6 files changed

+59
-9
lines changed

packages/applet/src/components/timeline/index.vue

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script setup lang="ts">
22
import type { CustomInspectorState, TimelineEventOptions } from '@vue/devtools-kit'
3-
import { DevToolsMessagingEvents, rpc } from '@vue/devtools-core'
3+
import { DevToolsMessagingEvents, rpc, useDevToolsState } from '@vue/devtools-core'
44
import { parse } from '@vue/devtools-kit'
5+
import { vTooltip, VueIcIcon } from '@vue/devtools-ui'
56
67
import { Pane, Splitpanes } from 'splitpanes'
78
import { computed, onUnmounted, ref } from 'vue'
@@ -14,6 +15,7 @@ import EventList from './EventList.vue'
1415
1516
const props = withDefaults(defineProps<{
1617
layerIds: string[]
18+
pluginId: string
1719
docLink: string
1820
githubRepoLink?: string
1921
headerVisible?: boolean
@@ -29,7 +31,10 @@ expandedStateNodes.value = ['0', '1']
2931
const eventList = ref<TimelineEventOptions['event'][]>([])
3032
const groupList = ref<Map<string | number | undefined, TimelineEventOptions['event'][]>>(new Map())
3133
const selectedEventIndex = ref(0)
34+
const devtoolsState = useDevToolsState()
35+
const recordingState = computed(() => devtoolsState.timelineLayersState.value?.[props.pluginId])
3236
const selectedEventInfo = computed(() => eventList.value[selectedEventIndex.value] ?? null)
37+
const recordingTooltip = computed(() => recordingState.value ? 'Stop recording' : 'Start recording')
3338
// event info
3439
const normalizedEventInfo = computed(() => {
3540
const info: CustomInspectorState[] = []
@@ -96,19 +101,28 @@ onUnmounted(() => {
96101
rpc.functions.off(DevToolsMessagingEvents.TIMELINE_EVENT_UPDATED, onTimelineEventUpdated)
97102
})
98103
104+
function clear() {
105+
eventList.value = []
106+
groupList.value.clear()
107+
}
108+
99109
defineExpose({
100-
clear() {
101-
eventList.value = []
102-
groupList.value.clear()
103-
},
110+
clear,
104111
})
112+
113+
function toggleRecordingState() {
114+
rpc.value.updateTimelineLayersState({
115+
[props.pluginId]: !recordingState.value,
116+
})
117+
}
105118
</script>
106119

107120
<template>
108-
<div class="h-full flex flex-col">
121+
<div class="relative h-full flex flex-col">
109122
<DevToolsHeader v-if="headerVisible" :doc-link="docLink" :github-repo-link="githubRepoLink">
110123
<Navbar />
111124
</DevToolsHeader>
125+
112126
<template v-if="eventList.length">
113127
<div class="flex-1 overflow-hidden">
114128
<Splitpanes class="h-full">
@@ -128,5 +142,36 @@ defineExpose({
128142
<Empty v-else class="flex-1">
129143
No events
130144
</Empty>
145+
146+
<div class="absolute right-3 top-12 flex items-center justify-end b-1 border-base rounded-1 b-solid px2 py1">
147+
<div class="flex items-center gap-2 px-1">
148+
<div v-tooltip.bottom-end="{ content: recordingTooltip }" class="flex items-center gap1" @click="toggleRecordingState">
149+
<span v-if="recordingState" class="recording recording-btn bg-[#ef4444]" />
150+
<span v-else class="recording-btn bg-black op70 dark:(bg-white) hover:op100" />
151+
</div>
152+
<div v-tooltip.bottom-end="{ content: 'Clear all timelines' }" class="flex items-center gap1" @click="clear">
153+
<VueIcIcon name="baseline-delete" cursor-pointer text-xl op70 hover:op100 />
154+
</div>
155+
<div v-tooltip.bottom-end="{ content: '<p style=\'width: 285px\'>Timeline events can cause significant performance overhead in large applications, so we recommend enabling it only when needed and on-demand. </p>', html: true }" class="flex items-center gap1">
156+
<VueIcIcon name="baseline-tips-and-updates" cursor-pointer text-xl op70 hover:op100 />
157+
</div>
158+
</div>
159+
</div>
131160
</div>
132161
</template>
162+
163+
<style scoped>
164+
@keyframes pulse {
165+
50% {
166+
opacity: 0.5;
167+
}
168+
}
169+
.recording-btn {
170+
--at-apply: w-3.5 h-3.5 inline-flex cursor-pointer rounded-50%;
171+
}
172+
.recording {
173+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
174+
transition-duration: 1s;
175+
box-shadow: #ef4444 0 0 8px;
176+
}
177+
</style>

packages/applet/src/modules/custom-inspector/components/timeline/Index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ const state = useCustomInspectorState()
66
</script>
77

88
<template>
9-
<Timeline :layer-ids="state.timelineLayerIds!" :doc-link="state.homepage!" />
9+
<Timeline :layer-ids="state.timelineLayerIds!" :doc-link="state.homepage!" :plugin-id="state.pluginId" />
1010
</template>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<script setup lang="ts">
22
import Timeline from '~/components/timeline/index.vue'
33
4+
const pluginDescriptorId = 'dev.esm.pinia'
45
const LAYER_IDS = ['pinia:mutations']
56
</script>
67

78
<template>
8-
<Timeline :layer-ids="LAYER_IDS" doc-link="https://pinia.vuejs.org/" github-repo-link="https://github.com/vuejs/pinia" />
9+
<Timeline :layer-ids="LAYER_IDS" doc-link="https://pinia.vuejs.org/" :plugin-id="pluginDescriptorId" github-repo-link="https://github.com/vuejs/pinia" />
910
</template>

packages/applet/src/modules/router/components/timeline/Index.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import Timeline from '~/components/timeline/index.vue'
33
import { useCustomInspectorState } from '~/composables/custom-inspector-state'
44
5+
const pluginDescriptorId = 'org.vuejs.router'
56
const state = useCustomInspectorState()
67
</script>
78

89
<template>
9-
<Timeline :layer-ids="state.timelineLayerIds!" doc-link="https://router.vuejs.org/" github-repo-link="https://github.com/vuejs/router" />
10+
<Timeline :layer-ids="state.timelineLayerIds!" doc-link="https://router.vuejs.org/" :plugin-id="pluginDescriptorId" github-repo-link="https://github.com/vuejs/router" />
1011
</template>

packages/devtools-kit/src/ctx/hook.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ export function createDevToolsCtxHooks() {
335335

336336
// add timeline event
337337
hooks.hook(DevToolsContextHookKeys.TIMELINE_EVENT_ADDED, ({ options, plugin }) => {
338+
if (devtoolsState.highPerfModeEnabled || !devtoolsState.timelineLayersState?.[plugin.descriptor.id])
339+
return
338340
// @ts-expect-error hookable
339341
hooks.callHookWith(async (callbacks) => {
340342
await Promise.all(callbacks.map(cb => cb(options)))

packages/devtools-kit/src/ctx/timeline.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const devtoolsTimelineLayers = new Proxy<DevToolsKitTimelineLayer[]>(targ
1818
})
1919

2020
export function addTimelineLayer(options: TimelineLayerOptions, descriptor: PluginDescriptor) {
21+
devtoolsState.timelineLayersState[descriptor.id] = false
2122
devtoolsTimelineLayers.push({
2223
...options,
2324
descriptorId: descriptor.id,

0 commit comments

Comments
 (0)
0