Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 2 additions & 70 deletions packages/devtools/src/app/components/data/ModuleDetailsLoader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
import type { ModuleInfo, RolldownModuleTransformInfo, SessionContext } from '~~/shared/types'
import { useRpc } from '#imports'
import { computedAsync } from '@vueuse/core'
import { computed, nextTick, ref, watchEffect } from 'vue'
import { nextTick, ref, watchEffect } from 'vue'
import { settings } from '~~/app/state/settings'
import { getContentByteSize } from '~~/app/utils/format'

const props = defineProps<{
session: SessionContext
Expand Down Expand Up @@ -45,41 +44,6 @@ const info = computedAsync(async () => {
} as ModuleInfo
})

const durations = computed(() => {
const data = info.value
const _resolveIds = data?.resolve_ids.reduce((t, node) => {
t += node.duration
return t
}, 0) ?? 0
const _loads = data?.loads?.reduce((t, node) => {
t += node.duration
return t
}, 0) ?? 0
const _transforms = data?.transforms.reduce((t, node) => {
t += node.duration
return t
}, 0) ?? 0
const total = _resolveIds + _loads + _transforms
return {
resolveIds: _resolveIds,
loads: _loads,
transforms: _transforms,
total,
}
})

const sourceCodeSize = computed(() => {
const data = info.value?.transforms
const source = data?.[0]?.content_from ?? ''
return getContentByteSize(source)
})

const transformedCodeSize = computed(() => {
const data = info.value?.transforms?.filter(t => t.content_to)?.reverse()
const source = data?.[0]?.content_to ?? ''
return getContentByteSize(source)
})

function selectFlowNode(v: boolean) {
flowNodeSelected.value = v
}
Expand All @@ -98,39 +62,7 @@ function selectFlowNode(v: boolean) {
>
<DisplayModuleId :id="module" px2 pt1 :session />
<div text-xs font-mono flex="~ items-center gap-3" ml2>
<DisplayDuration
:duration="durations.resolveIds" flex="~ gap-1 items-center"
:title="`resolveId hooks cost: ${durations.resolveIds}ms`"
>
<span i-ph-magnifying-glass-duotone inline-block />
</DisplayDuration>
<DisplayDuration
:duration="durations.loads" flex="~ gap-1 items-center"
:title="`load hooks cost: ${durations.loads}ms`"
>
<span i-ph-upload-simple-duotone inline-block />
</DisplayDuration>
<DisplayDuration
:duration="durations.transforms" flex="~ gap-1 items-center"
:title="`transform hooks cost: ${durations.transforms}ms`"
>
<span i-ph-magic-wand-duotone inline-block />
</DisplayDuration>
<span op40>|</span>
<DisplayDuration
:duration="durations.total" flex="~ gap-1 items-center"
:title="`Total build cost: ${durations.total}ms`"
>
<span i-ph-clock-duotone inline-block />
</DisplayDuration>
<template v-if="sourceCodeSize && transformedCodeSize">
<span op40>|</span>
<div flex="~ gap-1 items-center">
<DisplayFileSizeBadge title="Source code size" :bytes="sourceCodeSize" />
<span i-carbon-arrow-right op50 />
<DisplayFileSizeBadge title="Transformed code size" :bytes="transformedCodeSize" />
</div>
</template>
<ModulesBuildMetrics v-if="info" :metrics="info.build_metrics" />
</div>
<div flex="~ gap-2">
<button
Expand Down
3 changes: 3 additions & 0 deletions packages/devtools/src/app/components/display/ModuleId.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ const containerClass = computed(() => {
text="virtual"
/> -->
</div>
<div>
<slot name="detail" />
</div>
<template #popper>
<span font-mono text-sm>
{{ props.id }}
Expand Down
83 changes: 83 additions & 0 deletions packages/devtools/src/app/components/modules/BuildMetrics.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<script setup lang="ts">
import type { ModuleBuildMetrics } from '~~/shared/types'
import { computed } from 'vue'

const props = defineProps<{
metrics: ModuleBuildMetrics
}>()

const durations = computed(() => {
const data = props.metrics
const _resolveIds = data?.resolve_ids.reduce((t, node) => {
t += node.duration
return t
}, 0) ?? 0
const _loads = data?.loads?.reduce((t, node) => {
t += node.duration
return t
}, 0) ?? 0
const _transforms = data?.transforms.reduce((t, node) => {
t += node.duration
return t
}, 0) ?? 0
const total = _resolveIds + _loads + _transforms
return {
resolveIds: _resolveIds,
loads: _loads,
transforms: _transforms,
total,
}
})

const sourceCodeSize = computed(() => {
const data = props.metrics?.transforms
return data?.[0]?.source_code_size
})

const transformedCodeSize = computed(() => {
const data = props.metrics?.transforms.filter(t => t.transformed_code_size)
return data?.[data.length - 1]?.transformed_code_size
})
</script>

<template>
<div text-xs font-mono flex="~ items-center gap-3" ml2>
<DisplayDuration
:duration="durations.resolveIds" flex="~ gap-1 items-center"
:title="`resolveId hooks cost: ${durations.resolveIds}ms`"
>
<span i-ph-magnifying-glass-duotone inline-block />
</DisplayDuration>
<DisplayDuration
:duration="durations.loads" flex="~ gap-1 items-center"
:title="`load hooks cost: ${durations.loads}ms`"
>
<span i-ph-upload-simple-duotone inline-block />
</DisplayDuration>
<DisplayDuration
:duration="durations.transforms" flex="~ gap-1 items-center"
:title="`transform hooks cost: ${durations.transforms}ms`"
>
<span i-ph-magic-wand-duotone inline-block />
</DisplayDuration>
<span op40>|</span>
<DisplayDuration
:duration="durations.total" flex="~ gap-1 items-center"
:title="`Total build cost: ${durations.total}ms`"
>
<span i-ph-clock-duotone inline-block />
</DisplayDuration>
<template v-if="sourceCodeSize && transformedCodeSize">
<span op40>|</span>
<div flex="~ gap-1 items-center">
<DisplayFileSizeBadge title="Source code size" :bytes="sourceCodeSize" />
<span i-carbon-arrow-right op50 />
<DisplayFileSizeBadge title="Transformed code size" :bytes="transformedCodeSize" />
</div>
</template>
</div>
</template>

<style scoped>

</style>
57 changes: 57 additions & 0 deletions packages/devtools/src/app/components/modules/DetailedList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script setup lang="ts">
import type { ModuleListItem, SessionContext } from '~~/shared/types'
import { computed } from 'vue'

const props = defineProps<{
session: SessionContext
modules: ModuleListItem[]
}>()

const filteredTransformsMap = computed(() => {
const map = new Map<string, Exclude<ModuleListItem['buildMetrics'], undefined>['transforms']>()
for (const mod of props.modules) {
const t = mod.buildMetrics?.transforms.filter(i => i.source_code_size !== i.transformed_code_size).filter(i => i.transformed_code_size)
map.set(mod.id, t!)
}
return map
})
</script>

<template>
<div flex="~ col gap-2" p4>
<template v-for="mod of modules" :key="mod">
<div>
<DisplayModuleId
:id="mod.id"
:session
hover="bg-active" block px2 p1
border="~ base rounded"
:link="true"
>
<template #detail>
<div flex="~ gap-1 wrap" text-xs>
<ul flex="~ auto text-xs wrap">
<template v-for="(p, i) of filteredTransformsMap.get(mod.id)" :key="i">
<li v-if="p.source_code_size !== p.transformed_code_size && p.transformed_code_size" flex="~ items-center">
<DisplayPluginName
:name="p.plugin_name"
class="font-mono ws-nowrap op-50"
/>
<span v-if="i !== filteredTransformsMap.get(mod.id)!.length - 1" op20>|</span>
</li>
</template>
</ul>

<div flex="~ auto gap-1" of-hidden />
<div flex="~ none gap-1 wrap justify-end">
<span>
<ModulesBuildMetrics v-if="mod.buildMetrics" :metrics="mod.buildMetrics" />
</span>
</div>
</div>
</template>
</DisplayModuleId>
</div>
</template>
</div>
</template>
1 change: 0 additions & 1 deletion packages/devtools/src/app/components/modules/FlatList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ defineProps<{
<template>
<div flex="~ col gap-2" p4>
<template v-for="mod of modules" :key="mod">
<!-- WIP: toggle to show detailed list like plugins and time cost -->
<DisplayModuleId
:id="mod.id"
:session
Expand Down
1 change: 1 addition & 0 deletions packages/devtools/src/app/pages/session/[session].vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ onMounted(async () => {
fileType: getFileTypeFromName(mod.id).name,
imports: mod.imports ?? [],
importers: mod.importers ?? [],
buildMetrics: mod.build_metrics,
}))
session.buildDuration = summary.build_duration
isLoading.value = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ const moduleViewTypes = [
{
label: 'List',
value: 'list',
icon: 'i-ph-list-duotone',
icon: 'i-carbon-list',
},
{
label: 'DetailedList',
value: 'detailed-list',
icon: 'i-carbon-list-boxes',
},
{
label: 'Graph',
Expand Down Expand Up @@ -161,6 +166,19 @@ function toggleDisplay(type: ClientSettings['moduleGraphViewType']) {
</div>
</div>
</template>
<template v-else-if="settings.moduleGraphViewType === 'detailed-list'">
<div of-auto h-screen pt-45>
<ModulesDetailedList
:session="session"
:modules="searched"
/>
<div
absolute bottom-4 py-1 px-2 bg-glass left="1/2" translate-x="-1/2" border="~ base rounded-full" text="center xs"
>
<span op50>{{ searched.length }} of {{ session.modulesList.length }}</span>
</div>
</div>
</template>
<template v-else-if="settings.moduleGraphViewType === 'graph'">
<ModulesGraph
:session="session"
Expand Down
2 changes: 1 addition & 1 deletion packages/devtools/src/app/state/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface ClientSettings {
flowExpandAssets: boolean
flowShowAllTransforms: boolean
flowShowAllLoads: boolean
moduleGraphViewType: 'list' | 'graph' | 'folder'
moduleGraphViewType: 'list' | 'detailed-list' | 'graph' | 'folder'
assetViewType: 'list' | 'folder' | 'treemap' | 'sunburst' | 'flamegraph'
chartAnimation: boolean
moduleDetailsViewType: 'flow' | 'charts' | 'imports'
Expand Down
Loading
Loading