Skip to content

Notes: Stream note loading progressively on large posts#80018

Open
adamsilverstein wants to merge 6 commits into
trunkfrom
fix/71668-notes-progressive-load
Open

Notes: Stream note loading progressively on large posts#80018
adamsilverstein wants to merge 6 commits into
trunkfrom
fix/71668-notes-progressive-load

Conversation

@adamsilverstein

@adamsilverstein adamsilverstein commented Jul 8, 2026

Copy link
Copy Markdown
Member

What?

Adds the core-data RECEIVE_INTERMEDIATE_RESULTS flag to the notes query in useNoteThreads, so notes stream into the collab sidebar page-by-page as they load instead of the sidebar blocking until the entire collection has been fetched.

Fixes #71668.

Why?

The collab sidebar fetches every note for a post in a single per_page: -1 query. Without the intermediate-results flag, the core-data resolver resolves that query in one shot and only populates the store once the full set has loaded, so the sidebar shows nothing until the last record arrives. On posts with hundreds or thousands of notes that is a long, blank wait.

How?

per_page: -1 combined with RECEIVE_INTERMEDIATE_RESULTS: true switches the resolver to its paginated branch: it fetches 100 records per page and dispatches receiveEntityRecords after each page. Because useEntityRecords is reactive, the sidebar re-renders as each page lands and notes appear progressively.

This is the same pattern already used by the hierarchical term selector (packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js). The flag is a Symbol, so it does not leak into the request URL or affect the query cache key.

This is the low-risk, incremental first step discussed in #71668. It does not attempt the larger "render top-level notes first, then replies" or lazy-load-on-expand redesigns, which remain worth pursuing for the full scaling story (see the issue discussion).

Testing Instructions

Setup: seed a post with many notes

The streaming only kicks in past 100 notes (the resolver pages at 100 per request), so the post needs 100+ notes. The easiest way to get there is @t-hamano's Notes Data Generator test plugin (dev sites only): install and activate it, open a post with a few blocks, and use its panel in the editor sidebar to generate notes from random users, content, and dates. Adding notes by hand across several blocks works too, just slower.

Verify progressive loading

  1. Reload the editor and open the notes sidebar ("All notes" in the top bar).
  2. Notes appear progressively as pages load, rather than all at once after a single blocking request. Throttling the connection in DevTools (e.g. "Slow 4G") makes the page-by-page fill-in easy to see.
  3. In the Network panel, filter for comments: you should see sequential ?...&type=note&...&per_page=100&page=1, page=2, ... requests instead of one per_page=-1 request.
  4. Confirm existing behavior (add, resolve, reopen, reply, delete, floating placement) is unchanged.

Automated test

test/e2e/specs/editor/various/block-notes-progressive-load.spec.js covers the streaming behavior directly: it seeds a post with 105 notes, holds the second page of the notes query via route interception, and asserts the first 100 threads render in the sidebar before the full set has loaded (then releases the request and asserts all 105 render). Without the flag the store only receives records once every page has resolved, so the test fails on trunk.

npm run test:e2e -- test/e2e/specs/editor/various/block-notes-progressive-load.spec.js

Alternatives considered

Discussed in #71668: _embed=children to fetch first-level replies in one query, and lazy-loading replies only when a thread is expanded. Both are stronger for the extreme "thousands of notes" case but require more work (and likely a small REST change for embedding). This PR ships the immediate win; those can follow.

The collab sidebar fetches every note for a post in a single
`per_page: -1` query and blocks rendering until the full set has
loaded. This does not scale to posts with hundreds or thousands of
notes.

Pair the query with the core-data RECEIVE_INTERMEDIATE_RESULTS flag so
the resolver streams the pages (100 records at a time) into the store as
they arrive, letting the sidebar render notes progressively instead of
waiting for the whole collection. This mirrors the pattern already used
by the hierarchical term selector.

Addresses #71668.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: jeffpaul <jeffpaul@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: TimothyBJacobs <timothyblynjacobs@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions Bot added the [Package] Editor /packages/editor label Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Size Change: +54 B (0%)

Total Size: 7.73 MB

📦 View Changed
Filename Size Change
build/scripts/editor/index.min.js 499 kB +54 B (+0.01%)

compressed-size-action

The notes query now streams pages via RECEIVE_INTERMEDIATE_RESULTS, so the
core-data resolver paginates the request itself with an explicit `page`
param instead of leaning on api-fetch's fetch-all middleware. The startup
request the preload specs snapshot therefore gains `&page=1`.

Update the expected route in the post-editor and site-editor preload
specs to match.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Flaky tests detected in 758f234.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/29759857390
📝 Reported issues:

@adamsilverstein
adamsilverstein requested a review from Mamaduka July 11, 2026 06:14
Seed a post with 105 notes, hold the second page of the notes query
via route interception, and assert the first 100 threads render in the
All notes sidebar before the full set has loaded, then release the
request and assert all 105 render. Without RECEIVE_INTERMEDIATE_RESULTS
the store only receives records once every page has resolved, so this
test fails when the flag is removed (verified locally red/green).
@adamsilverstein adamsilverstein added the [Type] Bug An existing feature does not function as intended label Jul 17, 2026
@adamsilverstein adamsilverstein self-assigned this Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Editor /packages/editor [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ensure notes feature scales to many notes

1 participant