From 83367aad3829a0298fbc730798aaef8ddf6bccd6 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Tue, 13 Oct 2026 08:29:27 +0200 Subject: [PATCH] fix(tanstackstart-react): Keep parametrized route names in Nitro 3 builds The Vite plugin injects the route patterns into the SDK's own `wrapFetchWithSentry` file at build time. Vite externalizes dependencies in server builds, and current Nitro 3 releases copy external dependencies into `.output/server/node_modules` instead of bundling them. The transform then never sees the SDK file, so route parametrization turned off and server spans were named only after the HTTP method. The plugin now adds `@sentry/tanstackstart-react` to `resolve.noExternal` of the server environments in builds, so the SDK is always bundled. The canary build of the e2e app now also installs the latest Nitro, Vite, React SWC plugin and `vite-tsconfig-paths`. TanStack Start 1.169, the first stable release, needs Vite 8, and the build kept Vite 7.3.2. It also kept `nitro@3.0.0`, the old placeholder release that `latest || *` resolves to, which answers every request with a 500 on 1.169. The `tanstackstart-react-cloudflare` app accepts any TanStack Start 1.x, so it installed 1.169 with Vite 7.3.2 and its build failed too. It now uses Vite 8 with the matching `@vitejs/plugin-react` and `vite-tsconfig-paths`. Co-Authored-By: Claude Opus 5.5 --- .../package.json | 6 ++--- .../tanstackstart-react/package.json | 2 +- .../src/vite/routePatterns.ts | 10 ++++++++ .../test/vite/routePatterns.test.ts | 25 ++++++++++++++++++- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json index 5cf6accf0cd1..688094b3d237 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/package.json @@ -28,10 +28,10 @@ "@sentry-internal/test-utils": "link:../../../test-utils", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^4.5.0", + "@vitejs/plugin-react": "^6.1.2", "typescript": "^5.9.0", - "vite": "7.3.2", - "vite-tsconfig-paths": "^5.1.4", + "vite": "8.3.4", + "vite-tsconfig-paths": "^6.1.1", "wrangler": "^4.68.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json index 89dad11c3985..410f41baecbc 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json @@ -14,7 +14,7 @@ "test:build:tunnel-static": "pnpm install && E2E_TEST_TUNNEL_ROUTE_MODE=static E2E_TEST_DSN=http://public@localhost:3031/1337 pnpm build", "test:build:tunnel-custom": "pnpm install && E2E_TEST_CUSTOM_TUNNEL_ROUTE=1 pnpm build", "test:build:tunnel-object": "pnpm install && E2E_TEST_TUNNEL_ROUTE_MODE=object E2E_TEST_DSN=http://public@localhost:3031/1337 pnpm build", - "test:build-latest": "pnpm add @tanstack/react-start@latest @tanstack/react-router@latest && pnpm install && pnpm build", + "test:build-latest": "pnpm add @tanstack/react-start@latest @tanstack/react-router@latest nitro@latest vite@latest @vitejs/plugin-react-swc@latest vite-tsconfig-paths@latest && pnpm install && pnpm build", "test:assert:proxy": "pnpm test && TEST_ENV=development pnpm playwright test db-drivers", "test:assert": "pnpm test:assert:proxy", "test:assert:tunnel-generated": "E2E_TEST_TUNNEL_ROUTE_MODE=dynamic E2E_TEST_DSN=http://public@localhost:3031/1337 pnpm test", diff --git a/packages/tanstackstart-react/src/vite/routePatterns.ts b/packages/tanstackstart-react/src/vite/routePatterns.ts index 5ffbdaa83c52..82a187d08e70 100644 --- a/packages/tanstackstart-react/src/vite/routePatterns.ts +++ b/packages/tanstackstart-react/src/vite/routePatterns.ts @@ -19,6 +19,16 @@ export function makeRoutePatternPlugin(): Plugin { name: 'sentry-tanstackstart-route-patterns', enforce: 'post', + // The transform below must see the SDK's own `wrapFetchWithSentry` file. Vite externalizes dependencies in + // server builds, and Nitro 3 copies external dependencies into its output instead of bundling them. + configEnvironment(name, config, env) { + if (env.command === 'serve' || (config.consumer ?? (name === 'client' ? 'client' : 'server')) !== 'server') { + return null; + } + + return { resolve: { noExternal: ['@sentry/tanstackstart-react'] } }; + }, + configResolved(config) { resolvedRoot = config.root || process.cwd(); }, diff --git a/packages/tanstackstart-react/test/vite/routePatterns.test.ts b/packages/tanstackstart-react/test/vite/routePatterns.test.ts index 413b29adafe1..abc5c92527d9 100644 --- a/packages/tanstackstart-react/test/vite/routePatterns.test.ts +++ b/packages/tanstackstart-react/test/vite/routePatterns.test.ts @@ -2,7 +2,30 @@ import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -import { extractRoutePatterns, findRouteTreeFile } from '../../src/vite/routePatterns'; +import { extractRoutePatterns, findRouteTreeFile, makeRoutePatternPlugin } from '../../src/vite/routePatterns'; + +describe('makeRoutePatternPlugin', () => { + const configEnvironment = makeRoutePatternPlugin().configEnvironment as ( + name: string, + config: { consumer?: 'client' | 'server' }, + env: { command: 'build' | 'serve'; mode: string }, + ) => { resolve: { noExternal: string[] } } | null; + + it('bundles the SDK into server environments of a build', () => { + const build = { command: 'build', mode: 'production' } as const; + + expect(configEnvironment('ssr', {}, build)).toEqual({ resolve: { noExternal: ['@sentry/tanstackstart-react'] } }); + expect(configEnvironment('nitro', { consumer: 'server' }, build)).toEqual({ + resolve: { noExternal: ['@sentry/tanstackstart-react'] }, + }); + }); + + it('does not change client environments or the dev server', () => { + expect(configEnvironment('client', {}, { command: 'build', mode: 'production' })).toBeNull(); + expect(configEnvironment('ssr', { consumer: 'client' }, { command: 'build', mode: 'production' })).toBeNull(); + expect(configEnvironment('ssr', {}, { command: 'serve', mode: 'development' })).toBeNull(); + }); +}); describe('extractRoutePatterns', () => { it('extracts full path patterns from single-line fullPaths union', () => {