From 50cf61b80514ed969c0f5467930bc5394500e7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez?= Date: Sun, 12 Jan 2025 18:41:54 +0100 Subject: [PATCH] feat(ui): allow hide/show node_modules in module graph tab (#7217) --- packages/ui/client/components/FileDetails.vue | 47 ++++++++++++++----- .../components/views/ViewModuleGraph.vue | 39 +++++++++++++-- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/packages/ui/client/components/FileDetails.vue b/packages/ui/client/components/FileDetails.vue index f1c841224b66..6b23e147bd97 100644 --- a/packages/ui/client/components/FileDetails.vue +++ b/packages/ui/client/components/FileDetails.vue @@ -2,6 +2,7 @@ import type { ModuleGraph } from '~/composables/module-graph' import type { Params } from '~/composables/params' import { hasFailedSnapshot } from '@vitest/ws-client' +import { toJSON } from 'flatted' import { browserState, client, @@ -18,6 +19,7 @@ const draft = ref(false) const hasGraphBeenDisplayed = ref(false) const loadingModuleGraph = ref(false) const currentFilepath = ref(undefined) +const hideNodeModules = ref(true) const graphData = computed(() => { const c = current.value @@ -61,10 +63,12 @@ function onDraft(value: boolean) { draft.value = value } -async function loadModuleGraph() { +const nodeModuleRegex = /[/\\]node_modules[/\\]/ + +async function loadModuleGraph(force = false) { if ( loadingModuleGraph.value - || graphData.value?.filepath === currentFilepath.value + || (graphData.value?.filepath === currentFilepath.value && !force) ) { return } @@ -76,20 +80,39 @@ async function loadModuleGraph() { try { const gd = graphData.value if (!gd) { + loadingModuleGraph.value = false return } if ( - !currentFilepath.value + force + || !currentFilepath.value || gd.filepath !== currentFilepath.value || (!graph.value.nodes.length && !graph.value.links.length) ) { + let moduleGraph = await client.rpc.getModuleGraph( + gd.projectName, + gd.filepath, + !!browserState, + ) + // remove node_modules from the graph when enabled + if (hideNodeModules.value) { + // when using static html reporter, we've the meta as global, we need to clone it + if (isReport) { + moduleGraph + = typeof window.structuredClone !== 'undefined' + ? window.structuredClone(moduleGraph) + : toJSON(moduleGraph) + } + moduleGraph.inlined = moduleGraph.inlined.filter( + n => !nodeModuleRegex.test(n), + ) + moduleGraph.externalized = moduleGraph.externalized.filter( + n => !nodeModuleRegex.test(n), + ) + } graph.value = getModuleGraph( - await client.rpc.getModuleGraph( - gd.projectName, - gd.filepath, - !!browserState, - ), + moduleGraph, gd.filepath, ) currentFilepath.value = gd.filepath @@ -103,10 +126,11 @@ async function loadModuleGraph() { } debouncedWatch( - () => [graphData.value, viewMode.value] as const, - ([, vm]) => { + () => [graphData.value, viewMode.value, hideNodeModules.value] as const, + ([, vm, hide], old) => { if (vm === 'graph') { - loadModuleGraph() + // only force reload when hide is changed + loadModuleGraph(old && hide !== old[2]) } }, { debounce: 100, immediate: true }, @@ -221,6 +245,7 @@ const projectNameTextColor = computed(() => {
() +const hideNodeModules = defineModel({ required: true }) + const { graph } = toRefs(props) const el = ref() @@ -46,7 +48,7 @@ onUnmounted(() => { controller.value?.shutdown() }) -watch(graph, resetGraphController) +watch(graph, () => resetGraphController()) function setFilter(name: ModuleType, value: boolean) { controller.value?.filterNodesByType(value, name) @@ -57,8 +59,16 @@ function setSelectedModule(id: string) { modalShow.value = true } -function resetGraphController() { +function resetGraphController(reset = false) { controller.value?.shutdown() + + // Force reload the module graph only when node_modules are shown. + // The module graph doesn't contain node_modules entries. + if (reset && !hideNodeModules.value) { + hideNodeModules.value = true + return + } + if (!graph.value || !el.value) { return } @@ -154,6 +164,28 @@ function bindOnClick(
+
+ + +