Skip to content

fix: reduce start SSR manifest asset duplication#7157

Merged
schiller-manuel merged 3 commits intomainfrom
fix-ssr-manifest-dedupe
Apr 11, 2026
Merged

fix: reduce start SSR manifest asset duplication#7157
schiller-manuel merged 3 commits intomainfrom
fix-ssr-manifest-dedupe

Conversation

@schiller-manuel
Copy link
Copy Markdown
Contributor

@schiller-manuel schiller-manuel commented Apr 11, 2026

Summary by CodeRabbit

  • New Features
    • Reduced SSR payload by excluding unmatched-route assets while preserving shared asset deduplication
    • Improved manifest serialization to ensure reliable asset identity across routes
  • Tests
    • Added Playwright e2e and unit tests validating SSR HTML, CSS-module hydration, client navigation, and shared asset reuse across routes

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 11, 2026

📝 Walkthrough

Walkthrough

Excludes unmatched route assets from SSR-dehydrated router state, adds seroval-based start-manifest serialization to preserve shared asset identity, changes server to disable unmatched-route assets by default, and introduces an E2E suite validating CSS-module hydration, navigation, and manifest asset reuse.

Changes

Cohort / File(s) Summary
Changeset
./.changeset/cyan-camels-dance.md
New changeset documenting SSR dehydration and manifest serialization changes plus tests.
E2E: Project config
e2e/react-start/start-manifest/package.json, e2e/react-start/start-manifest/playwright.config.ts, e2e/react-start/start-manifest/tsconfig.json, e2e/react-start/start-manifest/vite.config.ts
New E2E project scaffold and scripts (build/start/test) for the start-manifest scenario.
E2E: UI & Styles
e2e/react-start/start-manifest/src/components/AppShell.tsx, e2e/react-start/start-manifest/src/components/SharedNestedLayout.tsx, e2e/react-start/start-manifest/src/styles/*
New layout and shared components with CSS modules used to exercise hydration and style isolation.
E2E: Routes & Router
e2e/react-start/start-manifest/src/routes/__root.tsx, e2e/react-start/start-manifest/src/routes/index.tsx, e2e/react-start/start-manifest/src/routes/r*.tsx, e2e/react-start/start-manifest/src/routes/shared-*.tsx, e2e/react-start/start-manifest/src/routeTree.gen.ts, e2e/react-start/start-manifest/src/router.tsx
File-based route files, generated route tree/types, and router setup for SSR + client hydration tests.
E2E: Tests
e2e/react-start/start-manifest/tests/start-manifest.spec.ts
Comprehensive Playwright tests asserting SSR stylesheet inclusion/exclusion, hydration, navigation, computed CSS validation, and manifest asset identity reuse.
Router Core: SSR behavior
packages/router-core/src/ssr/ssr-server.ts, packages/router-core/tests/ssr-server-manifest.test.ts
Added optional includeUnmatchedRouteAssets parameter (default true) affecting manifest dehydration; tests validate both behaviors.
Start Plugin Core: manifest serialization
packages/start-plugin-core/package.json, packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts, packages/start-plugin-core/src/vite/start-manifest-plugin/plugin.ts, packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
Added seroval dependency, introduced StartManifest type and serializeStartManifest (seroval) and updated Vite plugin to emit serialized manifest; tests assert shared asset identity preserved after round-trip.
Start Server Core: default change
packages/start-server-core/src/createStartHandler.ts
Server now invokes SSR utils with includeUnmatchedRouteAssets: false, excluding unmatched-route assets from production SSR outputs.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client (Browser)
    participant Server as Server (Nitro/Vite SSR)
    participant Router as Router SSR
    participant ManifestBuilder as StartManifest Builder
    participant Store as Serialized Manifest (seroval)

    Client->>Server: HTTP SSR request (route)
    Server->>Router: load router, run server SSR
    Router->>ManifestBuilder: request start-manifest for matched routes
    ManifestBuilder->>Store: serializeStartManifest(startManifest)
    Store-->>Router: serialized manifest (embedded)
    Router-->>Server: dehydrate router state (exclude unmatched assets per flag)
    Server-->>Client: SSR HTML + serialized manifest payload
    Client->>Client: hydrate, fetch clientEntry, reuse shared assets (identity preserved)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nibble at manifests light and lean,

Seroval keeps shared sprites pristine,
SSR trims routes that do not meet,
CSS stays true from head to feet,
Hops, tests, and bytes—what a scene!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.13% 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 name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix: reduce start SSR manifest asset duplication' directly and clearly summarizes the main change: reducing SSR manifest payload size by excluding unmatched route assets, which reduces duplication. The title is concise, specific, and accurately reflects the core objective.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-ssr-manifest-dedupe

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 11, 2026

🚀 Changeset Version Preview

3 package(s) bumped directly, 20 bumped as dependents.

🟩 Patch bumps

Package Version Reason
@tanstack/router-core 1.168.12 → 1.168.13 Changeset
@tanstack/start-plugin-core 1.167.26 → 1.167.27 Changeset
@tanstack/start-server-core 1.167.16 → 1.167.17 Changeset
@tanstack/react-router 1.168.16 → 1.168.17 Dependent
@tanstack/react-start 1.167.29 → 1.167.30 Dependent
@tanstack/react-start-client 1.166.33 → 1.166.34 Dependent
@tanstack/react-start-rsc 0.0.9 → 0.0.10 Dependent
@tanstack/react-start-server 1.166.34 → 1.166.35 Dependent
@tanstack/router-cli 1.166.28 → 1.166.29 Dependent
@tanstack/router-generator 1.166.27 → 1.166.28 Dependent
@tanstack/router-plugin 1.167.15 → 1.167.16 Dependent
@tanstack/router-vite-plugin 1.166.30 → 1.166.31 Dependent
@tanstack/solid-router 1.168.15 → 1.168.16 Dependent
@tanstack/solid-start 1.167.27 → 1.167.28 Dependent
@tanstack/solid-start-client 1.166.31 → 1.166.32 Dependent
@tanstack/solid-start-server 1.166.32 → 1.166.33 Dependent
@tanstack/start-client-core 1.167.14 → 1.167.15 Dependent
@tanstack/start-static-server-functions 1.166.30 → 1.166.31 Dependent
@tanstack/start-storage-context 1.166.26 → 1.166.27 Dependent
@tanstack/vue-router 1.168.15 → 1.168.16 Dependent
@tanstack/vue-start 1.167.27 → 1.167.28 Dependent
@tanstack/vue-start-client 1.166.31 → 1.166.32 Dependent
@tanstack/vue-start-server 1.166.32 → 1.166.33 Dependent

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 11, 2026

Bundle Size Benchmarks

  • Commit: 5cec6fbdaf9d
  • Measured at: 2026-04-11T18:14:31.850Z
  • Baseline source: history:8ec9ca97b472
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.34 KiB 0 B (0.00%) 274.64 KiB 75.89 KiB ▇██▇▇▇▄▁▁▁▁
react-router.full 90.61 KiB 0 B (0.00%) 285.71 KiB 78.72 KiB ██████▄▁▁▁▁
solid-router.minimal 35.53 KiB 0 B (0.00%) 106.64 KiB 31.96 KiB ▅█████▅▁▁▁▁
solid-router.full 39.99 KiB 0 B (0.00%) 120.13 KiB 35.88 KiB ▅█████▅▁▁▁▁
vue-router.minimal 53.31 KiB 0 B (0.00%) 152.04 KiB 47.91 KiB ▇█████▄▁▁▁▁
vue-router.full 58.21 KiB 0 B (0.00%) 167.47 KiB 52.11 KiB ▆█████▄▁▁▁▁
react-start.minimal 101.75 KiB 0 B (0.00%) 322.36 KiB 87.96 KiB ▇███▅▅▃▁▁▁▁
react-start.full 105.19 KiB 0 B (0.00%) 332.69 KiB 90.87 KiB ▇███▆▆▃▁▁▁▁
solid-start.minimal 49.53 KiB 0 B (0.00%) 152.45 KiB 43.67 KiB ▇███▅▅▃▁▁▁▁
solid-start.full 55.04 KiB 0 B (0.00%) 168.65 KiB 48.46 KiB ▇███▅▅▄▁▁▁▁

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/router-core/src/ssr/ssr-server.ts (1)

245-247: ⚠️ Potential issue | 🟠 Major

Include the new option in the manifest cache key.

Line 246 caches by route IDs only. In production, if two routers share the same manifest but use different includeUnmatchedRouteAssets values, one can reuse the other’s cached filtered routes and return the wrong manifest shape.

Suggested fix
-        const manifestCacheKey = currentRouteIdsList.join('\0')
+        const manifestCacheKey = `${includeUnmatchedRouteAssets ? '1' : '0'}\0${currentRouteIdsList.join('\0')}`

Also applies to: 250-275

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/src/ssr/ssr-server.ts` around lines 245 - 247, Cache key
currently built from currentRouteIdsList (manifestCacheKey) ignores the
includeUnmatchedRouteAssets option, so different includeUnmatchedRouteAssets
settings can collide; update the cache key construction (where manifestCacheKey
is created/used in ssr-server.ts and the related cache logic around
matchesToDehydrate) to incorporate the includeUnmatchedRouteAssets boolean (or
its string/serialised form) into the key (e.g., append
`\0includeUnmatchedRouteAssets=${includeUnmatchedRouteAssets}`) so cached
filtered manifests are segregated by that option.
🧹 Nitpick comments (2)
packages/router-core/src/ssr/ssr-server.ts (1)

241-243: Update the filtering comment to match the new conditional behavior.

The comment says unmatched routes always include assets, but this now depends on includeUnmatchedRouteAssets.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/src/ssr/ssr-server.ts` around lines 241 - 243, Update
the misleading comment above the manifest conditional to reflect the new
conditional behavior: instead of stating "For all other routes, only send assets
(no preloads...)", mention that unmatched routes will include assets only when
includeUnmatchedRouteAssets is true; reference the existing manifest conditional
and the includeUnmatchedRouteAssets flag in the comment so readers know the
behavior depends on includeUnmatchedRouteAssets.
packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts (1)

1-1: Import ordering and type specifier style.

ESLint flags import ordering and suggests using top-level type-only imports. These are style preferences that could be addressed for consistency.

♻️ Optional: Fix import ordering and type specifier style
+import type { StartManifest } from '../../src/start-manifest-plugin/manifestBuilder'
 import { deserialize } from 'seroval'
 import { describe, expect, test } from 'vitest'
 import {
   appendUniqueAssets,
   appendUniqueStrings,
   buildStartManifest,
   collectDynamicImportCss,
   createChunkCssAssetCollector,
   createManifestAssetResolvers,
   getRouteFilePathsFromModuleIds,
   normalizeViteClientBuild,
   normalizeViteClientChunk,
-  serializeStartManifest,
   scanClientChunks,
-  type StartManifest,
+  serializeStartManifest,
 } from '../../src/start-manifest-plugin/manifestBuilder'

Also applies to: 13-15

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts`
at line 1, Reorder and style the imports so runtime imports like "deserialize"
from 'seroval' are grouped before/after other groups per the project's
import-order rule, and convert any type-only imports used in this test (e.g.,
interfaces or types imported on lines around the test file where types are
imported) to top-level "import type" specifiers; update the "import {
deserialize } from 'seroval'" import grouping and change any purely type imports
referenced in this file to use "import type" to satisfy ESLint import-order and
type-only import rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/router-core/src/ssr/ssr-server.ts`:
- Around line 245-247: Cache key currently built from currentRouteIdsList
(manifestCacheKey) ignores the includeUnmatchedRouteAssets option, so different
includeUnmatchedRouteAssets settings can collide; update the cache key
construction (where manifestCacheKey is created/used in ssr-server.ts and the
related cache logic around matchesToDehydrate) to incorporate the
includeUnmatchedRouteAssets boolean (or its string/serialised form) into the key
(e.g., append `\0includeUnmatchedRouteAssets=${includeUnmatchedRouteAssets}`) so
cached filtered manifests are segregated by that option.

---

Nitpick comments:
In `@packages/router-core/src/ssr/ssr-server.ts`:
- Around line 241-243: Update the misleading comment above the manifest
conditional to reflect the new conditional behavior: instead of stating "For all
other routes, only send assets (no preloads...)", mention that unmatched routes
will include assets only when includeUnmatchedRouteAssets is true; reference the
existing manifest conditional and the includeUnmatchedRouteAssets flag in the
comment so readers know the behavior depends on includeUnmatchedRouteAssets.

In
`@packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts`:
- Line 1: Reorder and style the imports so runtime imports like "deserialize"
from 'seroval' are grouped before/after other groups per the project's
import-order rule, and convert any type-only imports used in this test (e.g.,
interfaces or types imported on lines around the test file where types are
imported) to top-level "import type" specifiers; update the "import {
deserialize } from 'seroval'" import grouping and change any purely type imports
referenced in this file to use "import type" to satisfy ESLint import-order and
type-only import rules.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f949c0cf-e87b-428d-919d-074555766fee

📥 Commits

Reviewing files that changed from the base of the PR and between 8ec9ca9 and 0b6b6cf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (32)
  • .changeset/cyan-camels-dance.md
  • e2e/react-start/start-manifest/package.json
  • e2e/react-start/start-manifest/playwright.config.ts
  • e2e/react-start/start-manifest/src/components/AppShell.tsx
  • e2e/react-start/start-manifest/src/components/SharedNestedLayout.tsx
  • e2e/react-start/start-manifest/src/routeTree.gen.ts
  • e2e/react-start/start-manifest/src/router.tsx
  • e2e/react-start/start-manifest/src/routes/__root.tsx
  • e2e/react-start/start-manifest/src/routes/index.tsx
  • e2e/react-start/start-manifest/src/routes/r1.tsx
  • e2e/react-start/start-manifest/src/routes/r2.tsx
  • e2e/react-start/start-manifest/src/routes/r3.tsx
  • e2e/react-start/start-manifest/src/routes/r4.tsx
  • e2e/react-start/start-manifest/src/routes/r5.tsx
  • e2e/react-start/start-manifest/src/routes/r6.tsx
  • e2e/react-start/start-manifest/src/routes/shared-a.tsx
  • e2e/react-start/start-manifest/src/routes/shared-b.tsx
  • e2e/react-start/start-manifest/src/routes/shared-c.tsx
  • e2e/react-start/start-manifest/src/styles/root-shell.module.css
  • e2e/react-start/start-manifest/src/styles/route-one.module.css
  • e2e/react-start/start-manifest/src/styles/route-two.module.css
  • e2e/react-start/start-manifest/src/styles/shared-layout.module.css
  • e2e/react-start/start-manifest/tests/start-manifest.spec.ts
  • e2e/react-start/start-manifest/tsconfig.json
  • e2e/react-start/start-manifest/vite.config.ts
  • packages/router-core/src/ssr/ssr-server.ts
  • packages/router-core/tests/ssr-server-manifest.test.ts
  • packages/start-plugin-core/package.json
  • packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts
  • packages/start-plugin-core/src/vite/start-manifest-plugin/plugin.ts
  • packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
  • packages/start-server-core/src/createStartHandler.ts

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud bot commented Apr 11, 2026

View your CI Pipeline Execution ↗ for commit 8f5b695

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 1m 32s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-11 18:15:28 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 11, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7157

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-rsc

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 8f5b695

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 11, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing fix-ssr-manifest-dedupe (8f5b695) with main (8ec9ca9)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (5cec6fb) during the generation of this report, so 8ec9ca9 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

nx-cloud[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts (1)

3-16: ⚠️ Potential issue | 🟡 Minor

Fix import style/order to clear current ESLint failures.

This block currently violates sort-imports and import/consistent-type-specifier-style (inline type StartManifest + member ordering).

Suggested diff
 import {
   appendUniqueAssets,
   appendUniqueStrings,
   buildStartManifest,
   collectDynamicImportCss,
   createChunkCssAssetCollector,
   createManifestAssetResolvers,
   getRouteFilePathsFromModuleIds,
   normalizeViteClientBuild,
   normalizeViteClientChunk,
-  serializeStartManifest,
   scanClientChunks,
-  type StartManifest,
+  serializeStartManifest,
 } from '../../src/start-manifest-plugin/manifestBuilder'
+import type { StartManifest } from '../../src/start-manifest-plugin/manifestBuilder'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts`
around lines 3 - 16, The import list violates sort-imports and
import/consistent-type-specifier-style; fix by splitting the type import into a
dedicated type-only import and alphabetizing the non-type imports from the
module. For example, keep value exports (appendUniqueAssets,
appendUniqueStrings, buildStartManifest, collectDynamicImportCss,
createChunkCssAssetCollector, createManifestAssetResolvers,
getRouteFilePathsFromModuleIds, normalizeViteClientBuild,
normalizeViteClientChunk, scanClientChunks, serializeStartManifest) in one
alphabetized import, and add a separate "import type { StartManifest }" line for
the type; ensure the member order matches project import sorting rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts`:
- Around line 3-16: The import list violates sort-imports and
import/consistent-type-specifier-style; fix by splitting the type import into a
dedicated type-only import and alphabetizing the non-type imports from the
module. For example, keep value exports (appendUniqueAssets,
appendUniqueStrings, buildStartManifest, collectDynamicImportCss,
createChunkCssAssetCollector, createManifestAssetResolvers,
getRouteFilePathsFromModuleIds, normalizeViteClientBuild,
normalizeViteClientChunk, scanClientChunks, serializeStartManifest) in one
alphabetized import, and add a separate "import type { StartManifest }" line for
the type; ensure the member order matches project import sorting rules.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6c7dc4a-a377-4258-baf8-fd9567c72be1

📥 Commits

Reviewing files that changed from the base of the PR and between 0b6b6cf and 1c7146f.

📒 Files selected for processing (2)
  • packages/router-core/src/ssr/ssr-server.ts
  • packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts

Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud bot left a comment

Choose a reason for hiding this comment

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

Nx Cloud is proposing a fix for your failed CI:

We add non-null assertions (!) to the assets property accesses in the new serializeStartManifest identity test, fixing the TS2532 "Object is possibly 'undefined'" errors raised by TypeScript 5.6's stricter indexed-access checks. The assets field is optional on RouteTreeRoute, but the test explicitly constructs routes with assets populated, so the assertions are safe and accurately reflect the test's intent.

Tip

We verified this fix by re-running @tanstack/start-plugin-core:test:types.

diff --git a/packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts b/packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
index 9cdb00d8e2..c11b1f6726 100644
--- a/packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
+++ b/packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts
@@ -703,11 +703,11 @@ describe('buildStartManifest', () => {
       serializeStartManifest(manifest),
     )
 
-    expect(evaluated.routes['/a'].assets[0]).toBe(
-      evaluated.routes['/b'].assets[0],
+    expect(evaluated.routes['/a']!.assets![0]).toBe(
+      evaluated.routes['/b']!.assets![0],
     )
-    expect(evaluated.routes['/b'].assets[0]).toBe(
-      evaluated.routes['/c'].assets[0],
+    expect(evaluated.routes['/b']!.assets![0]).toBe(
+      evaluated.routes['/c']!.assets![0],
     )
   })
 

Apply fix via Nx Cloud  Reject fix via Nx Cloud


Or Apply changes locally with:

npx nx-cloud apply-locally 65lt-TxmR

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts (1)

3-16: ⚠️ Potential issue | 🟡 Minor

Fix import ordering and split the type-only import.

This block currently violates the configured lint rules (sort-imports and import/consistent-type-specifier-style).

Proposed fix
 import {
   appendUniqueAssets,
   appendUniqueStrings,
   buildStartManifest,
   collectDynamicImportCss,
   createChunkCssAssetCollector,
   createManifestAssetResolvers,
   getRouteFilePathsFromModuleIds,
   normalizeViteClientBuild,
   normalizeViteClientChunk,
-  serializeStartManifest,
   scanClientChunks,
-  type StartManifest,
+  serializeStartManifest,
 } from '../../src/start-manifest-plugin/manifestBuilder'
+import type { StartManifest } from '../../src/start-manifest-plugin/manifestBuilder'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts`
around lines 3 - 16, Reorder and split the import list to satisfy the lint
rules: alphabetically sort the imported bindings (appendUniqueAssets,
appendUniqueStrings, buildStartManifest, collectDynamicImportCss,
createChunkCssAssetCollector, createManifestAssetResolvers,
getRouteFilePathsFromModuleIds, normalizeViteClientBuild,
normalizeViteClientChunk, scanClientChunks, serializeStartManifest) and move the
type-only import into its own statement using the `import type { StartManifest }
from '../../src/start-manifest-plugin/manifestBuilder'` form so the type
specifier style is consistent with linting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts`:
- Around line 3-16: Reorder and split the import list to satisfy the lint rules:
alphabetically sort the imported bindings (appendUniqueAssets,
appendUniqueStrings, buildStartManifest, collectDynamicImportCss,
createChunkCssAssetCollector, createManifestAssetResolvers,
getRouteFilePathsFromModuleIds, normalizeViteClientBuild,
normalizeViteClientChunk, scanClientChunks, serializeStartManifest) and move the
type-only import into its own statement using the `import type { StartManifest }
from '../../src/start-manifest-plugin/manifestBuilder'` form so the type
specifier style is consistent with linting.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be4725c9-5fe0-43b6-b580-f03da2212b6e

📥 Commits

Reviewing files that changed from the base of the PR and between 1c7146f and 8f5b695.

📒 Files selected for processing (1)
  • packages/start-plugin-core/tests/start-manifest-plugin/manifestBuilder.test.ts

@schiller-manuel schiller-manuel merged commit 812792f into main Apr 11, 2026
15 of 16 checks passed
@schiller-manuel schiller-manuel deleted the fix-ssr-manifest-dedupe branch April 11, 2026 18:15
Sign up for free to 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