Skip to content

Commit 60a198e

Browse files
authored
fix(nextjs): use LRU map instead of map for ISR route cache (#18234)
Make use of our existing `LRUMap` for the ISR route cache to avoid the map growing too big.
1 parent 1679d80 commit 60a198e

File tree

2 files changed

+16
-14
lines changed

2 files changed

+16
-14
lines changed

packages/nextjs/src/client/routing/isrRoutingTracing.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { LRUMap } from '@sentry/core';
12
import { WINDOW } from '@sentry/react';
23
import { getManifest, maybeParameterizeRoute } from './parameterization';
34

45
/**
56
* Cache for ISR/SSG route checks. Exported for testing purposes.
67
* @internal
78
*/
8-
export const IS_ISR_SSG_ROUTE_CACHE = new Map<string, boolean>();
9+
export const IS_ISR_SSG_ROUTE_CACHE = new LRUMap<string, boolean>(100);
910

1011
/**
1112
* Check if the current page is an ISR/SSG route by checking the route manifest.
@@ -17,8 +18,9 @@ export function isIsrSsgRoute(pathname: string): boolean {
1718
const pathToCheck = parameterizedPath || pathname;
1819

1920
// Check cache using the parameterized path as the key
20-
if (IS_ISR_SSG_ROUTE_CACHE.has(pathToCheck)) {
21-
return IS_ISR_SSG_ROUTE_CACHE.get(pathToCheck) as boolean;
21+
const cachedResult = IS_ISR_SSG_ROUTE_CACHE.get(pathToCheck);
22+
if (cachedResult !== undefined) {
23+
return cachedResult;
2224
}
2325

2426
// Cache miss get the manifest

packages/nextjs/test/client/isrRoutingTracing.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,14 @@ describe('isrRoutingTracing', () => {
301301
const result1 = isIsrSsgRoute('/products/123');
302302
expect(result1).toBe(true);
303303
expect(IS_ISR_SSG_ROUTE_CACHE.size).toBe(1);
304-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/products/:id')).toBe(true);
304+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/products/:id')).toBeDefined();
305305

306306
// Second call with different concrete path /products/456
307307
const result2 = isIsrSsgRoute('/products/456');
308308
expect(result2).toBe(true);
309309
// Cache size should still be 1 - both paths map to same parameterized route
310310
expect(IS_ISR_SSG_ROUTE_CACHE.size).toBe(1);
311-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/products/:id')).toBe(true);
311+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/products/:id')).toBeDefined();
312312

313313
// Third call with yet another path /products/999
314314
const result3 = isIsrSsgRoute('/products/999');
@@ -324,7 +324,7 @@ describe('isrRoutingTracing', () => {
324324
// First call - cache miss, will populate cache
325325
isIsrSsgRoute('/products/1');
326326
expect(IS_ISR_SSG_ROUTE_CACHE.size).toBe(1);
327-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/products/:id')).toBe(true);
327+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/products/:id')).toBeDefined();
328328

329329
// Second call with different concrete path - cache hit
330330
const result2 = isIsrSsgRoute('/products/2');
@@ -341,7 +341,7 @@ describe('isrRoutingTracing', () => {
341341
it('should cache false results for non-ISR routes', () => {
342342
const result1 = isIsrSsgRoute('/not-an-isr-route');
343343
expect(result1).toBe(false);
344-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/not-an-isr-route')).toBe(true);
344+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/not-an-isr-route')).toBeDefined();
345345
expect(IS_ISR_SSG_ROUTE_CACHE.get('/not-an-isr-route')).toBe(false);
346346

347347
// Second call should use cache
@@ -355,14 +355,14 @@ describe('isrRoutingTracing', () => {
355355

356356
const result = isIsrSsgRoute('/any-route');
357357
expect(result).toBe(false);
358-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/any-route')).toBe(true);
358+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/any-route')).toBeDefined();
359359
expect(IS_ISR_SSG_ROUTE_CACHE.get('/any-route')).toBe(false);
360360
});
361361

362362
it('should cache static routes without parameterization', () => {
363363
const result1 = isIsrSsgRoute('/blog');
364364
expect(result1).toBe(true);
365-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/blog')).toBe(true);
365+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/blog')).toBeDefined();
366366

367367
// Second call should use cache
368368
const result2 = isIsrSsgRoute('/blog');
@@ -378,10 +378,10 @@ describe('isrRoutingTracing', () => {
378378

379379
// Should have 4 cache entries (one for each unique route pattern)
380380
expect(IS_ISR_SSG_ROUTE_CACHE.size).toBe(4);
381-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/products/:id')).toBe(true);
382-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/posts/:slug')).toBe(true);
383-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/blog')).toBe(true);
384-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/')).toBe(true);
381+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/products/:id')).toBeDefined();
382+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/posts/:slug')).toBeDefined();
383+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/blog')).toBeDefined();
384+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/')).toBeDefined();
385385
});
386386

387387
it('should efficiently handle multiple calls to same dynamic route with different params', () => {
@@ -392,7 +392,7 @@ describe('isrRoutingTracing', () => {
392392

393393
// Should only have 1 cache entry despite 100 calls
394394
expect(IS_ISR_SSG_ROUTE_CACHE.size).toBe(1);
395-
expect(IS_ISR_SSG_ROUTE_CACHE.has('/products/:id')).toBe(true);
395+
expect(IS_ISR_SSG_ROUTE_CACHE.get('/products/:id')).toBeDefined();
396396
});
397397
});
398398
});

0 commit comments

Comments
 (0)