From 65cf5573bb00adcd431987c7a8a71830ec292ac0 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Mon, 22 Jun 2026 21:54:37 +0000 Subject: [PATCH 1/2] fix: preserve route topology order --- src/route-watch.ts | 27 ++++++++++++++------------- tests/route-watch.test.ts | 34 +++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/route-watch.ts b/src/route-watch.ts index e726fec..29a49fe 100644 --- a/src/route-watch.ts +++ b/src/route-watch.ts @@ -61,19 +61,20 @@ export const createRouteManifestSnapshot = ( routes: Record ): Set => new Set( - Object.entries(routes) - .sort(([left], [right]) => left.localeCompare(right)) - .map(([routeId, route]) => - JSON.stringify([ - routeId, - route.id, - route.parentId ?? null, - route.path ?? null, - route.index ?? null, - route.caseSensitive ?? null, - route.file, - ]) - ) + // React Router uses sibling declaration order as a match tiebreaker, so the + // snapshot must preserve route-manifest insertion order. + Object.entries(routes).map(([routeId, route], order) => + JSON.stringify([ + order, + routeId, + route.id, + route.parentId ?? null, + route.path ?? null, + route.index ?? null, + route.caseSensitive ?? null, + route.file, + ]) + ) ); export const ensureDevRestartMarker = async ( diff --git a/tests/route-watch.test.ts b/tests/route-watch.test.ts index a9740e4..2315c76 100644 --- a/tests/route-watch.test.ts +++ b/tests/route-watch.test.ts @@ -170,27 +170,39 @@ describe('route watch topology snapshot', () => { ); }); - it('is stable for equivalent route manifests with different object insertion order', () => { + it('changes when sibling declaration order changes', () => { const first = createRouteManifestSnapshot({ root: { id: 'root', path: '', file: 'root.tsx' }, - 'routes/demo': { - id: 'routes/demo', + 'routes/a': { + id: 'routes/a', parentId: 'root', - path: 'demo', - file: 'routes/demo.tsx', + path: ':value', + file: 'routes/a.tsx', + }, + 'routes/b': { + id: 'routes/b', + parentId: 'root', + path: ':value', + file: 'routes/b.tsx', }, }); const second = createRouteManifestSnapshot({ - 'routes/demo': { - id: 'routes/demo', + root: { id: 'root', path: '', file: 'root.tsx' }, + 'routes/b': { + id: 'routes/b', parentId: 'root', - path: 'demo', - file: 'routes/demo.tsx', + path: ':value', + file: 'routes/b.tsx', + }, + 'routes/a': { + id: 'routes/a', + parentId: 'root', + path: ':value', + file: 'routes/a.tsx', }, - root: { id: 'root', path: '', file: 'root.tsx' }, }); - expect(second).toEqual(first); + expect(second).not.toEqual(first); }); }); From 0f5a76e403fddc4e533c4085b11d048e660a50f8 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:17:00 +0000 Subject: [PATCH 2/2] chore: add route topology order changeset --- .changeset/quiet-topology-order.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/quiet-topology-order.md diff --git a/.changeset/quiet-topology-order.md b/.changeset/quiet-topology-order.md new file mode 100644 index 0000000..e0ec1c9 --- /dev/null +++ b/.changeset/quiet-topology-order.md @@ -0,0 +1,6 @@ +--- +"rsbuild-plugin-react-router": patch +--- + +Preserve route topology declaration order during development so reordering route +entries is detected as a topology change.