Skip to content

Conversation

@Bobadu
Copy link

@Bobadu Bobadu commented Oct 24, 2025

Summary

Fixes #34966

When using renderToPipeableStream with onAllReady callback (recommended for SEO crawlers), React was injecting streaming scripts and hidden HTML elements even when all content was fully loaded. This negatively impacted SEO scores.

Changes

  • Added check for allPendingTasks === 0 before outlining Suspense boundaries
  • Skip blocking shell instructions when all tasks are complete
  • Don't emit <template> tag when rendering is complete
  • Added comprehensive tests to verify the fix

Test Plan

  • Added new test file ReactDOMFizzServerNodeIssue34966-test.js with tests for both onAllReady and onShellReady modes
  • Updated existing snapshots in test files
  • All 190 tests pass successfully

Before:

<div hidden id="S:0"><button>Test</button></div>
<script>$RB=[];$RV=function(a){...};</script>
<template id="_R_"></template>
<link rel="expect" href="#_R_" blocking="render"/>

After:

<!DOCTYPE html>
<html><head></head><body><button>Test</button></body></html>

Clean HTML with no streaming scripts, hidden elements, or template tags.

How did you test this change?

  • Added specific tests for the reported issue
  • Verified streaming still works correctly in onShellReady mode
  • All existing tests pass

Fixes facebook#34966

When using renderToPipeableStream with onAllReady callback, React no longer
emits streaming scripts and hidden elements when all pending tasks are complete.
This improves SEO by providing clean HTML output for crawlers.

- Added check for allPendingTasks === 0 before outlining boundaries
- Skip blocking shell instructions when everything is ready
- Don't emit template tag when isComplete is true
- Added tests to verify fix
@meta-cla
Copy link

meta-cla bot commented Oct 24, 2025

Hi @Bobadu!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@meta-cla meta-cla bot added the CLA Signed label Oct 24, 2025
@meta-cla
Copy link

meta-cla bot commented Oct 24, 2025

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

VedantKh added a commit to VedantKh/react that referenced this pull request Oct 25, 2025
…ng onAllReady

This fix addresses issue facebook#34966 where renderToPipeableStream with the onAllReady
callback incorrectly injected streaming scripts and hidden HTML elements even when
all content was fully loaded.

Changes:
- Modified flushSegment in ReactFizzServer.js to check allPendingTasks > 0 before
  outlining Suspense boundaries
- Modified flushCompletedQueues in ReactFizzServer.js to skip blocking shell
  instructions when allPendingTasks === 0
- Modified writeCompletedRoot in ReactFizzConfigDOM.js to only emit template tag
  when not complete
- Updated test snapshots to reflect new behavior (no streaming instructions when
  using onAllReady)
- Added new test file ReactDOMFizzServerNodeIssue34966-test.js to verify the fix

This prevents unnecessary streaming scripts and hidden elements from being injected
when using onAllReady for SEO crawlers, improving SEO scores.

Co-Authored-By: Vedant Khanna <[email protected]>
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.

Bug: [19.2.0] Streaming scripts injected in onAllReady in renderToPipeableStream and prerenderToNodeStream

1 participant