Capítulo 10 de 24

Chapter 10: Large Route Trees

Core Idea

This example stress-tests file-based routing at scale: a Node script (src/createRoutes.mjs) generates 100 copies of absolute routes, relative routes, search-param routes, and dynamic-param routes into src/routes/(gen)/, producing hundreds of route files from four templates. It exists to validate that the router, the Vite plugin, and TypeScript inference hold up on a large generated route tree, not to demonstrate a new routing API.

Setup

  • Routing style: file-based, with a route group (gen) holding generated routes plus a hand-written root
  • Key dependencies: @tanstack/react-router, @tanstack/router-plugin, @tanstack/react-query, zod
  • Structure: src/routes/__root.tsx (root layout), src/routes/absolute.tsx / relative.tsx / search/searchPlaceholder.tsx / params/$paramsPlaceholder.tsx (the four templates), src/createRoutes.mjs (codegen script run via npm run gen), src/routes/(gen)/... (the generated output, not hand-maintained).

Code Example

// src/createRoutes.mjs (codegen driving the large tree)
const length = 100

const main = async () => {
  const search = (await readFile('./src/routes/search/searchPlaceholder.tsx')).toString()
  // ...similar reads for absolute, relative, params templates

  for (let y = 0; y < length; y = y + 1) {
    const replacedSearch = search.replaceAll('searchPlaceholder', `search${y}`)
    await writeFile(`./src/routes/(gen)/search/search${y}.tsx`, replacedSearch)
    // ...writes absolute${y}.tsx, relative${y}.tsx, $param${y}.tsx the same way
  }
}
// src/routes/search/searchPlaceholder.tsx (one of the templates being duplicated)
const search = z.object({
  searchPlaceholder: z.literal('searchPlaceholder'),
  page: z.number(),
  offset: z.number(),
  search: z.string(),
})

export const Route = createFileRoute('/search/searchPlaceholder')({
  component: SearchComponent,
  validateSearch: search,
  loader: (opts) => opts.context.queryClient.ensureQueryData(searchQueryOptions),
})
  • What it demonstrates: string-substitution codegen (replaceAll('searchPlaceholder', 'search${y}')) turns one route template into N distinct routes with unique paths, unique zod-validated search schemas, and unique loaders, all still picked up by the file-based route scanner.

Key Takeaways

  1. File-based routing scales by file count, not by hand-written config; codegen scripts like createRoutes.mjs are a legitimate way to populate or benchmark a large route tree.
  2. Route groups in parentheses, (gen) here, let generated routes live alongside hand-written ones without adding a URL segment or being mistaken for source-of-truth files.
  3. Run npm run gen before dev/build in this example, the generated (gen) folder is not checked in as final source, it is produced from the four templates each time.
  4. If TypeScript or build performance degrades with a large route tree, this example is the reference project for reproducing and profiling that at scale.

Connects To

  • kitchen-sink examples (ch005/ch006, referenced elsewhere in this skill): Also exercise large, varied route trees, but hand-authored to cover many router features at once rather than generated to test scale.
  • ch012-search-validator-adapters: Uses the same validateSearch + zod pattern seen in the search/searchPlaceholder.tsx template, at a much smaller scale.