Skip to content

Commit 4babe3e

Browse files
committed
fix(build): improve static path generation performance and fix parameter collisions
- Replace O(n²) parameter deduplication with O(n) Map-based approach - Fix parameter value collisions by adding type prefixes (A: for arrays, S: for strings, U: for undefined) - Rewrite assignErrorIfEmpty to use Trie data structure for efficient route analysis - Add comprehensive test coverage for edge cases including collisions and empty inputs - Sort route parameter keys for consistent Map iteration order
1 parent e2422f4 commit 4babe3e

File tree

2 files changed

+291
-86
lines changed

2 files changed

+291
-86
lines changed

packages/next/src/build/static-paths/app.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,58 @@ describe('assignErrorIfEmpty', () => {
110110
expect(prerenderedRoutes[3].throwOnEmptyStaticShell).toBe(true)
111111
expect(prerenderedRoutes[4].throwOnEmptyStaticShell).toBe(false)
112112
})
113+
114+
it('should handle parameter value collisions', () => {
115+
const params = [{ slug: ['foo', 'bar'] }, { slug: 'foo,bar' }]
116+
117+
const unique = filterUniqueRootParamsCombinations(['slug'], params)
118+
119+
expect(unique).toEqual([{ slug: ['foo', 'bar'] }, { slug: 'foo,bar' }])
120+
})
121+
122+
it('should handle multiple routes at the same trie node', () => {
123+
const prerenderedRoutes: PrerenderedRoute[] = [
124+
{
125+
params: { id: '1' },
126+
pathname: '/1/[name]',
127+
encodedPathname: '/1/[name]',
128+
fallbackRouteParams: ['name'],
129+
fallbackMode: FallbackMode.NOT_FOUND,
130+
fallbackRootParams: [],
131+
throwOnEmptyStaticShell: true,
132+
},
133+
{
134+
params: { id: '1' },
135+
pathname: '/1/[name]/[extra]',
136+
encodedPathname: '/1/[name]/[extra]',
137+
fallbackRouteParams: ['name', 'extra'],
138+
fallbackMode: FallbackMode.NOT_FOUND,
139+
fallbackRootParams: [],
140+
throwOnEmptyStaticShell: true,
141+
},
142+
{
143+
params: { id: '1', name: 'test' },
144+
pathname: '/1/test',
145+
encodedPathname: '/1/test',
146+
fallbackRouteParams: [],
147+
fallbackMode: FallbackMode.NOT_FOUND,
148+
fallbackRootParams: [],
149+
throwOnEmptyStaticShell: true,
150+
},
151+
]
152+
153+
assignErrorIfEmpty(prerenderedRoutes, ['id', 'name', 'extra'])
154+
155+
expect(prerenderedRoutes[0].throwOnEmptyStaticShell).toBe(false)
156+
expect(prerenderedRoutes[1].throwOnEmptyStaticShell).toBe(false)
157+
expect(prerenderedRoutes[2].throwOnEmptyStaticShell).toBe(true)
158+
})
159+
160+
it('should handle empty input', () => {
161+
const prerenderedRoutes: PrerenderedRoute[] = []
162+
assignErrorIfEmpty(prerenderedRoutes, [])
163+
expect(prerenderedRoutes).toEqual([])
164+
})
113165
})
114166

115167
describe('filterUniqueParams', () => {
@@ -154,4 +206,23 @@ describe('filterUniqueRootParamsCombinations', () => {
154206

155207
expect(unique).toEqual([{ id: '1' }, { id: '2' }])
156208
})
209+
210+
it('should handle multiple root parameters', () => {
211+
const params = [
212+
{ lang: 'en', region: 'US', page: 'home' },
213+
{ lang: 'en', region: 'US', page: 'about' },
214+
{ lang: 'fr', region: 'CA', page: 'home' },
215+
{ lang: 'fr', region: 'CA', page: 'about' },
216+
]
217+
218+
const unique = filterUniqueRootParamsCombinations(
219+
['lang', 'region'],
220+
params
221+
)
222+
223+
expect(unique).toEqual([
224+
{ lang: 'en', region: 'US' },
225+
{ lang: 'fr', region: 'CA' },
226+
])
227+
})
157228
})

0 commit comments

Comments
 (0)