fix(dashboard): stop sidebar RSC prefetch storms (#8292)

* fix(dashboard): disable sidebar route prefetch

Co-Authored-By: Claude <noreply@anthropic.com>

* test(dashboard): cover sidebar prefetch traffic

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Ravi Tharuma
2026-07-23 16:06:59 +02:00
committed by GitHub
parent acd3d46ab4
commit 069d5a7925
3 changed files with 44 additions and 0 deletions

View File

@@ -431,6 +431,7 @@ export default function Sidebar({
<Link
key={item.href}
href={item.href}
prefetch={false}
onClick={onClose}
className={className}
{...sharedProps}
@@ -497,6 +498,7 @@ export default function Sidebar({
<div className={cn("py-3", collapsed ? "px-2" : "px-4")}>
<Link
href="/home"
prefetch={false}
className={cn("flex items-center", collapsed ? "justify-center" : "gap-2.5")}
>
<div className="flex items-center justify-center size-8 rounded bg-linear-to-br from-[#E54D5E] to-[#C93D4E] shrink-0">

View File

@@ -1,4 +1,5 @@
import { test, expect } from "@playwright/test";
import { gotoDashboardRoute } from "./helpers/dashboardAuth";
test.describe("Dashboard Navigation", () => {
test("redirects unauthenticated user to /login", async ({ page }) => {
@@ -10,6 +11,30 @@ test.describe("Dashboard Navigation", () => {
expect(url).toMatch(/\/(login|dashboard)/);
});
test("does not prefetch dashboard routes and preserves client navigation", async ({ page }) => {
const speculativeRequests: string[] = [];
page.on("request", (request) => {
const headers = request.headers();
const isRscPrefetch =
headers.rsc === "1" &&
(headers["next-router-prefetch"] === "1" ||
headers.purpose?.toLowerCase().includes("prefetch") ||
headers["sec-purpose"]?.toLowerCase().includes("prefetch"));
if (isRscPrefetch) speculativeRequests.push(request.url());
});
await gotoDashboardRoute(page, "/home");
await expect(page.getByRole("link", { name: /providers/i }).first()).toBeVisible();
await page.waitForTimeout(500);
expect(speculativeRequests).toEqual([]);
await page.getByRole("link", { name: /providers/i }).first().click();
await expect(page).toHaveURL(/\/dashboard\/providers/);
});
test("login page renders with form elements", async ({ page }) => {
await page.goto("/login");
// Should show some form of authentication UI

View File

@@ -0,0 +1,17 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";
const SIDEBAR = "src/shared/components/Sidebar.tsx";
test("#8281: dashboard navigation opts out of automatic route prefetch", async () => {
const source = await readFile(SIDEBAR, "utf8");
const internalLink = source.match(/<Link\s+[\s\S]*?href=\{item\.href\}[\s\S]*?>/);
assert.ok(internalLink, "expected the sidebar's internal navigation Link");
assert.match(internalLink[0], /prefetch=\{false\}/);
const logoLink = source.match(/<Link\s+href="\/home"[\s\S]*?>/);
assert.ok(logoLink, "expected the sidebar logo home Link");
assert.match(logoLink[0], /prefetch=\{false\}/);
});