Skip to content

Commit e2374b0

Browse files
committed
chore: update
1 parent 40cc30f commit e2374b0

File tree

4 files changed

+352
-318
lines changed

4 files changed

+352
-318
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<script setup lang="ts">
2+
import type { Chunk, ChunkImport } from '@rolldown/debug'
3+
import type { SessionContext } from '~~/shared/types/data'
4+
import type { ModuleGraphLink, ModuleGraphNode } from '~/composables/moduleGraph'
5+
import { computed, nextTick, unref } from 'vue'
6+
import { createModuleGraph } from '~/composables/moduleGraph'
7+
8+
const props = defineProps<{
9+
session: SessionContext
10+
chunks: ChunkInfo[]
11+
}>()
12+
13+
const chunks = computed(() => props.chunks)
14+
15+
type ChunkInfo = Chunk & {
16+
id: string
17+
}
18+
createModuleGraph<ChunkInfo, ChunkImport>({
19+
modules: chunks,
20+
spacing: {
21+
width: 320,
22+
height: 55,
23+
linkOffset: 15,
24+
margin: 120,
25+
gap: 80,
26+
},
27+
generateGraph: (options) => {
28+
const { isFirstCalculateGraph, scale, spacing, tree, hierarchy, collapsedNodes, container, modulesMap, nodes, links, nodesMap, linksMap, width, height, childToParentMap } = options
29+
return () => {
30+
width.value = window.innerWidth
31+
height.value = window.innerHeight
32+
33+
const root = hierarchy<ModuleGraphNode<ChunkInfo, ChunkImport> & { end?: boolean }>(
34+
{ module: { id: '~root' } } as any,
35+
(parent) => {
36+
if (`${parent.module?.id}` === '~root') {
37+
chunks.value.forEach((x) => {
38+
if (isFirstCalculateGraph.value) {
39+
childToParentMap.set(x.id, '~root')
40+
}
41+
})
42+
return chunks.value.map(x => ({
43+
module: x,
44+
expanded: !collapsedNodes.has(x.id),
45+
hasChildren: false,
46+
}))
47+
}
48+
49+
if (collapsedNodes.has(`${parent.module?.id}`) || parent.end) {
50+
return []
51+
}
52+
53+
const nodes = parent.module.imports
54+
.map((x): ModuleGraphNode<ChunkInfo, ChunkImport> & { end: boolean } | undefined => {
55+
const module = modulesMap.value.get(`${x.chunk_id}`)
56+
if (!module)
57+
return undefined
58+
59+
if (isFirstCalculateGraph.value) {
60+
childToParentMap.set(module.id, parent.module.id)
61+
}
62+
63+
return {
64+
module,
65+
import: x,
66+
expanded: !collapsedNodes.has(module.id),
67+
hasChildren: false,
68+
end: true,
69+
}
70+
})
71+
.filter(x => x !== undefined)
72+
73+
return nodes
74+
},
75+
)
76+
77+
if (isFirstCalculateGraph.value) {
78+
isFirstCalculateGraph.value = false
79+
}
80+
81+
// Calculate the layout
82+
const layout = tree<ModuleGraphNode<ChunkInfo, ChunkImport> & { end?: boolean }>()
83+
.nodeSize([unref(spacing.height), unref(spacing.width) + unref(spacing.gap)])
84+
layout(root)
85+
86+
const _nodes = root.descendants()
87+
88+
for (const node of _nodes) {
89+
// Rotate the graph from top-down to left-right
90+
[node.x, node.y] = [node.y! - unref(spacing.width), node.x!]
91+
92+
if (node.data.module.imports) {
93+
node.data.hasChildren = node.data.module.imports.length > 0 && !node.data.end
94+
}
95+
}
96+
97+
// Offset the graph and adding margin
98+
const minX = Math.min(..._nodes.map(n => n.x!))
99+
const minY = Math.min(..._nodes.map(n => n.y!))
100+
if (minX < unref(spacing.margin)) {
101+
for (const node of _nodes) {
102+
node.x! += Math.abs(minX) + unref(spacing.margin)
103+
}
104+
}
105+
if (minY < unref(spacing.margin)) {
106+
for (const node of _nodes) {
107+
node.y! += Math.abs(minY) + unref(spacing.margin)
108+
}
109+
}
110+
111+
nodes.value = _nodes
112+
nodesMap.clear()
113+
for (const node of _nodes) {
114+
nodesMap.set(`${node.data.module.id}`, node)
115+
}
116+
const _links = root.links()
117+
.filter(x => `${x.source.data.module.id}` !== '~root')
118+
.map((x): ModuleGraphLink<ChunkInfo, ChunkImport> => {
119+
return {
120+
...x,
121+
import: x.source.data.import,
122+
id: `${x.source.data.module.id}|${x.target.data.module.id}`,
123+
}
124+
})
125+
linksMap.clear()
126+
for (const link of _links) {
127+
linksMap.set(link.id, link)
128+
}
129+
links.value = _links
130+
131+
nextTick(() => {
132+
width.value = (container.value!.scrollWidth / scale.value + unref(spacing.margin))
133+
height.value = (container.value!.scrollHeight / scale.value + unref(spacing.margin))
134+
})
135+
}
136+
},
137+
})
138+
</script>
139+
140+
<template>
141+
<DisplayModuleGraph
142+
:session="session"
143+
:modules="chunks"
144+
>
145+
<template #default="{ node }">
146+
<div flex="~ items-center">
147+
<span op50 font-mono w12>#{{ node.data.module.id }}</span>
148+
<div flex="~ gap-2 items-center" :title="`Chunk #${node.data.module.id}`">
149+
<div i-ph-shapes-duotone />
150+
<div>{{ node.data.module.name || '[unnamed]' }}</div>
151+
<DisplayBadge :text="node.data.module.reason" />
152+
</div>
153+
<div flex-auto />
154+
<div flex="~ gap-1 items-center">
155+
<div i-ph-package-duotone />
156+
{{ node.data.module.modules.length }}
157+
</div>
158+
</div>
159+
</template>
160+
</DisplayModuleGraph>
161+
</template>
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<script setup lang="ts">
2+
import type { ModuleImport, ModuleListItem, SessionContext } from '~~/shared/types'
3+
import type { ModuleGraphLink, ModuleGraphNode } from '~/composables/moduleGraph'
4+
import { computed, nextTick, unref } from 'vue'
5+
import { createModuleGraph } from '~/composables/moduleGraph'
6+
7+
const props = defineProps<{
8+
modules: ModuleListItem[]
9+
session: SessionContext
10+
}>()
11+
12+
const modules = computed(() => props.modules)
13+
14+
createModuleGraph<ModuleListItem, ModuleImport>({
15+
modules,
16+
spacing: {
17+
width: 400,
18+
height: 55,
19+
linkOffset: 20,
20+
margin: 800,
21+
gap: 150,
22+
},
23+
generateGraph: (options) => {
24+
const { isFirstCalculateGraph, scale, spacing, tree, hierarchy, collapsedNodes, container, modulesMap, nodes, links, nodesMap, linksMap, width, height, childToParentMap, focusOn } = options
25+
const rootModules = computed(() => {
26+
return modules.value.filter(x => x.importers.length === 0)
27+
})
28+
29+
return (focusOnFirstRootNode = true) => {
30+
width.value = window.innerWidth
31+
height.value = window.innerHeight
32+
33+
const seen = new Set<ModuleListItem>()
34+
const root = hierarchy<ModuleGraphNode<ModuleListItem, ModuleImport>>(
35+
{ module: { id: '~root' } } as any,
36+
(parent) => {
37+
if (parent.module.id === '~root') {
38+
rootModules.value.forEach((x) => {
39+
seen.add(x)
40+
41+
if (isFirstCalculateGraph.value) {
42+
childToParentMap.set(x.id, '~root')
43+
}
44+
})
45+
return rootModules.value.map(x => ({
46+
module: x,
47+
expanded: !collapsedNodes.has(x.id),
48+
hasChildren: false,
49+
}))
50+
}
51+
52+
if (collapsedNodes.has(parent.module.id)) {
53+
return []
54+
}
55+
56+
const modules = parent.module.imports
57+
.map((x): ModuleGraphNode<ModuleListItem, ModuleImport> | undefined => {
58+
const module = modulesMap.value.get(x.module_id)
59+
if (!module)
60+
return undefined
61+
if (seen.has(module))
62+
return undefined
63+
64+
// Check if the module is a child of the current parent
65+
if (childToParentMap.has(module.id) && childToParentMap.get(module.id) !== parent.module.id)
66+
return undefined
67+
68+
seen.add(module)
69+
70+
if (isFirstCalculateGraph.value) {
71+
childToParentMap.set(module.id, parent.module.id)
72+
}
73+
74+
return {
75+
module,
76+
import: x,
77+
expanded: !collapsedNodes.has(module.id),
78+
hasChildren: false,
79+
}
80+
})
81+
.filter(x => x !== undefined)
82+
83+
return modules
84+
},
85+
)
86+
87+
if (isFirstCalculateGraph.value) {
88+
isFirstCalculateGraph.value = false
89+
}
90+
91+
// Calculate the layout
92+
const layout = tree<ModuleGraphNode<ModuleListItem, ModuleImport>>()
93+
.nodeSize([unref(spacing.height), unref(spacing.width) + unref(spacing.gap)])
94+
layout(root)
95+
96+
const _nodes = root.descendants()
97+
98+
for (const node of _nodes) {
99+
// Rotate the graph from top-down to left-right
100+
[node.x, node.y] = [node.y! - unref(spacing.width), node.x!]
101+
102+
if (node.data.module.imports) {
103+
node.data.hasChildren = node.data.module.imports
104+
?.filter(subNode => childToParentMap.get(subNode.module_id) === node.data.module.id)
105+
.length > 0
106+
}
107+
}
108+
109+
// Offset the graph and adding margin
110+
const minX = Math.min(..._nodes.map(n => n.x!))
111+
const minY = Math.min(..._nodes.map(n => n.y!))
112+
if (minX < unref(spacing.margin)) {
113+
for (const node of _nodes) {
114+
node.x! += Math.abs(minX) + unref(spacing.margin)
115+
}
116+
}
117+
if (minY < unref(spacing.margin)) {
118+
for (const node of _nodes) {
119+
node.y! += Math.abs(minY) + unref(spacing.margin)
120+
}
121+
}
122+
123+
nodes.value = _nodes
124+
nodesMap.clear()
125+
for (const node of _nodes) {
126+
nodesMap.set(node.data.module.id, node)
127+
}
128+
const _links = root.links()
129+
.filter(x => x.source.data.module.id !== '~root')
130+
.map((x): ModuleGraphLink<ModuleListItem, ModuleImport> => {
131+
return {
132+
...x,
133+
import: x.source.data.import,
134+
id: `${x.source.data.module.id}|${x.target.data.module.id}`,
135+
}
136+
})
137+
138+
linksMap.clear()
139+
for (const link of _links) {
140+
linksMap.set(link.id, link)
141+
}
142+
links.value = _links
143+
144+
nextTick(() => {
145+
width.value = (container.value!.scrollWidth / scale.value + unref(spacing.margin))
146+
height.value = (container.value!.scrollHeight / scale.value + unref(spacing.margin))
147+
const moduleId = rootModules.value?.[0]?.id
148+
if (focusOnFirstRootNode && moduleId) {
149+
nextTick(() => {
150+
focusOn(moduleId, false)
151+
})
152+
}
153+
})
154+
}
155+
},
156+
})
157+
</script>
158+
159+
<template>
160+
<DisplayModuleGraph
161+
:session="session"
162+
:modules="modules"
163+
>
164+
<template #default="{ node, nodesRefMap }">
165+
<DisplayModuleId
166+
:id="node.data.module.id"
167+
:ref="(el: any) => nodesRefMap.set(node.data.module.id, el?.$el)"
168+
:link="true"
169+
:session="session"
170+
:minimal="true"
171+
flex="1"
172+
/>
173+
</template>
174+
<template #link="{ link, d, linkClass }">
175+
<path
176+
:d="d"
177+
:class="linkClass"
178+
:stroke-dasharray="link.import?.kind === 'dynamic-import' ? '3 6' : undefined"
179+
fill="none"
180+
/>
181+
</template>
182+
</DisplayModuleGraph>
183+
</template>

0 commit comments

Comments
 (0)