diff --git a/.changeset/brown-jars-lick.md b/.changeset/brown-jars-lick.md
new file mode 100644
index 000000000000..0d824e445f47
--- /dev/null
+++ b/.changeset/brown-jars-lick.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes an issue where links with the same pathname as the current page, but different search params, were not prefetched.
diff --git a/packages/astro/e2e/fixtures/prefetch/src/pages/index.astro b/packages/astro/e2e/fixtures/prefetch/src/pages/index.astro
index e61bc1c6c33e..88ce196ae22f 100644
--- a/packages/astro/e2e/fixtures/prefetch/src/pages/index.astro
+++ b/packages/astro/e2e/fixtures/prefetch/src/pages/index.astro
@@ -9,6 +9,8 @@
false
+ search param
+
tap
hover
diff --git a/packages/astro/e2e/prefetch.test.js b/packages/astro/e2e/prefetch.test.js
index dc29bde33f07..a19c87680eca 100644
--- a/packages/astro/e2e/prefetch.test.js
+++ b/packages/astro/e2e/prefetch.test.js
@@ -16,7 +16,8 @@ test.describe('Prefetch (default)', () => {
test.beforeEach(async ({ page }) => {
page.on('request', (req) => {
- reqUrls.push(new URL(req.url()).pathname);
+ const urlObj = new URL(req.url());
+ reqUrls.push(urlObj.pathname + urlObj.search);
});
});
@@ -38,6 +39,16 @@ test.describe('Prefetch (default)', () => {
expect(reqUrls).not.toContainEqual('/prefetch-false');
});
+ test('Link with search param should prefetch', async ({ page, astro }) => {
+ await page.goto(astro.resolveUrl('/'));
+ expect(reqUrls).not.toContainEqual('/?search-param=true');
+ await Promise.all([
+ page.waitForEvent('request'), // wait prefetch request
+ page.locator('#prefetch-search-param').hover(),
+ ]);
+ expect(reqUrls).toContainEqual('/?search-param=true');
+ });
+
test('data-astro-prefetch="tap" should prefetch on tap', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/'));
expect(reqUrls).not.toContainEqual('/prefetch-tap');
@@ -102,7 +113,8 @@ test.describe("Prefetch (prefetchAll: true, defaultStrategy: 'tap')", () => {
test.beforeEach(async ({ page }) => {
page.on('request', (req) => {
- reqUrls.push(new URL(req.url()).pathname);
+ const urlObj = new URL(req.url());
+ reqUrls.push(urlObj.pathname + urlObj.search);
});
});
@@ -129,6 +141,16 @@ test.describe("Prefetch (prefetchAll: true, defaultStrategy: 'tap')", () => {
expect(reqUrls).not.toContainEqual('/prefetch-false');
});
+ test('Link with search param should prefetch', async ({ page, astro }) => {
+ await page.goto(astro.resolveUrl('/'));
+ expect(reqUrls).not.toContainEqual('/?search-param=true');
+ await Promise.all([
+ page.waitForEvent('request'), // wait prefetch request
+ page.locator('#prefetch-search-param').hover(),
+ ]);
+ expect(reqUrls).toContainEqual('/?search-param=true');
+ });
+
test('data-astro-prefetch="tap" should prefetch on tap', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/'));
expect(reqUrls).not.toContainEqual('/prefetch-tap');
diff --git a/packages/astro/src/prefetch/index.ts b/packages/astro/src/prefetch/index.ts
index 573efe5734ef..15f4ef0ccd95 100644
--- a/packages/astro/src/prefetch/index.ts
+++ b/packages/astro/src/prefetch/index.ts
@@ -226,7 +226,7 @@ function canPrefetchUrl(url: string, ignoreSlowConnection: boolean) {
const urlObj = new URL(url, location.href);
return (
location.origin === urlObj.origin &&
- location.pathname !== urlObj.pathname &&
+ (location.pathname !== urlObj.pathname || location.search !== urlObj.search) &&
!prefetchedUrls.has(url)
);
} catch {}