Skip to content

Replace turbo-combine-reducers with combineReducers from Redux - #54606

Merged
jsnajdr merged 8 commits into
trunkfrom
remove/turbo-combine-reducers
Sep 29, 2023
Merged

Replace turbo-combine-reducers with combineReducers from Redux#54606
jsnajdr merged 8 commits into
trunkfrom
remove/turbo-combine-reducers

Conversation

@jsnajdr

@jsnajdr jsnajdr commented Sep 19, 2023

Copy link
Copy Markdown
Member

This is still an experiment, I'm opening a PR mainly to get performance test results.

There are two major problems with combineReducers in Redux.

First, it doesn't allow slice reducers to ever return undefined state. undefined means uninitialized and every reducer is supposed to return an "initialized" inital state when undefined state is passed. We have many reducers that use undefined, and this PR has to modify them to use null instead. Otherwise, combineReducers will throw an exception and the app will crash. The prohibition on undefined will be a breaking change that we probably can't afford to do.

Second, it logs a warning when the combined reducer function is called with a state that contains unknown keys, with no reducer for them. For example, consider combining foo and bar reducers with combineReducers( { foo, bar } ). Then, when you pass an object with shape { foo, bar, baz } as state, combineReducers doesn't like the baz field, because there is no sub-reducer to pass it to. The warning is:

Unexpected key "baz" found in preloadedState argument passed to createStore.
Expected to find one of the known reducer keys instead: "foo", "bar".
Unexpected keys will be ignored.

The core/blocks store very often uses an enhancer pattern that leads to these "unexpected key" warnings:

function withIgnoredBlockChange( reducer ) {
  return ( state, action ) => {
    const nextState = reducer( state, action );
    if ( nextState !== state ) {
      nextState.isIgnoredChange = action.type === 'RECEIVE_BLOCKS';
    }
    return nextState;
  };
}

This enhancer calls the inner reducer and then adds the isIgnoredChange field to the existing ones. If the inner reducer is a result of combineReducers, it will complain about the unknown key. Although everything works, there's nothing really wrong with this pattern.

For these two reasons, we'll probably have to write our own version of combineReducers.

Fixes #42513.

@jsnajdr jsnajdr added [Type] Performance Related to performance efforts [Package] Data /packages/data [Type] Security Related to security concerns or efforts labels Sep 19, 2023
@jsnajdr
jsnajdr requested a review from tyxla September 19, 2023 14:10
@jsnajdr jsnajdr self-assigned this Sep 19, 2023
}
setIsListViewOpened( showListViewByDefault );
setEditorCanvasContainerView( undefined );
setEditorCanvasContainerView( null );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that changing all reducers to use undefined instead of a null is likely to end up being a regression, since some of the reducers might make a strict differentiation between the null and undefined. This is especially valid for custom @wordpress/data stores that are already using undefined as a valid value somewhere in their reducer trees.

With that in mind, I think we might have to consider adding our own wrapper around the Redux combineReducers that handles undefined in a way that allows supporting it as a valid value.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsnajdr what are your thoughts on the above comment?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, after I abandoned the idea to use combineReducers from Redux and created my own version instead, undefined state is no longer a concern. And neither are extra keys in state. @wordpress/data reducers can continue to use them without any change.

However, this PR still contains changes to Gutenberg's data stores that remove undefined state and replace it with null. They're no longer strictly needed, but still seem to me like a good code quality improvement.

But these changes are not worth doing if they introduce any backward compatibility issues for the existing Gutenberg stores. But are there any? And if there are, can they be solved?

For example, the setEditorCanvasContainerView( undefined ) call no longer works and has to be changed to setEditorCanvasContainerView( null ). But that can be easily avoided by defaulting the action parameter to null: ( view = null ) => .... I haven't 100% verified this yet, I only know that unit and e2e tests are green.

@github-actions

github-actions Bot commented Sep 22, 2023

Copy link
Copy Markdown

Size Change: +24 B (0%)

Total Size: 1.62 MB

Filename Size Change
build/block-editor/index.min.js 218 kB +82 B (0%)
build/block-library/blocks/image/style-rtl.css 1.4 kB -18 B (-1%)
build/block-library/blocks/image/style.css 1.39 kB -18 B (-1%)
build/block-library/blocks/image/view.min.js 1.83 kB +2 B (0%)
build/block-library/blocks/navigation-link/style-rtl.css 103 B -12 B (-10%) 👏
build/block-library/blocks/navigation-link/style.css 103 B -12 B (-10%) 👏
build/block-library/index.min.js 207 kB -4 B (0%)
build/block-library/style-rtl.css 14 kB -16 B (0%)
build/block-library/style.css 14 kB -16 B (0%)
build/components/index.min.js 248 kB +6 B (0%)
build/components/style-rtl.css 11.8 kB +8 B (0%)
build/components/style.css 11.8 kB +11 B (0%)
build/core-data/index.min.js 70.5 kB +3 B (0%)
build/data/index.min.js 8.78 kB -93 B (-1%)
build/edit-site/index.min.js 185 kB +26 B (0%)
build/edit-site/style-rtl.css 14 kB +37 B (0%)
build/edit-site/style.css 14 kB +38 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 964 B
build/annotations/index.min.js 2.71 kB
build/api-fetch/index.min.js 2.29 kB
build/autop/index.min.js 2.11 kB
build/blob/index.min.js 461 B
build/block-directory/index.min.js 7.07 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.28 kB
build/block-editor/content.css 4.27 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/style-rtl.css 15.6 kB
build/block-editor/style.css 15.6 kB
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 90 B
build/block-library/blocks/archives/style.css 90 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 138 B
build/block-library/blocks/audio/theme.css 138 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 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 633 B
build/block-library/blocks/button/style.css 632 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 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 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 121 B
build/block-library/blocks/code/style.css 121 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 421 B
build/block-library/blocks/columns/style.css 421 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 199 B
build/block-library/blocks/comment-template/style.css 198 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 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 647 B
build/block-library/blocks/cover/editor.css 650 B
build/block-library/blocks/cover/style-rtl.css 1.7 kB
build/block-library/blocks/cover/style.css 1.69 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 98 B
build/block-library/blocks/details/style.css 98 B
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 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 316 B
build/block-library/blocks/file/editor.css 316 B
build/block-library/blocks/file/style-rtl.css 311 B
build/block-library/blocks/file/style.css 312 B
build/block-library/blocks/file/view.min.js 321 B
build/block-library/blocks/footnotes/style-rtl.css 201 B
build/block-library/blocks/footnotes/style.css 199 B
build/block-library/blocks/freeform/editor-rtl.css 2.61 kB
build/block-library/blocks/freeform/editor.css 2.61 kB
build/block-library/blocks/gallery/editor-rtl.css 957 B
build/block-library/blocks/gallery/editor.css 962 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 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 189 B
build/block-library/blocks/heading/style.css 189 B
build/block-library/blocks/html/editor-rtl.css 340 B
build/block-library/blocks/html/editor.css 341 B
build/block-library/blocks/image/editor-rtl.css 834 B
build/block-library/blocks/image/editor.css 833 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 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 478 B
build/block-library/blocks/latest-posts/style.css 478 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 505 B
build/block-library/blocks/media-text/style.css 503 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 671 B
build/block-library/blocks/navigation-link/editor.css 672 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.26 kB
build/block-library/blocks/navigation/editor.css 2.26 kB
build/block-library/blocks/navigation/style-rtl.css 2.26 kB
build/block-library/blocks/navigation/style.css 2.25 kB
build/block-library/blocks/navigation/view.min.js 1.01 kB
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 401 B
build/block-library/blocks/page-list/editor.css 401 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 235 B
build/block-library/blocks/paragraph/editor.css 235 B
build/block-library/blocks/paragraph/style-rtl.css 335 B
build/block-library/blocks/paragraph/style.css 335 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 508 B
build/block-library/blocks/post-comments-form/style.css 508 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 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 588 B
build/block-library/blocks/post-featured-image/editor.css 586 B
build/block-library/blocks/post-featured-image/style-rtl.css 322 B
build/block-library/blocks/post-featured-image/style.css 322 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 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 314 B
build/block-library/blocks/post-template/style.css 314 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 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 125 B
build/block-library/blocks/preformatted/style.css 125 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 335 B
build/block-library/blocks/pullquote/style.css 335 B
build/block-library/blocks/pullquote/theme-rtl.css 168 B
build/block-library/blocks/pullquote/theme.css 168 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 288 B
build/block-library/blocks/query-pagination/style.css 284 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 486 B
build/block-library/blocks/query/editor.css 486 B
build/block-library/blocks/query/style-rtl.css 375 B
build/block-library/blocks/query/style.css 372 B
build/block-library/blocks/query/view.min.js 609 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 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 149 B
build/block-library/blocks/rss/editor.css 149 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 184 B
build/block-library/blocks/search/editor.css 184 B
build/block-library/blocks/search/style-rtl.css 613 B
build/block-library/blocks/search/style.css 613 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/search/view.min.js 471 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 329 B
build/block-library/blocks/shortcode/editor.css 329 B
build/block-library/blocks/site-logo/editor-rtl.css 760 B
build/block-library/blocks/site-logo/editor.css 760 B
build/block-library/blocks/site-logo/style-rtl.css 204 B
build/block-library/blocks/site-logo/style.css 204 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 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 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 682 B
build/block-library/blocks/social-links/editor.css 681 B
build/block-library/blocks/social-links/style-rtl.css 1.45 kB
build/block-library/blocks/social-links/style.css 1.45 kB
build/block-library/blocks/spacer/editor-rtl.css 359 B
build/block-library/blocks/spacer/editor.css 359 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 432 B
build/block-library/blocks/table/editor.css 432 B
build/block-library/blocks/table/style-rtl.css 646 B
build/block-library/blocks/table/style.css 645 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 403 B
build/block-library/blocks/template-part/editor.css 403 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/term-description/style-rtl.css 111 B
build/block-library/blocks/term-description/style.css 111 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 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 191 B
build/block-library/blocks/video/style.css 191 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 12.2 kB
build/block-library/editor.css 12.2 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/theme-rtl.css 700 B
build/block-library/theme.css 705 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.5 kB
build/commands/index.min.js 15.5 kB
build/commands/style-rtl.css 947 B
build/commands/style.css 942 B
build/compose/index.min.js 12.7 kB
build/core-commands/index.min.js 2.72 kB
build/customize-widgets/index.min.js 12 kB
build/customize-widgets/style-rtl.css 1.51 kB
build/customize-widgets/style.css 1.5 kB
build/data-controls/index.min.js 651 B
build/date/index.min.js 17.9 kB
build/deprecated/index.min.js 462 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.68 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 35.7 kB
build/edit-post/style-rtl.css 7.92 kB
build/edit-post/style.css 7.91 kB
build/edit-widgets/index.min.js 17 kB
build/edit-widgets/style-rtl.css 4.84 kB
build/edit-widgets/style.css 4.84 kB
build/editor/index.min.js 45.9 kB
build/editor/style-rtl.css 3.58 kB
build/editor/style.css 3.58 kB
build/element/index.min.js 4.87 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.79 kB
build/format-library/style-rtl.css 577 B
build/format-library/style.css 577 B
build/hooks/index.min.js 1.57 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.61 kB
build/interactivity/index.min.js 11.4 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.76 kB
build/keycodes/index.min.js 1.9 kB
build/list-reusable-blocks/index.min.js 2.21 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.92 kB
build/notices/index.min.js 964 B
build/nux/index.min.js 2.01 kB
build/nux/style-rtl.css 775 B
build/nux/style.css 771 B
build/patterns/index.min.js 3.57 kB
build/patterns/style-rtl.css 325 B
build/patterns/style.css 325 B
build/plugins/index.min.js 1.81 kB
build/preferences-persistence/index.min.js 1.85 kB
build/preferences/index.min.js 1.26 kB
build/primitives/index.min.js 994 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 972 B
build/react-i18n/index.min.js 631 B
build/react-refresh-entry/index.min.js 9.46 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.71 kB
build/reusable-blocks/index.min.js 2.73 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 10.2 kB
build/router/index.min.js 1.79 kB
build/server-side-render/index.min.js 1.96 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 1.98 kB
build/token-list/index.min.js 587 B
build/url/index.min.js 3.84 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 967 B
build/warning/index.min.js 259 B
build/widgets/index.min.js 7.18 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

@jsnajdr

jsnajdr commented Sep 22, 2023

Copy link
Copy Markdown
Member Author

Here are performance tests results. I don't see any significant regressions. Some tasks are faster, some are slower, and my intuitive guess is that none of them is outside the random fluctuation threshold.

post-editor
┌──────────────────────┬──────────────────────────────────────────┬───────────────┐
│       (index)        │ 6a0c6c625075126721a3e22cbb79fad3b54755fd │     trunk     │
├──────────────────────┼──────────────────────────────────────────┼───────────────┤
│    serverResponse    │               '337.35 ms'                │  '329.4 ms'   │
│      firstPaint      │                '610.9 ms'                │  '590.65 ms'  │
│   domContentLoaded   │               '1295.25 ms'               │ '1278.75 ms'  │
│        loaded        │               '1296.45 ms'               │  '1279.8 ms'  │
│ firstContentfulPaint │               '2296.75 ms'               │ '2309.25 ms'  │
│      firstBlock      │              '15015.75 ms'               │ '15173.65 ms' │
│         type         │                '67.38 ms'                │  '72.98 ms'   │
│       minType        │                '60.84 ms'                │  '68.72 ms'   │
│       maxType        │                '78.58 ms'                │  '92.13 ms'   │
│    typeContainer     │                '22.43 ms'                │  '27.19 ms'   │
│   minTypeContainer   │                '19.16 ms'                │  '20.36 ms'   │
│   maxTypeContainer   │                '27.54 ms'                │  '35.26 ms'   │
│        focus         │               '124.28 ms'                │  '96.36 ms'   │
│       minFocus       │               '112.19 ms'                │  '84.35 ms'   │
│       maxFocus       │               '141.69 ms'                │  '130.34 ms'  │
│     inserterOpen     │                '40.31 ms'                │  '47.15 ms'   │
│   minInserterOpen    │                '37.38 ms'                │  '35.43 ms'   │
│   maxInserterOpen    │                '44.13 ms'                │  '122.86 ms'  │
│    inserterSearch    │                 '9.1 ms'                 │   '9.55 ms'   │
│  minInserterSearch   │                '8.15 ms'                 │   '8.3 ms'    │
│  maxInserterSearch   │                '10.36 ms'                │  '12.17 ms'   │
│    inserterHover     │                '56.86 ms'                │  '53.67 ms'   │
│   minInserterHover   │                '50.58 ms'                │  '48.04 ms'   │
│   maxInserterHover   │                '62.61 ms'                │  '60.66 ms'   │
│     listViewOpen     │               '214.57 ms'                │  '214.13 ms'  │
│   minListViewOpen    │               '200.63 ms'                │  '193.45 ms'  │
│   maxListViewOpen    │               '235.62 ms'                │  '235.6 ms'   │
└──────────────────────┴──────────────────────────────────────────┴───────────────┘

site-editor
┌──────────────────────┬──────────────────────────────────────────┬───────────────┐
│       (index)        │ 6a0c6c625075126721a3e22cbb79fad3b54755fd │     trunk     │
├──────────────────────┼──────────────────────────────────────────┼───────────────┤
│    serverResponse    │                '141.2 ms'                │  '161.15 ms'  │
│      firstPaint      │                '650.7 ms'                │  '596.25 ms'  │
│   domContentLoaded   │               '1330.75 ms'               │  '1306.3 ms'  │
│        loaded        │               '1331.6 ms'                │ '1307.05 ms'  │
│ firstContentfulPaint │               '1555.45 ms'               │  '1529.5 ms'  │
│      firstBlock      │               '13297.2 ms'               │ '13061.65 ms' │
│         type         │                '77.11 ms'                │  '80.73 ms'   │
│       minType        │                '69.41 ms'                │  '71.48 ms'   │
│       maxType        │                '97.75 ms'                │  '105.48 ms'  │
└──────────────────────┴──────────────────────────────────────────┴───────────────┘
@jsnajdr
jsnajdr force-pushed the remove/turbo-combine-reducers branch 2 times, most recently from d3d2537 to d1d71e8 Compare September 25, 2023 10:41
@github-actions

github-actions Bot commented Sep 25, 2023

Copy link
Copy Markdown

Flaky tests detected in d1d71e8.
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/6298235508
📝 Reported issues:

@jsnajdr
jsnajdr marked this pull request as ready for review September 25, 2023 14:29
@jsnajdr jsnajdr removed the [Type] Performance Related to performance efforts label Sep 25, 2023
@WordPress WordPress deleted a comment from github-actions Bot Sep 25, 2023

@tyxla tyxla left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work, thanks for working on it @jsnajdr!

As we discussed separately, it might be a good idea to move the undefined -> null changes to a separate PR, since they might be controversial and potentially breaking for some use cases.

I also think we can add some unit tests to cover our custom combineReducers implementation.

Once those two points are addressed, I think we should be good to go.

@jsnajdr
jsnajdr force-pushed the remove/turbo-combine-reducers branch from d1d71e8 to ce4de3a Compare September 27, 2023 13:13
Comment thread packages/core-data/src/selectors.ts Outdated

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fix that was forced by the "null state instead of undefined" changes, and it can be merged even though the state.currentTheme remains undefined. getEntityRecord should never get a fourth argument (key) that's not a valid string, its type doesn't allow that. The State type for the getCurrentTheme's state argument "lies" about the type of state.currentTheme. It can be undefined (or null) when there is no active theme or when the active theme is not yet fetched from the REST endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is pre-existing, but there are places in the codebase that rely on the getCurrentTheme() to always return a non-nullish value, for example:

( select ) => select( coreStore ).getCurrentTheme().stylesheet

Should we be concerned that those potentially might cause issues under some conditions?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If state.currentTheme is not a valid theme slug, then getEntityRecord would return undefined anyway, because the state never has a theme whose slug (ID) would be undefined or null. So, it's not that we're now returning null where a theme object would be previously returned.

The existing places in the codebase are incorrect, because getCurrentTheme() is not guaranteed to return a valid theme. The code relies on the fact that by the time it runs, the /wp/v2/themes?status=active REST request has already finished loading.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed - the existing code would throw an error before with the undefined, and will throw an error now with the null.

IMHO these cases can be handled in another PR, and are something that an eventual TS migration will catch anyway.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the state.currentTheme fix. The stylesheet field contains the ID of the theme, and if the test mock doesn't supply it, the state.currentTheme becomes undefined.

@jsnajdr

jsnajdr commented Sep 27, 2023

Copy link
Copy Markdown
Member Author

Once those two points are addressed, I think we should be good to go.

Both points are addressed now: I removed the changes for undefined state values, and added unit tests for combineReducers.

@tyxla tyxla left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great overall, thanks for working on it @jsnajdr!

I think it's quite close and I've left a few questions - let me know what you think.

Comment thread packages/core-data/src/selectors.ts Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is pre-existing, but there are places in the codebase that rely on the getCurrentTheme() to always return a non-nullish value, for example:

( select ) => select( coreStore ).getCurrentTheme().stylesheet

Should we be concerned that those potentially might cause issues under some conditions?

Comment thread packages/data/src/redux-store/index.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs a CHANGELOG entry.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, added a changelog entry for the data package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more or less a simplified version of the Redux combineReducers(): https://github.com/reduxjs/redux/blob/957aed6e23624113b4d0ff6d9f277f25fca90b38/src/combineReducers.ts#L123

Should we add a mention in CREDITS.md?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not, I think it's sufficiently different from Redux. There are only so many ways to write a combineReducers function, it's very hard to be completely original 🙂 Also, Gutenberg doesn't even have a CREDITS.md file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redux's combineReducers will also complain if there are no reducer subkeys. We could add a test for that too, although it would be a rare scenario.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, do you mean calling combineReducers( {} )? I think that's a valid case, it returns a valid "zero" reducer that always returns {}. Something like empty {} TypeScript type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I was talking about combineReducers( {} ). AFAIK the Redux version won't allow this, while our version allows it. So that makes it a good case for a unit test IMHO.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a failproof check to ensure reducers is a proper object? Should be cheap IMHO. If you agree we should, it could be yet another case to add a test for.

Alternatively, we could introduce combineReducers as a typed function. Then we wouldn't be worried about non-object reducers arguments.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither Redux nor turbo-combined-reducers do such a check on reducers. Both of them do an Object.keys( reducers ) call at the very beginning, that's where they crash if it's not a proper object.

@wordpress/data re-exports the Redux type for combineReducers, so the function has been already typed, and continues to be.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, no need to overcomplicate 👍

@jsnajdr
jsnajdr force-pushed the remove/turbo-combine-reducers branch from ce4de3a to 3ee400f Compare September 28, 2023 11:27

@tyxla tyxla left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks and works great, thanks for addressing it @jsnajdr!

I think we could add a unit test for combineReducers( {} ) before shipping, but that's not a blocker.

🚀

@jsnajdr

jsnajdr commented Sep 29, 2023

Copy link
Copy Markdown
Member Author

I think we could add a unit test for combineReducers( {} ) before shipping

It's added, now I'm going to 🚢

@jsnajdr
jsnajdr merged commit 8e7ce73 into trunk Sep 29, 2023
@jsnajdr
jsnajdr deleted the remove/turbo-combine-reducers branch September 29, 2023 18:38
@github-actions github-actions Bot added this to the Gutenberg 16.8 milestone Sep 29, 2023
@noahtallen

Copy link
Copy Markdown
Member

After installing this update, I'm seeing a lot of errors like Property 'analyzer' does not exist on type '{}'. I think this comes from type definitions like this: export type State = ReturnType< typeof reducers >;. This currently turns into type State: {}, because the return type of combineReducers is now {}, even when the input reducers are fully typed.

@tyxla

tyxla commented Oct 12, 2023

Copy link
Copy Markdown
Member

Fix for the type problem is here: #55321

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Data /packages/data [Type] Security Related to security concerns or efforts

3 participants