Skip to content

feat: support split base and basepath in TanStack Start dev server - #6792

Merged
schiller-manuel merged 2 commits into
mainfrom
feat-split-base
Mar 1, 2026
Merged

feat: support split base and basepath in TanStack Start dev server#6792
schiller-manuel merged 2 commits into
mainfrom
feat-split-base

Conversation

@schiller-manuel

@schiller-manuelschiller-manuel commented Mar 1, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added support for split base and basepath in React e2e project and a dev middleware to transparently rewrite URLs when bases differ.
  • Bug Fixes

    • Resolved runtime error caused by misaligned router basepath and dev server base.
  • Tests

    • Added comprehensive end-to-end Playwright tests validating SSR, asset paths, and client navigation.
  • Chores

    • Removed an unused emitted build-time global and added project scaffolding, configuration, and dependency version updates.

@coderabbitai

coderabbitaiBot commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7cd49b6 and bec3134.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • e2e/react-start/custom-basepath/package.json
  • e2e/react-start/split-base-and-basepath/package.json
  • e2e/react-start/split-base-and-basepath/tests/app.spec.ts
  • e2e/solid-start/custom-basepath/package.json
  • e2e/vue-start/custom-basepath/package.json
  • packages/start-plugin-core/src/plugin.ts
✅ Files skipped from review due to trivial changes (1)
  • e2e/react-start/custom-basepath/package.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/react-start/split-base-and-basepath/package.json
  • packages/start-plugin-core/src/plugin.ts

📝 Walkthrough

Walkthrough

Adds a new e2e fixture (split-base-and-basepath) with router routes, tests, and Vite/Playwright configs; introduces dev-time URL-rewrite middleware in start-plugin-core to handle mismatched Vite base vs router basepath; removes a define constant from an existing Vite config.

Changes

Cohort / File(s)Summary
Vite config tweak
e2e/react-start/import-protection/vite.config.ts
Removed the define.__IMPORT_PROTECTION_FIXTURE_ROOT__ property from the exported Vite config.
New e2e fixture (configs & tooling)
e2e/react-start/split-base-and-basepath/.gitignore, .../.prettierignore, .../package.json, .../playwright.config.ts, .../tsconfig.json, .../vite.config.ts
Adds a new e2e project with TypeScript, Vite (base '/_ui/'), Playwright config, and scripts for dev/prod/e2e flows.
New e2e fixture (app source & styles)
e2e/react-start/split-base-and-basepath/src/routeTree.gen.ts, .../src/router.tsx, .../src/routes/__root.tsx, .../src/routes/index.tsx, .../src/routes/about.tsx, .../src/styles/app.css
Generated route tree, router factory, root/index/about routes, and base CSS to exercise split base/basepath routing and SSR integration.
New e2e fixture (server & tests)
e2e/react-start/split-base-and-basepath/prod-server.js, .../tests/app.spec.ts
Adds Express prod-server bootstrap serving SSR and static client under /_ui/, plus Playwright tests validating SSR asset prefixes and navigation.
Start plugin runtime change
packages/start-plugin-core/src/plugin.ts
Replaces error on misaligned router basepath with a needsDevBaseRewrite flag and registers a tanstack-start-core:dev-base-rewrite plugin that installs early Connect middleware to rewrite incoming request URLs by prefixing the Vite base in dev.
Dependency bumps
e2e/*/custom-basepath/package.json (multiple)
Bumps express dependency from ^4.21.2 to ^5.1.0 in several e2e projects.

Sequence Diagram

sequenceDiagram
participant Client as Browser/Client
participant DevRewrite as Dev Base Rewrite Middleware
participant ViteBase as Vite Base Middleware
participant SSR as SSR Handler
Note over Client,SSR: Dev-mode request when router basepath != Vite base
Client->>DevRewrite: GET /about
DevRewrite->>DevRewrite: detects Vite base '/_ui/' and rewrites URL
DevRewrite->>ViteBase: GET /_ui/about
ViteBase->>ViteBase: strips '/_ui/' prefix
ViteBase->>SSR: GET /about
SSR->>SSR: render HTML with asset URLs prefixed '/_ui/'
SSR->>ViteBase: return HTML
ViteBase->>DevRewrite: pass-through
DevRewrite->>Client: HTML response (assets use /_ui/*)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • birkskyum

Poem

🐰 I hopped through routes and Vite's domain,
I rewrote paths to keep requests sane,
Home and About now play in tune,
Assets march under /_ui/ moon,
A tiny rabbit cheers the new deploy — hooray! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately describes the main change: adding support for split base and basepath in the TanStack Start dev server, which is the core feature introduced by the dev-base-rewrite plugin and accompanying e2e tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-split-base

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud

nx-cloudBot commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit bec3134

CommandStatusDurationResult
nx run tanstack-router-e2e-bundle-size:build --...✅ Succeeded1m 26sView ↗

☁️ Nx Cloud last updated this comment at 2026-03-01 17:33:05 UTC

@pkg-pr-new

pkg-pr-newBot commented Mar 1, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@6792

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@6792

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@6792

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@6792

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@6792

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@6792

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@6792

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@6792

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@6792

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@6792

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@6792

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@6792

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@6792

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@6792

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@6792

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@6792

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@6792

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@6792

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@6792

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@6792

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@6792

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@6792

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@6792

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@6792

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@6792

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@6792

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@6792

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@6792

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@6792

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@6792

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@6792

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@6792

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@6792

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@6792

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@6792

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@6792

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@6792

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@6792

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@6792

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@6792

commit: c5ff07b

@github-actions

github-actionsBot commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: 5a625b2f5208
  • Measured at: 2026-03-01T17:25:07.258Z
  • Baseline source: history:e979285ebbc8
  • Dashboard: bundle-size history
ScenarioCurrent (gzip)Delta vs baselineRawBrotliTrend
react-router.minimal86.58 KiB0 B (0.00%)272.45 KiB75.22 KiB▁▁▁▇▇██████
react-router.full89.61 KiB0 B (0.00%)282.78 KiB77.90 KiB▁▁▁▇▇██████
solid-router.minimal35.88 KiB0 B (0.00%)107.56 KiB32.26 KiB▁▁▁▆▆██████
solid-router.full40.21 KiB0 B (0.00%)120.61 KiB36.13 KiB▁▁▁▆▆██████
vue-router.minimal51.75 KiB0 B (0.00%)147.54 KiB46.50 KiB▁▁▁▆▆██████
vue-router.full56.55 KiB0 B (0.00%)163.12 KiB50.86 KiB▁▁▁▅▅██████
react-start.minimal99.11 KiB0 B (0.00%)311.58 KiB85.68 KiB▁▁▁▅▅██████
react-start.full102.50 KiB0 B (0.00%)321.39 KiB88.63 KiB▁▁▁▅▅▇▇▇▇▇█
solid-start.minimal48.19 KiB0 B (0.00%)145.13 KiB42.67 KiB▁▁▁▆▆██████
solid-start.full53.68 KiB0 B (0.00%)161.08 KiB47.37 KiB▁▁▁▆▆▇▇▇▇▇█

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
e2e/react-start/split-base-and-basepath/playwright.config.ts (1)

21-27: Remove duplicated PORT injection in prod command.

webServer.env.PORT already provides the variable; keeping it only there reduces command-string coupling.

♻️ Suggested patch
 webServer: {
- command: isDev ? `pnpm dev:e2e` : `pnpm build && PORT=${PORT} pnpm start`,+ command: isDev ? `pnpm dev:e2e` : `pnpm build && pnpm start`,
url: baseURL,
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@e2e/react-start/split-base-and-basepath/playwright.config.ts` around lines 21
- 27, The prod command in the Playwright webServer config duplicates PORT by
embedding PORT=${PORT} in the "command" string while "env" already sets PORT;
update the "command" property used when isDev is false to remove the embedded
PORT=${PORT} so it relies on the webServer.env.PORT value (locate the "command"
property and the webServer "env" object in playwright.config.ts and remove the
PORT injection from the non-dev command).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@e2e/react-start/split-base-and-basepath/package.json`:
- Around line 18-26: The package.json shows a runtime dependency "express" at v4
while devDependencies use "@types/express" v5 causing type mismatches; update
the dependency pair so their major versions match—either change "@types/express"
to a v4 release (e.g., ^4.x) to match "express": "^4.21.2", or upgrade "express"
to v5 and set "@types/express" to the corresponding v5; apply the same alignment
to any other e2e fixture package.json files that list "express" and
"@types/express".
In `@e2e/react-start/split-base-and-basepath/tests/app.spec.ts`:
- Around line 12-14: The test currently parses HTML from the fetch without first
asserting the HTTP response succeeded; add an explicit success assertion
immediately after `const response = await request.get('/')` (for example
`ok(response.ok)` or `assert.strictEqual(response.status, 200)`) so request
failures surface as a clear test/setup error before `const html = await
response.text()` and downstream regex/assert noise; update the test near the
`request.get('/')` call to perform this check.
In `@packages/start-plugin-core/src/plugin.ts`:
- Around line 413-415: The rewrite logic that prefixes req.url with base can
double-prefix when req.url already equals the base root with or without a
trailing slash or query (e.g., "/_ui" or "/_ui?x=1"); update the check to
normalize base (e.g., let normalizedBase = base.replace(/\/$/, '')) and only
prefix when req.url does not already start with normalizedBase nor
normalizedBase + '/' nor equal normalizedBase (and handle query strings
implicitly), i.e., replace the current if (req.url && !req.url.startsWith(base))
{ ... } with a comparison against the normalizedBase variants using the existing
req.url and base symbols so URLs at the base root are not rewritten.
---
Nitpick comments:
In `@e2e/react-start/split-base-and-basepath/playwright.config.ts`:
- Around line 21-27: The prod command in the Playwright webServer config
duplicates PORT by embedding PORT=${PORT} in the "command" string while "env"
already sets PORT; update the "command" property used when isDev is false to
remove the embedded PORT=${PORT} so it relies on the webServer.env.PORT value
(locate the "command" property and the webServer "env" object in
playwright.config.ts and remove the PORT injection from the non-dev command).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a625b2 and 7cd49b6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • e2e/react-start/import-protection/vite.config.ts
  • e2e/react-start/split-base-and-basepath/.gitignore
  • e2e/react-start/split-base-and-basepath/.prettierignore
  • e2e/react-start/split-base-and-basepath/package.json
  • e2e/react-start/split-base-and-basepath/playwright.config.ts
  • e2e/react-start/split-base-and-basepath/prod-server.js
  • e2e/react-start/split-base-and-basepath/src/routeTree.gen.ts
  • e2e/react-start/split-base-and-basepath/src/router.tsx
  • e2e/react-start/split-base-and-basepath/src/routes/__root.tsx
  • e2e/react-start/split-base-and-basepath/src/routes/about.tsx
  • e2e/react-start/split-base-and-basepath/src/routes/index.tsx
  • e2e/react-start/split-base-and-basepath/src/styles/app.css
  • e2e/react-start/split-base-and-basepath/tests/app.spec.ts
  • e2e/react-start/split-base-and-basepath/tsconfig.json
  • e2e/react-start/split-base-and-basepath/vite.config.ts
  • packages/start-plugin-core/src/plugin.ts
💤 Files with no reviewable changes (1)
  • e2e/react-start/import-protection/vite.config.ts

Comment threade2e/react-start/split-base-and-basepath/package.json Outdated
Comment threade2e/react-start/split-base-and-basepath/tests/app.spec.ts
Comment threadpackages/start-plugin-core/src/plugin.ts Outdated
@schiller-manuel
schiller-manuel merged commit d445986 into mainMar 1, 2026
8 checks passed
@schiller-manuel
schiller-manuel deleted the feat-split-base branch March 1, 2026 17:35
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@schiller-manuel