Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Site Editor: Improve loading experience (v1) #42525

Closed
wants to merge 11 commits into from
Closed

Conversation

tyxla
Copy link
Member

@tyxla tyxla commented Jul 19, 2022

What?

This is an experiment - DO NOT MERGE!

This PR aims to experiment with Suspense, specifically with our useSuspenseSelect() implementation to load the site editor behind the scenes, and display it once it's finished loading.

Why?

We're aiming to find a way to improve the editor loading experience.

As @mtias says:

The end goal should be that things load like a "screenshot"; all fully loaded when you start interacting.

See #35503 for more details and motivation.

How?

We're essentially replacing a bunch of useSelect() with useSuspenseSelect, adding a Suspense boundary with a dummy loading screen, and some artificial delay to prevent from flickering.

This is obviously not landable in this version - we'd likely need a better and more selective approach to which useSelect to alter and which not.

Testing Instructions

  • Load the site editor and observe the loading experience.
  • Observe that at the time the fallback placeholder has been hidden, the editor has fully loaded.

Screenshots or screencast

Screen.Recording.2022-07-19.at.14.52.31.mov

@tyxla tyxla added [Status] In Progress Tracking issues with work in progress [Type] Experimental Experimental feature or API. [Package] Edit Site /packages/edit-site [Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") labels Jul 19, 2022
@tyxla tyxla self-assigned this Jul 19, 2022
@github-actions
Copy link

github-actions bot commented Jul 19, 2022

Size Change: +619 B (0%)

Total Size: 1.25 MB

Filename Size Change
build/block-editor/index.min.js 163 kB +244 B (0%)
build/block-editor/style-rtl.css 15.3 kB +70 B (0%)
build/block-editor/style.css 15.3 kB +70 B (0%)
build/block-library/index.min.js 190 kB +255 B (0%)
build/components/index.min.js 198 kB -49 B (0%)
build/components/style-rtl.css 11.5 kB -14 B (0%)
build/components/style.css 11.5 kB -12 B (0%)
build/data/index.min.js 8.09 kB +25 B (0%)
build/edit-post/index.min.js 30.7 kB +11 B (0%)
build/edit-site/index.min.js 57.7 kB +19 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 982 B
build/annotations/index.min.js 2.76 kB
build/api-fetch/index.min.js 2.26 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 475 B
build/block-directory/index.min.js 7.05 kB
build/block-directory/style-rtl.css 990 B
build/block-directory/style.css 991 B
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 126 B
build/block-library/blocks/audio/theme.css 126 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 84 B
build/block-library/blocks/avatar/style.css 84 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 482 B
build/block-library/blocks/button/editor.css 482 B
build/block-library/blocks/button/style-rtl.css 523 B
build/block-library/blocks/button/style.css 523 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 103 B
build/block-library/blocks/code/style.css 103 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 187 B
build/block-library/blocks/comment-template/style.css 185 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 834 B
build/block-library/blocks/comments/editor.css 832 B
build/block-library/blocks/comments/style-rtl.css 632 B
build/block-library/blocks/comments/style.css 630 B
build/block-library/blocks/cover/editor-rtl.css 605 B
build/block-library/blocks/cover/editor.css 607 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.55 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 126 B
build/block-library/blocks/embed/theme.css 126 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 346 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 948 B
build/block-library/blocks/gallery/editor.css 950 B
build/block-library/blocks/gallery/style-rtl.css 1.53 kB
build/block-library/blocks/gallery/style.css 1.53 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 337 B
build/block-library/blocks/group/editor.css 337 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 327 B
build/block-library/blocks/html/editor.css 329 B
build/block-library/blocks/image/editor-rtl.css 876 B
build/block-library/blocks/image/editor.css 873 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 B
build/block-library/blocks/image/theme-rtl.css 126 B
build/block-library/blocks/image/theme.css 126 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 463 B
build/block-library/blocks/latest-posts/style.css 462 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 705 B
build/block-library/blocks/navigation-link/editor.css 703 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation-submenu/view.min.js 423 B
build/block-library/blocks/navigation/editor-rtl.css 1.99 kB
build/block-library/blocks/navigation/editor.css 2 kB
build/block-library/blocks/navigation/style-rtl.css 2.17 kB
build/block-library/blocks/navigation/style.css 2.16 kB
build/block-library/blocks/navigation/view-modal.min.js 2.78 kB
build/block-library/blocks/navigation/view.min.js 443 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 363 B
build/block-library/blocks/page-list/editor.css 363 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 260 B
build/block-library/blocks/paragraph/style.css 260 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 493 B
build/block-library/blocks/post-comments-form/style.css 493 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 547 B
build/block-library/blocks/post-featured-image/editor.css 545 B
build/block-library/blocks/post-featured-image/style-rtl.css 315 B
build/block-library/blocks/post-featured-image/style.css 315 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 282 B
build/block-library/blocks/query-pagination/style.css 278 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 439 B
build/block-library/blocks/query/editor.css 439 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 464 B
build/block-library/blocks/shortcode/editor.css 464 B
build/block-library/blocks/site-logo/editor-rtl.css 488 B
build/block-library/blocks/site-logo/editor.css 488 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 322 B
build/block-library/blocks/spacer/editor.css 322 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 494 B
build/block-library/blocks/table/editor.css 494 B
build/block-library/blocks/table/style-rtl.css 611 B
build/block-library/blocks/table/style.css 609 B
build/block-library/blocks/table/theme-rtl.css 190 B
build/block-library/blocks/table/theme.css 190 B
build/block-library/blocks/tag-cloud/style-rtl.css 239 B
build/block-library/blocks/tag-cloud/style.css 239 B
build/block-library/blocks/template-part/editor-rtl.css 235 B
build/block-library/blocks/template-part/editor.css 235 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 561 B
build/block-library/blocks/video/editor.css 563 B
build/block-library/blocks/video/style-rtl.css 174 B
build/block-library/blocks/video/style.css 174 B
build/block-library/blocks/video/theme-rtl.css 126 B
build/block-library/blocks/video/theme.css 126 B
build/block-library/common-rtl.css 1.02 kB
build/block-library/common.css 1.02 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11 kB
build/block-library/editor.css 11 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.2 kB
build/block-library/style.css 12.2 kB
build/block-library/theme-rtl.css 719 B
build/block-library/theme.css 722 B
build/block-serialization-default-parser/index.min.js 1.1 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 49.6 kB
build/compose/index.min.js 12 kB
build/core-data/index.min.js 15.5 kB
build/customize-widgets/index.min.js 11.3 kB
build/customize-widgets/style-rtl.css 1.38 kB
build/customize-widgets/style.css 1.38 kB
build/data-controls/index.min.js 653 B
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 507 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.7 kB
build/edit-navigation/index.min.js 16 kB
build/edit-navigation/style-rtl.css 3.99 kB
build/edit-navigation/style.css 4 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/edit-post/style-rtl.css 6.94 kB
build/edit-post/style.css 6.94 kB
build/edit-site/style-rtl.css 8.3 kB
build/edit-site/style.css 8.28 kB
build/edit-widgets/index.min.js 16.5 kB
build/edit-widgets/style-rtl.css 4.34 kB
build/edit-widgets/style.css 4.34 kB
build/editor/index.min.js 41.7 kB
build/editor/style-rtl.css 3.66 kB
build/editor/style.css 3.65 kB
build/element/index.min.js 4.68 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 6.75 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.64 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.77 kB
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.78 kB
build/keycodes/index.min.js 1.81 kB
build/list-reusable-blocks/index.min.js 1.74 kB
build/list-reusable-blocks/style-rtl.css 835 B
build/list-reusable-blocks/style.css 835 B
build/media-utils/index.min.js 2.93 kB
build/notices/index.min.js 953 B
build/nux/index.min.js 2.05 kB
build/nux/style-rtl.css 732 B
build/nux/style.css 728 B
build/plugins/index.min.js 1.94 kB
build/preferences-persistence/index.min.js 2.22 kB
build/preferences/index.min.js 1.3 kB
build/primitives/index.min.js 933 B
build/priority-queue/index.min.js 612 B
build/react-i18n/index.min.js 696 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.74 kB
build/reusable-blocks/index.min.js 2.21 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.4 kB
build/server-side-render/index.min.js 1.61 kB
build/shortcode/index.min.js 1.53 kB
build/style-engine/index.min.js 1.53 kB
build/token-list/index.min.js 644 B
build/url/index.min.js 3.61 kB
build/vendors/react-dom.min.js 38.5 kB
build/vendors/react.min.js 4.34 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.19 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.19 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@tyxla tyxla mentioned this pull request Jul 19, 2022
3 tasks
@jameskoster
Copy link
Contributor

Very excited to see some work on this! :)

I'm unable to explain why, but I am seeing small flashes of content behind the loader:

load.mp4

Let me know how I can help debug that.

It's generally not recommended to use a logo for a loading graphic as it can create a negative association with the brand. I'm not sure how much truth there is to that, but it might be best to use something like the Spinner component for now anyways? Hopefully in the future we can use a determinate progress bar.

@jameskoster jameskoster linked an issue Jul 20, 2022 that may be closed by this pull request
3 tasks
@mtias mtias added the [Type] Performance Related to performance efforts label Jul 29, 2022
@mtias
Copy link
Member

mtias commented Jul 29, 2022

This is great, thanks for working on it! It'll have a significant impact on the perception of the editor and the fragility waterfalls tend to signal.

@gziolo
Copy link
Member

gziolo commented Aug 2, 2022

@tyxla, impressive work so far. It shows the power of new React APIs ❤️

Have you experimented with giving priorities to suspense calls so we could render some more critical chunks of the page faster?

@tyxla
Copy link
Member Author

tyxla commented Aug 3, 2022

Thanks for your feedback everyone!

I'm unable to explain why, but I am seeing small flashes of content behind the loader:

Yes, those are easy to reproduce with CPU throttling. Those flashes will generally occur in periods when there are no async requests in flight, and our suspense boundary "thinks" that loading has finished, thus no longer presents us with the fallback. However, if this happens in the middle of the loading, when a new request is issued shortly, the fallback is displayed again. This is a downside of the lack of control we have over the current mechanism, and demonstrates the need to create a centralized mechanism that allows for better granularity and control (cc @griffbrad as we've been discussing that before). I've also demonstrated this in a simpler and isolated way in #42188. Alternatively, we could hack around this by debouncing the rendering with a small delay, however there's no guarantee it'll cover the flickering, because how short (or how long) a period without requests in the middle of the loading experience can vary greatly.

It's generally not recommended to use a logo for a loading graphic as it can create a negative association with the brand. I'm not sure how much truth there is to that, but it might be best to use something like the Spinner component for now anyways?

Of course, this was just for experimentation and demonstration purposes and never meant to land as-is. I've replaced the logo with a spinner component in the meantime if that helps.

Have you experimented with giving priorities to suspense calls so we could render some more critical chunks of the page faster?

No, I haven't. Actually, I'm not sure this makes a lot of sense for a few reasons:

  • As per the discussion in this issue, we'd like to display the page load "as a screenshot", not load section by section. IIUC, that means that we don't load and display certain parts of the page faster; we display it all at the same time, when everything has loaded and is ready for display.
  • How would you decide what to prioritize? To ensure everything will have loaded when finally displaying the editor, we need to asynchronize all requests. At the same time, we don't know what data is going to be necessary, because some of the components that will issue requests haven't still been mounted. Also the data is dynamic, and may (or not) contain various pieces, where priority may vary between different themes and templates. Does that infer the creation of a mechanism to point out the priority? Maybe, but it would add a lot of complexity and I'd really like us to be able to improve the loading experience without requiring extra APIs to be used.

Of course, I might be misunderstanding, so let me know if that's the case.

@mtias
Copy link
Member

mtias commented Aug 3, 2022

It's generally not recommended to use a logo for a loading graphic as it can create a negative association with the brand.

@jameskoster I think this is kind of nonsense :D

As per the discussion in this issue, we'd like to display the page load "as a screenshot", not load section by section. IIUC, that means that we don't load and display certain parts of the page faster; we display it all at the same time, when everything has loaded and is ready for display.

Correct. We might want to identify some structural parts like editor header and navigation bits (W menu) first and display those as soon as ready so you can go elsewhere and not wait for everything to load before navigating.

@tyxla
Copy link
Member Author

tyxla commented Aug 3, 2022

We might want to identify some structural parts like editor header and navigation bits (W menu) first and display those as soon as ready so you can go elsewhere and not wait for everything to load before navigating.

Oh, interesting. I'd love to see some sort of a raw preview or demo of how you envision this working so I could tinker with it.

@jameskoster
Copy link
Contributor

@jameskoster I think this is kind of nonsense :D

Maybe :D

I'd love to see some sort of a raw preview or demo

A very rough idea:

load

Note how the W button finishes loading first, then the top bar, then the canvas.

I do wonder about detaching the top bar / canvas though. What happens if you open the Inspector before the canvas is loaded? Or try to add a block via the Inserter? I'm not sure there's any real benefit to loading those tools before the canvas. It might be better to simply load those together. An alternative:

load2

@tyxla
Copy link
Member Author

tyxla commented Aug 5, 2022

Thanks for the demo!

At a first glance, this would be a bit troublesome with the current interface skeleton structure. Let me clarify.

Currently, we have this rough structure for the site editor:

  • Site Editor app
    • Suspense boundary
      • Editor
        • Interface Skeleton
          • Header
          • Content
          • Sidebar

To achieve what's suggested on the video, we'd have:

  • Site Editor app
    • Editor
      • Interface Skeleton
        • Header
          • Suspense boundary
        • Content
          • Suspense boundary
        • Sidebar
          • Suspense boundary

However, for this to work, we need to have no async suspense select calls outside of suspense boundaries. This is tough, because the Editor and the Header, for example, will share some data dependencies, and we can't (and shouldn't) query those data dependencies both ways.

To be able to do that, we'd need to structurally pull out the header from the interface skeleton, so it would be outside of the Editor, in order for the Editor and the Header to have separate suspense boundaries.

We should be able to get around this with useTransition(), however, this feature is available from React 18, and AFAIK this requires us to also upgrade to React Native 0.69 (https://reactnative.dev/blog/2022/06/21/version-069) but we're still stuck on an older version.

That being said, I wonder what still prevents us from upgrading to React 18 and if we can push that forward. cc @gziolo

@Mamaduka
Copy link
Member

Mamaduka commented Aug 5, 2022

However, for this to work, we need to have no async suspense select calls outside of suspense boundaries.

We also probably won't need to use suspense select everywhere. Maybe start with selectors that fetch entities from the server.

@mtias
Copy link
Member

mtias commented Aug 16, 2022

@tyxla @jameskoster we don't need anything too complicated at first here. Rendering a very basic skeleton (without pulsing elements) just outlining the header and site icon slot is fine. More important to get the foundation in so we can refine.

@jameskoster
Copy link
Contributor

Here's this PR as things stand:

loader

It's already in a decent spot imo, and potentially mergeable assuming subsequent refinements. If it's easy to try, we could use a slightly larger spinner, and print a very simple indication of where the site logo / top bar will appear:

Screenshot 2022-08-17 at 09 48 27

@mtias
Copy link
Member

mtias commented Aug 17, 2022

Yep, that last one is what I had in mind

@jameskoster
Copy link
Contributor

One issue to fix: The loading state should (for now) only be displayed when you first open the Site Editor. At the moment I noticed it pops up when you perform actions like:

  • Click 'Replace' in the Template Part toolbar
  • Open Global Styles
  • Switch to the Templates list (shouldn't this be included in the initial load?)

@tyxla
Copy link
Member Author

tyxla commented Aug 17, 2022

Thanks for the feedback everyone!

I've done some changes and here's how it looks now:

Screen.Recording.2022-08-17.at.15.25.19.mov

Basically, the header is now outside and since it generally loads quickly and doesn't have a ton of dependencies, I don't see a reason to add suspense to it at this time. We could, of course, do it if we find a good use case that makes it load slowly.

Beyond that, I've moved the boundary for the content and since will take more time to load, we'll see the spinner. I've increased the size of that a bit, just to demonstrate how things look that way.

Let me know what you think!

The loading state should (for now) only be displayed when you first open the Site Editor

I'd be happy to tinker with that, but was curious - what happens when we start interacting with the app and new data gets requested? Is it going to work just like it did before - with placeholders and spinners all over the place?

@ndiego
Copy link
Member

ndiego commented Sep 21, 2022

Hello all, can I get a status update on this one? Given that 6.1 Beta 1 has been released, can I remove this PR from the 6.1 Project Board and remove the Backport Label? @mtias @tyxla

@jsnajdr
Copy link
Member

jsnajdr commented Sep 22, 2022

@ndiego This work is unfortunately still very experimental and not likely to be in 6.1. You can safely remove it from any 6.1 project tracking stuff.

@ndiego ndiego removed the Backport to WP Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Sep 26, 2022
@ndiego
Copy link
Member

ndiego commented Sep 26, 2022

Thanks for the clarification @jsnajdr, removing the backport label.

@tyxla
Copy link
Member Author

tyxla commented Sep 26, 2022

One major downside is that all blocks, even the 3rd party ones that we don't control, need to use Suspense consistently. Otherwise, when classic and Suspense data loading is mixed together, the loading indicator will flicker.

Indeed. One way around this would be having a mechanism to always decide on runtime whether to use useSelect or useSuspenseSelect, and going with that for all usages that use useSelect as well. That way plugins would also benefit from that improvement. I still think it's worth experimenting with that. It might solve some of the problems created by the current approach we're exploring here.

@youknowriad
Copy link
Contributor

Another feature I've tinkered with is displaying the loading placeholder only on initial loading, as suggested by @jameskoster and @mtias. You can see in the preview that the image and page list no longer cause the loading screen to appear. Admittedly, it's in a hacky state, because with Suspense we don't have the luxury to have it display only on the first load; Suspense doesn't care whether it's the first or last load. So this requires some hacks, including runtime interchanging of useSuspenseSelect to work like useSelect after loading, and some artificial delay after loading to conceal the rerender flicker of elements that occurs when we re-render the editor without the suspense boundary.

After reading a bit on the internet (as this seemed like a common issue people could face), it seems the solution for folks here is to actually use "startTransition" to avoid showing the fallbacks. https://reactjs.org/docs/react-api.html#starttransition

So is it possible to have this:

  • useSuspenseSelect only for the important blocks we want to include in the loading fallback: template parts, navigation block as a start maybe, potentially images. (I don't think we necessarily need all blocks and third-party blocks to suspend rendering by default)
  • wrap all our editors with Suspense (to avoid breakage in the editors)
  • Add startTransition around the changes that we don't want to impact the loading state with (like setAttributes maybe)

What would be the issues with such approach?

@youknowriad
Copy link
Contributor

(I guess we need to wait for React 18 for startTransition to be available)

@tyxla
Copy link
Member Author

tyxla commented Sep 27, 2022

I've been hoping to use startTransition and useTransition here, and that's been one of my motivators to push forward to migrate all the remaining enzyme tests. The PR to remove enzyme is up now, by the way:

Which means the upgrade to React 18 will be unblocked very soon and we can reattempt it.

@mtias
Copy link
Member

mtias commented Nov 1, 2022

Where are we on the update to 18 blocker?

@Mamaduka
Copy link
Member

Mamaduka commented Nov 1, 2022

Here's the latest PR by @jsnajdr - #45235.

@tyxla
Copy link
Member Author

tyxla commented Dec 13, 2022

Now that we're ready with upgrading the dependencies in #45235, we're working to enable concurrent rendering features in #46467, which is the last blocker before we're able to experiment with useSyncExternalStore and startTransition / useTransition.

@jsnajdr
Copy link
Member

jsnajdr commented Jan 18, 2023

Add startTransition around the changes that we don't want to impact the loading state with (like setAttributes maybe)

startTransition doesn't affect updates done by useSyncExternalStore. These updates will always be sync (queueMicrotask). In code like:

const { setAttributes } = useDispatch();
startTransition( () => {
  setAttributes( newAttributes );
);

the startTransition code will be a noop: it will just synchronously execute the callback and won't do anything else.

I don't fully understand the problem we hope to solve with startTransition -- what do we want to delay and when? Then we can look for solutions.

@tyxla
Copy link
Member Author

tyxla commented Jan 20, 2023

Some context on what @jsnajdr talks about above can be found in this discussion: reactwg/react-18#86

Particularly this:

Updates triggered by a store change will always be synchronous, even when wrapped in startTransition

I don't think we considered experimenting with startTransition together with useSyncExternalStore in the first place. In any case, now that we use useSyncExternalStore in both useSelect and useSuspenseSelect, we'll need to drop the idea of using the transition API for managing the loading state, unless I'm misunderstanding something.

I'm starting to doubt if with suspense we will be able to solve this problem altogether. The issue there is all the third-party blocks and plugins which will not be suspending rendering in their components. We can't realistically ask for every plugin to suspend, therefore, we might need an alternative implementation.

This brings me back to an alternative solution we discussed earlier in the summer with @jsnajdr - basically implementing a custom wrapper system that relies on the status of the resolvers we're interested in and based on that, rendering either the placeholders or the actual component.

@jsnajdr @youknowriad do you have any additional thoughts or ideas on moving forward with this one?

@youknowriad
Copy link
Contributor

I'm starting to doubt if with suspense we will be able to solve this problem altogether. The issue there is all the third-party blocks and plugins which will not be suspending rendering in their components. We can't realistically ask for every plugin to suspend, therefore, we might need an alternative implementation.

Personally, I don't see this as a blocker at all. The important thing is that we get "some loaders" absorbed by the suspense provider, not all of them. Blocks like reusable blocks, template parts and navigation blocks are the most important one here, maybe images as well but if there's some blocks including third-party blocks that load asynchronously (have their own loaders), that's totally fine.

@mtias
Copy link
Member

mtias commented Jan 23, 2023

I agree — we don't need to absorb everything for this to succeed in addressing the main problem. It's ok to have a few things here and there waterfall loading; it's not ok for the main pieces of the interface and fundamental building blocks to load uncoordinated. Let's please start small and make the initial experience better than what it is today while we figure out the more difficult parts and how they integrate with the block API for other authors to take advantage of.

@tyxla
Copy link
Member Author

tyxla commented Jan 31, 2023

Thanks for the feedback, everyone!

I'm working on another experiment today - similar to what we had here, but a bit simpler. My idea is to still use suspense but to try declaring dependencies per the suspense boundary. That will not only give us the required granularity to add multiple suspense boundaries (header, content, footer) but will also allow us to have the flexibility and add/edit data dependencies for each suspense boundary as needed.

PR coming soon.

@tyxla
Copy link
Member Author

tyxla commented Jan 31, 2023

Here's the PR of this other experiment I was referencing above: #47612

@tyxla tyxla changed the title Try: Use Suspense for site editor Site Editor: Improve loading experience (v1) May 1, 2023
@tyxla
Copy link
Member Author

tyxla commented May 1, 2023

I've started working on a v3, which I prefer the most from the 3 approaches: #50222.

@tyxla
Copy link
Member Author

tyxla commented May 8, 2023

Since #50222 is much more reliable and flexible, I'm closing this one in its favor.

@tyxla tyxla closed this May 8, 2023
@tyxla tyxla deleted the try/suspense-site-edit branch May 8, 2023 12:49
@priethor priethor removed the [Status] In Progress Tracking issues with work in progress label May 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Package] Edit Site /packages/edit-site [Type] Experimental Experimental feature or API. [Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refine the Site Editor loading state
10 participants