Skip to content

fix(router): core trim whitespace from SSR dehydrated script output#7081

Open
canmi21 wants to merge 1 commit intoTanStack:mainfrom
canmi21:main
Open

fix(router): core trim whitespace from SSR dehydrated script output#7081
canmi21 wants to merge 1 commit intoTanStack:mainfrom
canmi21:main

Conversation

@canmi21
Copy link
Copy Markdown
Contributor

@canmi21 canmi21 commented Mar 31, 2026

Fix: #6947

Summary by CodeRabbit

  • Chores
    • Improved script handling consistency in server-side rendering by standardizing whitespace formatting in script injection, ensuring cleaner and more consistent script output.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

Updated the ScriptBuffer in the SSR server to trim whitespace from all initial queued scripts and each subsequently enqueued script before concatenation and injection, removing unnecessary leading and trailing whitespace from machine-generated dehydrated script output.

Changes

Cohort / File(s) Summary
SSR Script Buffering
packages/router-core/src/ssr/ssr-server.ts
Modified ScriptBuffer initialization to apply .trim() to initial scripts via INITIAL_SCRIPTS.map((s) => s.trim()) and to enqueued scripts via script.trim(), eliminating unnecessary whitespace from injected SSR dehydration scripts.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

🐰 A hop, a skip, through script so fine,
We trim the edges, make them align,
No extra spaces on the page,
Clean HTML is all the rage!
Whitespace be gone!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: trimming whitespace from SSR dehydrated script output in the router core.
Linked Issues check ✅ Passed The code changes directly address issue #6947 by trimming whitespace from initial and subsequently enqueued scripts to reduce HTML payload size.
Out of Scope Changes check ✅ Passed All changes are focused on whitespace trimming in the SSR script buffer, directly aligned with the objective to reduce payload size.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud bot commented Mar 31, 2026

View your CI Pipeline Execution ↗ for commit b31163d

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

☁️ Nx Cloud last updated this comment at 2026-03-31 13:53:22 UTC

@github-actions
Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: 5a81726f0a2f
  • Measured at: 2026-03-31T13:45:30.953Z
  • Baseline source: history:796406da66cf
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.48 KiB 0 B (0.00%) 275.76 KiB 75.97 KiB ████▁▁▁▁▁▂▃
react-router.full 90.78 KiB 0 B (0.00%) 286.95 KiB 78.95 KiB ▆▆▆█▁▁▁▁▁▂▂
solid-router.minimal 35.56 KiB 0 B (0.00%) 107.26 KiB 31.94 KiB ████▁▁▁▁▁▂█
solid-router.full 40.03 KiB 0 B (0.00%) 120.79 KiB 35.94 KiB ████▁▁▁▁▁▂▆
vue-router.minimal 53.38 KiB 0 B (0.00%) 153.07 KiB 47.94 KiB ████▁▁▁▁▁▂▄
vue-router.full 58.25 KiB 0 B (0.00%) 168.53 KiB 52.18 KiB ████▁▁▁▁▁▂▄
react-start.minimal 102.01 KiB 0 B (0.00%) 324.00 KiB 88.21 KiB ▅▅▅█▁▂▂▂▂▃▃
react-start.full 105.38 KiB 0 B (0.00%) 334.35 KiB 91.14 KiB ▆▆▆█▁▁▁▂▂▃▃
solid-start.minimal 49.66 KiB 0 B (0.00%) 153.51 KiB 43.84 KiB ▇▇▇▇▁▁▁▂▂▂█
solid-start.full 55.17 KiB 0 B (0.00%) 169.74 KiB 48.46 KiB ▇▇▇▇▁▂▂▂▂▃█

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 31, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: b31163d

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.

🧹 Nitpick comments (1)
packages/router-core/src/ssr/ssr-server.ts (1)

77-83: Harden concatenation boundaries after trimming script chunks.

Line 78 and Line 83 remove trailing newlines; combined with takeAll() using ';' separators, a chunk ending in // ... can comment out the next fragment. Keep trimming, but make concatenation newline-safe (and skip empty trimmed chunks).

Proposed patch
  enqueue(script: string) {
    if (this._cleanedUp) return
-    this._queue.push(script.trim())
+    const trimmed = script.trim()
+    if (!trimmed) return
+    this._queue.push(trimmed)
    // If barrier is lifted, schedule injection (if not already scheduled)
    if (this._scriptBarrierLifted && !this._pendingMicrotask) {
      this._pendingMicrotask = true
      queueMicrotask(() => {
        this._pendingMicrotask = false
        this.injectBufferedScripts()
      })
    }
  }

  takeAll() {
    const bufferedScripts = this._queue
    this._queue = []
    if (bufferedScripts.length === 0) {
      return undefined
    }
    // Optimization: if only one script, avoid join
    if (bufferedScripts.length === 1) {
-      return bufferedScripts[0] + ';document.currentScript.remove()'
+      return bufferedScripts[0] + '\n;document.currentScript.remove()'
    }
    // Append cleanup script and join - avoid push() to not mutate then iterate
-    return bufferedScripts.join(';') + ';document.currentScript.remove()'
+    return bufferedScripts.join(';\n') + '\n;document.currentScript.remove()'
  }
🤖 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 77 - 83, Trimmed
script chunks currently get concatenated with a bare ';' in takeAll, which lets
a trailing '//' comment in one chunk swallow the next; update
enqueue/INITIAL_SCRIPTS handling to skip empty trimmed chunks (don't push ''),
and change the concatenation in takeAll to join using a newline-safe boundary
(e.g., ';\n' or '\n') so fragments can't comment out following code; reference
_queue, enqueue, INITIAL_SCRIPTS and takeAll when making these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/router-core/src/ssr/ssr-server.ts`:
- Around line 77-83: Trimmed script chunks currently get concatenated with a
bare ';' in takeAll, which lets a trailing '//' comment in one chunk swallow the
next; update enqueue/INITIAL_SCRIPTS handling to skip empty trimmed chunks
(don't push ''), and change the concatenation in takeAll to join using a
newline-safe boundary (e.g., ';\n' or '\n') so fragments can't comment out
following code; reference _queue, enqueue, INITIAL_SCRIPTS and takeAll when
making these changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b895588b-afbe-4ed4-9fd7-c0ff5a259211

📥 Commits

Reviewing files that changed from the base of the PR and between 5a81726 and b31163d.

📒 Files selected for processing (1)
  • packages/router-core/src/ssr/ssr-server.ts

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 31, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing canmi21:main (b31163d) with main (796406d)1

Open in CodSpeed

Footnotes

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

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.

Start: SSR dehydrated script output contains unnecessary whitespace/newlines

1 participant