Skip to content

Commit 0acd58b

Browse files
committed
feat: display chunk in flow
1 parent b6a9cd3 commit 0acd58b

File tree

9 files changed

+168
-57
lines changed

9 files changed

+168
-57
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<script setup lang="ts">
2+
import type { Chunk as ChunkInfo } from '@rolldown/debug'
3+
import type { SessionContext } from '~~/shared/types'
4+
5+
defineProps<{
6+
chunk: ChunkInfo
7+
session: SessionContext
8+
}>()
9+
</script>
10+
11+
<template>
12+
<div flex="~ col gap-3">
13+
<div flex="~ gap-4 items-center">
14+
<div flex="~ gap-2 items-center" :title="`Chunk #${chunk.chunk_id}`">
15+
<div i-ph-shapes-duotone />
16+
<div>{{ chunk.name || '[unnamed]' }}</div>
17+
<DisplayBadge :text="chunk.reason" />
18+
</div>
19+
<div flex-auto />
20+
<span op50 font-mono>#{{ chunk.chunk_id }}</span>
21+
<div flex="~ gap-1 items-center">
22+
<div i-ph-package-duotone />
23+
{{ chunk.modules.length }}
24+
</div>
25+
</div>
26+
27+
<div op50>
28+
Imports
29+
</div>
30+
<div flex="~ col gap-1" ws-nowrap>
31+
<!-- TODO: -->
32+
{{ chunk.imports }}
33+
</div>
34+
35+
<div op50>
36+
Modules
37+
</div>
38+
<div flex="~ col gap-1" ws-nowrap>
39+
<DisplayModuleId
40+
v-for="module of chunk.modules"
41+
:id="module"
42+
:key="module"
43+
:session
44+
:link="true"
45+
:minimal="true"
46+
hover="bg-active"
47+
border="~ base rounded" px2 py1 w-full
48+
/>
49+
</div>
50+
</div>
51+
</template>

packages/devtools/src/app/components/flowmap/ModuleFlow.vue

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import type { ModuleInfo, RolldownModuleFlowNode, RolldownModuleNoChanges, RolldownModuleNoChangesHide, RolldownModuleTransformInfo, SessionContext } from '~~/shared/types'
2+
import type { ModuleInfo, RolldownChunkInfo, RolldownModuleFlowNode, RolldownModuleNoChanges, RolldownModuleNoChangesHide, RolldownModuleTransformInfo, SessionContext } from '~~/shared/types'
33
import { Menu as VMenu } from 'floating-vue'
44
import { computed, shallowRef, toRefs, watch } from 'vue'
55
import { settingsRefs } from '~/state/settings'
@@ -23,7 +23,7 @@ const {
2323
flowExpandResolveId,
2424
} = settingsRefs
2525
26-
const selected = shallowRef<RolldownModuleFlowNode | null>(null)
26+
const selected = shallowRef<RolldownChunkInfo | RolldownModuleFlowNode | null>(null)
2727
2828
const resolveIds = computed(() => info?.value?.resolve_ids ?? [])
2929
@@ -97,9 +97,10 @@ const nodes = computed(() => [
9797
...resolveIds.value,
9898
...loads.value,
9999
...transforms.value,
100+
...info.value.chunks,
100101
])
101102
102-
function isSelectedAncestor(node?: RolldownModuleFlowNode) {
103+
function isSelectedAncestor(node?: RolldownModuleFlowNode | RolldownChunkInfo) {
103104
if (!selected.value || !node)
104105
return false
105106
const indexSelected = nodes.value.indexOf(selected.value)
@@ -109,17 +110,15 @@ function isSelectedAncestor(node?: RolldownModuleFlowNode) {
109110
return false
110111
}
111112
112-
function select(node: RolldownModuleFlowNode) {
113-
selected.value = node
114-
}
115-
116113
watch(selected, (v) => {
117114
emit('select', !!v)
118115
})
119116
120117
const codeDisplay = computed(() => {
121118
if (!selected.value)
122119
return null
120+
if (!('type' in selected.value))
121+
return null
123122
if (selected.value.type === 'transform') {
124123
return {
125124
type: 'transform',
@@ -239,7 +238,7 @@ const codeDisplay = computed(() => {
239238
:session="session"
240239
:active="isSelectedAncestor(item)"
241240
:class="index > 0 ? 'pt-2' : ''"
242-
@select="select"
241+
@select="e => selected = e"
243242
/>
244243
</div>
245244
</template>
@@ -265,7 +264,7 @@ const codeDisplay = computed(() => {
265264
:session="session"
266265
:active="isSelectedAncestor(item)"
267266
:class="index > 0 ? 'pt-2' : ''"
268-
@select="select"
267+
@select="e => selected = e"
269268
@toggle-show-all="flowShowAllLoads = !flowShowAllLoads"
270269
/>
271270
</div>
@@ -277,7 +276,7 @@ const codeDisplay = computed(() => {
277276
:expandable="transforms.length > 0"
278277
:class-root-node="transforms.length === 0 ? 'border-dashed' : ''"
279278
:active-start="isSelectedAncestor(transforms[0])"
280-
:active-end="isSelectedAncestor(transforms.at(-1))"
279+
:active-end="isSelectedAncestor(info.chunks[0] || transforms.at(-1))"
281280
>
282281
<template #node>
283282
<div i-ph-magic-wand-duotone /> Transform
@@ -293,18 +292,36 @@ const codeDisplay = computed(() => {
293292
:session="session"
294293
:active="isSelectedAncestor(item)"
295294
:class="index > 0 ? 'pt-2' : ''"
296-
@select="select"
295+
@select="e => selected = e"
297296
@toggle-show-all="flowShowAllTransforms = !flowShowAllTransforms"
298297
/>
299298
</div>
300299
</template>
301300
</FlowmapExpandable>
302301

303-
<FlowmapNode :lines="{ top: true, bottom: true }" pl6 pt4>
304-
<template #content>
302+
<FlowmapExpandable
303+
:lines="{ top: true, bottom: true }"
304+
:expandable="info.chunks.length > 0"
305+
:class-root-node="info.chunks.length === 0 ? 'border-dashed' : ''"
306+
:active-start="isSelectedAncestor(info.chunks[0])"
307+
:active-end="isSelectedAncestor(info.chunks.at(-1))"
308+
pl6 pt4
309+
>
310+
<template #node>
305311
<div i-ph-shapes-duotone /> Chunk
312+
<span op50 text-xs>({{ info.chunks.length }})</span>
306313
</template>
307-
</FlowmapNode>
314+
<template #container>
315+
<FlowmapNodeChunkInfo
316+
v-for="chunk of info.chunks"
317+
:key="chunk.chunk_id"
318+
:item="chunk"
319+
:active="isSelectedAncestor(chunk)"
320+
:session="session"
321+
@select="e => selected = e"
322+
/>
323+
</template>
324+
</FlowmapExpandable>
308325

309326
<FlowmapNode :lines="{ top: true, bottom: true }" pl6 pt4>
310327
<template #content>
@@ -324,7 +341,15 @@ const codeDisplay = computed(() => {
324341
:class="codeDisplay?.from && codeDisplay?.to ? '' : 'border-dashed'"
325342
border="~ base rounded-lg" of-hidden max-h-120vh m4 flex="~ col"
326343
>
327-
<template v-if="codeDisplay?.from && codeDisplay?.to">
344+
<template v-if="selected?.type === 'chunk'">
345+
<div p4>
346+
<DataChunkDetails
347+
:chunk="selected"
348+
:session="session"
349+
/>
350+
</div>
351+
</template>
352+
<template v-else-if="codeDisplay?.from && codeDisplay?.to">
328353
<div pl4 p2 font-mono border="b base" flex="~ items-center gap-2" h-max-100vh>
329354
<PluginName :name="codeDisplay?.plugin_name ?? ''" />
330355
<span v-if="codeDisplay?.type" op50 text-xs>

packages/devtools/src/app/components/flowmap/Node.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const props = defineProps<{
3131
props.classNodeOuter,
3232
active ? 'border-flow-active' : 'border-flow',
3333
]"
34-
border="~ rounded-full" bg-base of-hidden
34+
border="~ rounded-2xl" bg-base of-hidden
3535
>
3636
<slot name="inner">
3737
<div px3 py1 :class="props.classNodeInner" flex="~ inline gap-2 items-center">
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script setup lang="ts">
2+
import type { RolldownChunkInfo, SessionContext } from '~~/shared/types'
3+
4+
defineProps<{
5+
item: RolldownChunkInfo
6+
session: SessionContext
7+
active?: boolean
8+
}>()
9+
10+
const emit = defineEmits<{
11+
(e: 'select', item: RolldownChunkInfo): void
12+
}>()
13+
</script>
14+
15+
<template>
16+
<FlowmapNode
17+
:lines="{ top: true }"
18+
:active="active"
19+
class-node-inline="gap-2 items-center"
20+
pl6
21+
>
22+
<template #inner>
23+
<button
24+
px3 py1 hover="bg-active" flex="~ inline gap-2 items-center"
25+
@click="emit('select', item)"
26+
>
27+
<slot name="button">
28+
<div flex="~ col gap-1 items-start" p1>
29+
<div flex="~ gap-2 items-center">
30+
<DisplayBadge :text="item.name || '<unnamed chunk>'" />
31+
<div flex-auto />
32+
<div :title="`Chunk ID: ${item.chunk_id}`" op50 font-mono text-sm>
33+
#{{ item.chunk_id }}
34+
</div>
35+
</div>
36+
<div text-sm>
37+
{{ item.modules.length }} modules
38+
</div>
39+
</div>
40+
</slot>
41+
</button>
42+
</template>
43+
<template #inline-after>
44+
<DisplayBadge :text="item.reason" />
45+
</template>
46+
</FlowmapNode>
47+
</template>

packages/devtools/src/app/pages/session/[session]/chunks.vue

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,15 @@ const { state: chunks } = useAsyncState(
1919
</script>
2020

2121
<template>
22-
<div p5 flex="~ col gap-2">
22+
<div p5 flex="~ col gap-4">
2323
Chunks
24-
<!-- <pre>{{ chunks }}</pre> -->
25-
2624
<template v-for="chunk of chunks" :key="chunk.id">
27-
<div border="~ base rounded" flex="~ col gap-3" p2>
28-
<div flex="~ gap-1 items-center">
29-
<div flex="~ gap-1 items-center">
30-
<div i-ph-hash-duotone />
31-
<span>{{ chunk.name }}</span>
32-
<span>{{ chunk.chunk_id }}</span>
33-
<DisplayBadge :text="chunk.reason" />
34-
</div>
35-
<div flex-auto />
36-
<div flex="~ gap-1 items-center">
37-
<div i-ph-package-duotone />
38-
{{ chunk.modules.length }}
39-
</div>
40-
</div>
41-
<div flex="~ col gap-1" ws-nowrap>
42-
<DisplayModuleId
43-
v-for="module of chunk.modules"
44-
:id="module"
45-
:key="module"
46-
:session
47-
:link="true"
48-
:minimal="true"
49-
hover="bg-active"
50-
border="~ base rounded" px2 py1 w-full
51-
/>
52-
</div>
53-
</div>
25+
<DataChunkDetails
26+
border="~ base rounded-lg"
27+
p3
28+
:chunk="chunk"
29+
:session="session"
30+
/>
5431
</template>
5532
</div>
5633
</template>

packages/devtools/src/node/rolldown/events-manager.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import type { Event, Module as ModuleInfo } from '@rolldown/debug'
1+
import type { Chunk as ChunkInfo, Event, Module as ModuleInfo } from '@rolldown/debug'
22

33
export type RolldownEvent = Event & {
44
event_id: string
55
}
66

77
export class RolldownEventsManager {
88
events: RolldownEvent[] = []
9+
chunks: Map<number, ChunkInfo> = new Map()
910
modules: Map<string, ModuleInfo> = new Map()
1011
source_refs: Map<string, string> = new Map()
1112

@@ -32,6 +33,13 @@ export class RolldownEventsManager {
3233
return
3334
}
3435

36+
if (event.action === 'ChunkGraphReady') {
37+
for (const chunk of event.chunks) {
38+
this.chunks.set(chunk.chunk_id, chunk)
39+
}
40+
return
41+
}
42+
3543
this.interpretSourceRefs(event, 'source')
3644
this.interpretSourceRefs(event, 'content')
3745

packages/devtools/src/node/rpc/functions/rolldown-get-chunks-graph.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ export const rolldownGetChunksGraph = defineRpcFunction({
77
return {
88
handler: async ({ session }: { session: string }) => {
99
const reader = await manager.loadSession(session)
10-
const graph = reader.manager.events.find(x => x.action === 'ChunkGraphReady')
11-
return graph?.chunks
10+
return Array.from(reader.manager.chunks.values())
1211
},
1312
}
1413
},

packages/devtools/src/node/rpc/functions/rolldown-get-module-info.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ export const rolldownGetModuleInfo = defineRpcFunction({
8282
info.resolve_ids.push(data)
8383
})
8484

85+
info.chunks = Array.from(reader.manager.chunks.values())
86+
.filter(chunk => chunk.modules.includes(module))
87+
.map(chunk => ({
88+
type: 'chunk',
89+
...chunk,
90+
}))
8591
info.loads.sort((a, b) => a.plugin_id - b.plugin_id)
8692
info.resolve_ids.sort((a, b) => a.plugin_id - b.plugin_id)
8793

packages/devtools/src/shared/types/data.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { HookResolveIdCallStart, ModuleImport, SessionMeta } from '@rolldown/debug'
1+
import type { Chunk as ChunkInfo, HookResolveIdCallStart, ModuleImport, SessionMeta } from '@rolldown/debug'
22

33
export type { ModuleImport }
44

@@ -20,17 +20,11 @@ export interface ModuleInfo {
2020
loads: RolldownModuleLoadInfo[]
2121
transforms: RolldownModuleTransformInfo[]
2222
resolve_ids: RolldownResolveInfo[]
23-
chunks: RolldownModuleChunkInfo[]
23+
chunks: RolldownChunkInfo[]
2424
imports: ModuleImport[] | null
2525
importers: string[] | null
2626
}
2727

28-
export interface RolldownModuleChunkInfo {
29-
type: 'chunk'
30-
id: string
31-
plugin_name: string
32-
}
33-
3428
export interface RolldownResolveInfo {
3529
type: 'resolve'
3630
id: string
@@ -84,6 +78,10 @@ export interface RolldownModuleNoChangesHide {
8478
duration: number
8579
}
8680

81+
export interface RolldownChunkInfo extends ChunkInfo {
82+
type: 'chunk'
83+
}
84+
8785
export type RolldownModuleFlowNode
8886
= | RolldownResolveInfo
8987
| RolldownModuleLoadInfo

0 commit comments

Comments
 (0)