From 634ff0289033e784fd69124818f752a3e4e3246c Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Thu, 16 Jul 2026 14:14:47 -0700 Subject: [PATCH 1/2] prefetch VPC and Subnets so instance networking tab loads without skeleton cells --- app/pages/project/instances/NetworkingTab.tsx | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/app/pages/project/instances/NetworkingTab.tsx b/app/pages/project/instances/NetworkingTab.tsx index c8856b7fb..81ae0b065 100644 --- a/app/pages/project/instances/NetworkingTab.tsx +++ b/app/pages/project/instances/NetworkingTab.tsx @@ -128,12 +128,29 @@ const staticSubnetCols = [ export async function clientLoader({ params }: LoaderFunctionArgs) { const { project, instance } = getInstanceSelector(params) await Promise.all([ - queryClient.fetchQuery( - q(api.instanceNetworkInterfaceList, { - // we want this to cover all NICs; TODO: determine actual limit? - query: { project, instance, limit: ALL_ISH }, - }) - ), + // Prefetch the by-ID VPC and subnet views the NIC table cells look up, so + // VpcNameFromId/SubnetNameFromId hit a warm cache instead of popping in + // after the table paints. IDs come from the NIC list, so chain off it; NICs + // usually share a VPC/subnet, so dedupe (≤8 NICs, typically 1 of each). + queryClient + .fetchQuery( + q(api.instanceNetworkInterfaceList, { + // we want this to cover all NICs; TODO: determine actual limit? + query: { project, instance, limit: ALL_ISH }, + }) + ) + .then((nics) => { + const vpcIds = [...new Set(nics.items.map((n) => n.vpcId))] + const subnetIds = [...new Set(nics.items.map((n) => n.subnetId))] + return Promise.all([ + ...vpcIds.map((vpc) => + queryClient.prefetchQuery(q(api.vpcView, { path: { vpc } })) + ), + ...subnetIds.map((subnet) => + queryClient.prefetchQuery(q(api.vpcSubnetView, { path: { subnet } })) + ), + ]) + }), queryClient.fetchQuery(q(api.floatingIpList, { query: { project, limit: ALL_ISH } })), queryClient.fetchQuery( q(api.externalSubnetList, { query: { project, limit: ALL_ISH } }) From 283ea6fff87bdae7916e6b58c452fd243dedacff Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Thu, 16 Jul 2026 14:52:30 -0700 Subject: [PATCH 2/2] Small refactor based on other VPC fetching needs --- app/pages/project/instances/NetworkingTab.tsx | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/app/pages/project/instances/NetworkingTab.tsx b/app/pages/project/instances/NetworkingTab.tsx index 81ae0b065..9f651adc4 100644 --- a/app/pages/project/instances/NetworkingTab.tsx +++ b/app/pages/project/instances/NetworkingTab.tsx @@ -128,10 +128,10 @@ const staticSubnetCols = [ export async function clientLoader({ params }: LoaderFunctionArgs) { const { project, instance } = getInstanceSelector(params) await Promise.all([ - // Prefetch the by-ID VPC and subnet views the NIC table cells look up, so - // VpcNameFromId/SubnetNameFromId hit a warm cache instead of popping in - // after the table paints. IDs come from the NIC list, so chain off it; NICs - // usually share a VPC/subnet, so dedupe (≤8 NICs, typically 1 of each). + // Prefetch the by-ID subnet views the NIC table's subnet cells look up, so + // SubnetNameFromId hits a warm cache. subnetIds come from the NIC list, so + // chain off it; NICs usually share a subnet, so dedupe (≤8 NICs, typically 1). + // VPC cells are handled by seeding vpcView from the vpcList fetch below. queryClient .fetchQuery( q(api.instanceNetworkInterfaceList, { @@ -140,16 +140,12 @@ export async function clientLoader({ params }: LoaderFunctionArgs) { }) ) .then((nics) => { - const vpcIds = [...new Set(nics.items.map((n) => n.vpcId))] const subnetIds = [...new Set(nics.items.map((n) => n.subnetId))] - return Promise.all([ - ...vpcIds.map((vpc) => - queryClient.prefetchQuery(q(api.vpcView, { path: { vpc } })) - ), - ...subnetIds.map((subnet) => + return Promise.all( + subnetIds.map((subnet) => queryClient.prefetchQuery(q(api.vpcSubnetView, { path: { subnet } })) - ), - ]) + ) + ) }), queryClient.fetchQuery(q(api.floatingIpList, { query: { project, limit: ALL_ISH } })), queryClient.fetchQuery( @@ -189,8 +185,15 @@ export async function clientLoader({ params }: LoaderFunctionArgs) { queryClient.setQueryData(queryKey, { type: 'success', data: pool }) } }), - // Fetch VPCs for Add NIC form - queryClient.fetchQuery(q(api.vpcList, { query: { project, limit: ALL_ISH } })), + // Fetch VPCs for the Add NIC form, and seed vpcView-by-id so the NIC + // table's VPC cells (VpcNameFromId) render without a skeleton. + queryClient + .fetchQuery(q(api.vpcList, { query: { project, limit: ALL_ISH } })) + .then((vpcs) => { + for (const vpc of vpcs.items) { + queryClient.setQueryData(q(api.vpcView, { path: { vpc: vpc.id } }).queryKey, vpc) + } + }), ]) return null }