nextjs - 💡(How to fix) Fix Turbopack: JSX whitespace stripped between closing tag and following word when text contains an HTML entity [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#93259Fetched 2026-04-27 05:28:37
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Root Cause

It's a silent prose-quality bug. The build succeeds. Lighthouse passes. The HTML is well-formed. The only signal is words running together in the rendered output, and authors only catch it when they (or a user) reads the page in a browser. We hit it on a content-heavy site and only spotted it after deploy when an end user pointed out two missing spaces; the same pattern was present in dozens of other places we then had to fix.

Fix Action

Workaround

Replace the literal space with an explicit `{" "}` after every closing tag in any paragraph that contains an HTML entity:

```tsx An <Term name="x">foo</Term>{" "}is the smallest — really. ```

Applies to any paragraph containing `—`, `’`, `“`, `–`, etc. Easier in practice to apply the workaround uniformly to all closing tags in prose-heavy files.

RAW_BUFFERClick to expand / collapse

Verify canary release

I ran into this on the latest stable (16.2.4) which builds with Turbopack by default. Have not yet retried on canary; happy to do so if asked.

Provide environment information

  • Operating System: macOS 25.4.0 (Darwin)
  • Node.js: v24.14.1
  • pnpm: 10.33.0
  • Next.js: 16.2.4 (Turbopack, default)
  • React: 19.2.4
  • TypeScript: 5

Which area(s) are affected? (Select all that apply)

Turbopack, SWC

Which stage(s) are affected? (Select all that apply)

next build (production), and the same output is served by next start. Affects deployed Vercel build.

Link to the code that reproduces this issue

Minimal repro inline below — single page, no deps beyond a create-next-app default.

To Reproduce

src/app/test-jsx/page.tsx:

```tsx export default function TestJsx() { return ( <div> <p id="case-a-with-entity"> A: A <strong>bold</strong> word continues with an entity — here. </p> <p id="case-b-no-entity"> B: A <strong>bold</strong> word continues without any entity here. </p> <p id="case-c-entity-same-line"> C: A <strong>bold</strong> word continues — entity on same line. </p> <p id="case-d-explicit-space"> D: A <strong>bold</strong>{" "}word continues with an entity — here. </p> </div> ); } ```

Run `pnpm build` and inspect `.next/server/app/test-jsx.html`.

Describe the Bug

The literal space between a closing tag (e.g. `</strong>`, `</em>`, `</a>`) and the following word is silently stripped in the rendered HTML when the surrounding paragraph contains an HTML entity (`—`, `’`, etc.) — even when the entity is on a different line, and even when the closing tag and following word are on the same line.

Rendered HTML from the four cases above:

CaseSource patternRendered HTMLBug?
A`</strong> word\n cont —``</strong>word continues with an entity`YES
B`</strong> word\n cont (no entity)``</strong> word continues`NO
C`</strong> word continues —` (1 line)`</strong>word continues —`YES
D`</strong>{" "}word ... —` (workaround)`</strong> <!-- -->word continues`NO

Case C is the most surprising: even when everything is on a single line and the JSX text `</strong> word continues — entity on same line.` should preserve the space between `</strong>` and `word`, the entity in the same JSX text expression triggers the strip.

Expected Behavior

Per the JSX whitespace spec (and Babel's behaviour), the literal space between `</strong>` and the following word on the same line should be preserved in the compiled output. The presence of an HTML entity later in the same JSX text expression should not affect this.

Babel produces:

```js React.createElement("p", null, "A: A ", React.createElement("strong", null, "bold"), " word continues with an entity \u2014 here." ); ```

Note the leading space in the third argument. That space is what's missing in SWC's output when an entity follows.

Why this matters

It's a silent prose-quality bug. The build succeeds. Lighthouse passes. The HTML is well-formed. The only signal is words running together in the rendered output, and authors only catch it when they (or a user) reads the page in a browser. We hit it on a content-heavy site and only spotted it after deploy when an end user pointed out two missing spaces; the same pattern was present in dozens of other places we then had to fix.

Workaround

Replace the literal space with an explicit `{" "}` after every closing tag in any paragraph that contains an HTML entity:

```tsx An <Term name="x">foo</Term>{" "}is the smallest — really. ```

Applies to any paragraph containing `—`, `’`, `“`, `–`, etc. Easier in practice to apply the workaround uniformly to all closing tags in prose-heavy files.

Possibly related historical SWC issues

This pattern looks like a regression of (or sibling to) a long-standing SWC JSX whitespace issue cluster that was previously fixed:

  • swc-project/swc#11392 — "HTML Entities-encoded whitespace gets trimmed in JSX"
  • swc-project/swc#11520 — "Whitespace between variable and HTML entity gets removed"
  • swc-project/swc#11521 — fix(es/jsx): Preserve whitespace before HTML entities
  • swc-project/swc#11541 — "JSX removing leading whitespace in front of charCode"
  • swc-project/swc#11557 — fix(react): preserve first-line leading whitespace with entity JSX text

The historical fixes look like they targeted leading whitespace at the start of a JSX text expression. This case affects the space between an inline closing tag and the following word mid-expression when an entity is present, which may not be covered by the earlier fixes.

🤖 Generated with Claude Code

extent analysis

TL;DR

The issue can be worked around by replacing the literal space with an explicit {\" \"} after every closing tag in any paragraph that contains an HTML entity.

Guidance

  • Verify that the issue is specific to the Turbopack build process and Next.js version 16.2.4.
  • Check if the problem persists when using a different build tool or version.
  • Apply the provided workaround by adding an explicit space {\" \"} after closing tags in paragraphs with HTML entities.
  • Test the workaround in different scenarios to ensure it doesn't introduce new issues.

Example

// Before
<p>An <Term name="x">foo</Term> is the smallest &mdash; really.</p>

// After (with workaround)
<p>An <Term name="x">foo</Term>{" "}is the smallest &mdash; really.</p>

Notes

The issue seems to be related to a regression in SWC's JSX whitespace handling, and the provided workaround may not be the final solution. Further investigation and potential updates to SWC or Next.js may be necessary.

Recommendation

Apply the workaround by adding explicit spaces after closing tags in paragraphs with HTML entities, as it provides a temporary fix for the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING