From c0edc39ba13c6e78a51c5070679c63ab2e450696 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Mon, 1 Mar 2021 18:10:53 +0100 Subject: [PATCH 01/18] Try parsing patterns when idling --- lib/block-patterns.php | 20 +++++++++ package-lock.json | 1 + .../components/block-patterns-list/index.js | 10 +++-- packages/block-editor/src/store/selectors.js | 16 ++++++- packages/edit-post/src/editor.js | 4 -- packages/edit-site/package.json | 1 + .../edit-site/src/components/editor/index.js | 7 ++- .../components/editor/pre-parse-patterns.js | 43 +++++++++++++++++++ 8 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 packages/edit-site/src/components/editor/pre-parse-patterns.js diff --git a/lib/block-patterns.php b/lib/block-patterns.php index d376fb59aea1e9..7adfb46d4e3577 100644 --- a/lib/block-patterns.php +++ b/lib/block-patterns.php @@ -62,3 +62,23 @@ ', ) ); + +for ( $i = 0; $i < 100; $i++ ) { + register_block_pattern( + 'query/small-posts' . $i, + array( + 'title' => __( 'Small' . $i, 'gutenberg' ), + 'scope' => array( + 'inserter' => true + ), + 'content' => ' +
+
+ + +
+
+ ', + ) + ); +} diff --git a/package-lock.json b/package-lock.json index d5b2a1bb89649e..22bf33e6639640 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12856,6 +12856,7 @@ "@wordpress/notices": "file:packages/notices", "@wordpress/plugins": "file:packages/plugins", "@wordpress/primitives": "file:packages/primitives", + "@wordpress/priority-queue": "file:packages/priority-queue", "@wordpress/url": "file:packages/url", "classnames": "^2.2.5", "downloadjs": "^1.4.7", diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 1601cbb728b57b..257d4c994b8fd8 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -1,8 +1,6 @@ /** * WordPress dependencies */ -import { useMemo } from '@wordpress/element'; -import { parse } from '@wordpress/blocks'; import { VisuallyHidden, __unstableComposite as Composite, @@ -11,16 +9,22 @@ import { } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import BlockPreview from '../block-preview'; import InserterDraggableBlocks from '../inserter-draggable-blocks'; +import { store as blockEditorStore } from '../../store'; function BlockPattern( { isDraggable, pattern, onClick, composite } ) { const { content, viewportWidth } = pattern; - const blocks = useMemo( () => parse( content ), [ content ] ); + const blocks = useSelect( + ( select ) => + select( blockEditorStore ).__experimentalGetParsedBlocks( content ), + [ content ] + ); const instanceId = useInstanceId( BlockPattern ); const descriptionId = `block-editor-block-patterns-list__item-description-${ instanceId }`; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 1e6e1a2073ae3f..d15b3a98db66a3 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1757,12 +1757,26 @@ export const __experimentalGetAllowedBlocks = createSelector( ] ); +export const __experimentalGetParsedBlocks = createSelector( + ( state, content ) => { + if ( ! content ) { + return []; + } + + return parse( content ); + }, + ( state, content ) => [ content ] +); + const __experimentalGetParsedPatterns = createSelector( ( state ) => { const patterns = state.settings.__experimentalBlockPatterns; return map( patterns, ( pattern ) => ( { ...pattern, - contentBlocks: parse( pattern.content ), + contentBlocks: __experimentalGetParsedBlocks( + state, + pattern.content + ), } ) ); }, ( state ) => [ state.settings.__experimentalBlockPatterns ] diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 11a82a1e899d34..89c0e8efae5c6c 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -82,10 +82,6 @@ function Editor( { const isFSETheme = getEditorSettings().isFSETheme; const isViewable = getPostType( postType )?.viewable ?? false; - // Prefetch and parse patterns. This ensures patterns are loaded and parsed when - // the editor is loaded rather than degrading the performance of the inserter. - select( 'core/block-editor' ).__experimentalGetAllowedPatterns(); - return { hasFixedToolbar: isFeatureActive( 'fixedToolbar' ) || diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 4de9eff2e53cce..a017a37d88c26a 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -46,6 +46,7 @@ "@wordpress/notices": "file:../notices", "@wordpress/plugins": "file:../plugins", "@wordpress/primitives": "file:../primitives", + "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/url": "file:../url", "classnames": "^2.2.5", "downloadjs": "^1.4.7", diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 9b5d8a0962d4c2..8ab8103d4c94e3 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -35,6 +35,7 @@ import URLQueryController from '../url-query-controller'; import InserterSidebar from '../secondary-sidebar/inserter-sidebar'; import ListViewSidebar from '../secondary-sidebar/list-view-sidebar'; import { store as editSiteStore } from '../../store'; +import { usePreParsePatterns } from './pre-parse-patterns'; const interfaceLabels = { secondarySidebar: __( 'Block Library' ), @@ -67,10 +68,6 @@ function Editor( { initialSettings } ) { const postType = getEditedPostType(); const postId = getEditedPostId(); - // Prefetch and parse patterns. This ensures patterns are loaded and parsed when - // the editor is loaded rather than degrading the performance of the inserter. - select( 'core/block-editor' ).__experimentalGetAllowedPatterns(); - // The currently selected entity to display. Typically template or template part. return { isInserterOpen: isInserterOpened(), @@ -151,6 +148,8 @@ function Editor( { initialSettings } ) { } }, [ isNavigationOpen ] ); + usePreParsePatterns(); + // Don't render the Editor until the settings are set and loaded if ( ! settings?.siteUrl ) { return null; diff --git a/packages/edit-site/src/components/editor/pre-parse-patterns.js b/packages/edit-site/src/components/editor/pre-parse-patterns.js new file mode 100644 index 00000000000000..5cdde9fe3cce52 --- /dev/null +++ b/packages/edit-site/src/components/editor/pre-parse-patterns.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { useSelect, select } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { createQueue } from '@wordpress/priority-queue'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; + +export function usePreParsePatterns() { + const patterns = useSelect( + ( _select ) => + _select( editSiteStore ).getSettings().__experimentalBlockPatterns, + [] + ); + + useEffect( () => { + if ( ! patterns ) { + return; + } + + const asyncQueue = createQueue(); + const append = ( index ) => () => { + if ( patterns.length <= index ) { + return; + } + select( blockEditorStore ).__experimentalGetParsedBlocks( + patterns[ index ].content, + index + ); + asyncQueue.add( {}, append( index + 1 ) ); + }; + asyncQueue.add( {}, append( 0 ) ); + + return () => asyncQueue.reset(); + }, [ patterns ] ); + + return null; +} From 4298360e5d1174ceb0c4db6bb9b80eba7b873589 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 2 Mar 2021 11:43:20 +0100 Subject: [PATCH 02/18] Increase number of patterns --- lib/block-patterns.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/block-patterns.php b/lib/block-patterns.php index 7adfb46d4e3577..a98ec22c0f5ec9 100644 --- a/lib/block-patterns.php +++ b/lib/block-patterns.php @@ -63,7 +63,7 @@ ) ); -for ( $i = 0; $i < 100; $i++ ) { +for ( $i = 0; $i < 1000; $i++ ) { register_block_pattern( 'query/small-posts' . $i, array( From c1d85b4ecc27647bc0e9ec115aec479b1e606546 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 2 Mar 2021 11:43:47 +0100 Subject: [PATCH 03/18] Limit to a single task per idle callback --- .../src/components/editor/pre-parse-patterns.js | 8 +++++++- packages/priority-queue/src/index.js | 13 ++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/editor/pre-parse-patterns.js b/packages/edit-site/src/components/editor/pre-parse-patterns.js index 5cdde9fe3cce52..84d684fa742cf7 100644 --- a/packages/edit-site/src/components/editor/pre-parse-patterns.js +++ b/packages/edit-site/src/components/editor/pre-parse-patterns.js @@ -23,9 +23,13 @@ export function usePreParsePatterns() { return; } - const asyncQueue = createQueue(); + window.console.time( '[usePreParsePatterns] initiate queue' ); + const asyncQueue = createQueue( 1 ); const append = ( index ) => () => { + const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ].title }`; + window.console.time( marker ); if ( patterns.length <= index ) { + window.console.timeEnd( marker ); return; } select( blockEditorStore ).__experimentalGetParsedBlocks( @@ -33,8 +37,10 @@ export function usePreParsePatterns() { index ); asyncQueue.add( {}, append( index + 1 ) ); + window.console.timeEnd( marker ); }; asyncQueue.add( {}, append( 0 ) ); + window.console.timeEnd( '[usePreParsePatterns] initiate queue' ); return () => asyncQueue.reset(); }, [ patterns ] ); diff --git a/packages/priority-queue/src/index.js b/packages/priority-queue/src/index.js index 751326a8001117..0b8578c5ec499b 100644 --- a/packages/priority-queue/src/index.js +++ b/packages/priority-queue/src/index.js @@ -63,9 +63,10 @@ import requestIdleCallback from './request-idle-callback'; * queue.add( ctx2, () => console.log( 'This will be printed second' ) ); *``` * + * @param {number} [callbacksToProcessPerRun] * @return {WPPriorityQueue} Queue object with `add`, `flush` and `reset` methods. */ -export const createQueue = () => { +export const createQueue = ( callbacksToProcessPerRun ) => { /** @type {WPPriorityQueueContext[]} */ let waitingList = []; @@ -75,12 +76,13 @@ export const createQueue = () => { let isRunning = false; /** - * Callback to process as much queue as time permits. + * Callback to process as much queue as time and `callbacksToProcessPerRun` permits. * * @param {IdleDeadline|number} deadline Idle callback deadline object, or * animation frame timestamp. */ const runWaitingList = ( deadline ) => { + let tasksProcessed = 0; const hasTimeRemaining = typeof deadline === 'number' ? () => false @@ -101,7 +103,12 @@ export const createQueue = () => { // loops and race conditions in the queue. callback(); elementsMap.delete( nextElement ); - } while ( hasTimeRemaining() ); + tasksProcessed++; + } while ( + hasTimeRemaining() && + ( ! callbacksToProcessPerRun || + tasksProcessed < callbacksToProcessPerRun ) + ); requestIdleCallback( runWaitingList ); }; From b0b6b43c496c088f5ed77ab4f0892ee8ad05808e Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 2 Mar 2021 11:44:27 +0100 Subject: [PATCH 04/18] Update docs --- packages/priority-queue/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/priority-queue/README.md b/packages/priority-queue/README.md index 600a82240cbb8e..f939ee9f550a61 100644 --- a/packages/priority-queue/README.md +++ b/packages/priority-queue/README.md @@ -38,6 +38,10 @@ queue.add( ctx2, () => console.log( 'This won\'t be printed' ) ); queue.add( ctx2, () => console.log( 'This will be printed second' ) ); ``` +_Parameters_ + +- _callbacksToProcessPerRun_ `[number]`: + _Returns_ - `WPPriorityQueue`: Queue object with `add`, `flush` and `reset` methods. From 39bc7ebffff0807147779dee595665753d7a0e48 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 2 Mar 2021 12:41:32 +0100 Subject: [PATCH 05/18] Use requestIdleCallback instead of queue --- .../components/editor/pre-parse-patterns.js | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/edit-site/src/components/editor/pre-parse-patterns.js b/packages/edit-site/src/components/editor/pre-parse-patterns.js index 84d684fa742cf7..4eda56c3e583f4 100644 --- a/packages/edit-site/src/components/editor/pre-parse-patterns.js +++ b/packages/edit-site/src/components/editor/pre-parse-patterns.js @@ -4,7 +4,6 @@ import { useSelect, select } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { createQueue } from '@wordpress/priority-queue'; /** * Internal dependencies @@ -23,26 +22,26 @@ export function usePreParsePatterns() { return; } + let handle; + let index = -1; window.console.time( '[usePreParsePatterns] initiate queue' ); - const asyncQueue = createQueue( 1 ); - const append = ( index ) => () => { + const callback = () => { + index++; const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ].title }`; window.console.time( marker ); - if ( patterns.length <= index ) { - window.console.timeEnd( marker ); - return; + if ( patterns.length > index ) { + select( blockEditorStore ).__experimentalGetParsedBlocks( + patterns[ index ].content, + index + ); + window.requestIdleCallback( callback ); } - select( blockEditorStore ).__experimentalGetParsedBlocks( - patterns[ index ].content, - index - ); - asyncQueue.add( {}, append( index + 1 ) ); window.console.timeEnd( marker ); }; - asyncQueue.add( {}, append( 0 ) ); + window.requestIdleCallback( callback ); window.console.timeEnd( '[usePreParsePatterns] initiate queue' ); - return () => asyncQueue.reset(); + return () => window.cancelIdleCallback( handle ); }, [ patterns ] ); return null; From 34e4aadd973639f3c99e21e1932110f62702653b Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 2 Mar 2021 12:44:42 +0100 Subject: [PATCH 06/18] Revert queue --- package-lock.json | 1 - packages/edit-site/package.json | 1 - packages/priority-queue/README.md | 4 ---- packages/priority-queue/src/index.js | 13 +++---------- 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 22bf33e6639640..d5b2a1bb89649e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12856,7 +12856,6 @@ "@wordpress/notices": "file:packages/notices", "@wordpress/plugins": "file:packages/plugins", "@wordpress/primitives": "file:packages/primitives", - "@wordpress/priority-queue": "file:packages/priority-queue", "@wordpress/url": "file:packages/url", "classnames": "^2.2.5", "downloadjs": "^1.4.7", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index a017a37d88c26a..4de9eff2e53cce 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -46,7 +46,6 @@ "@wordpress/notices": "file:../notices", "@wordpress/plugins": "file:../plugins", "@wordpress/primitives": "file:../primitives", - "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/url": "file:../url", "classnames": "^2.2.5", "downloadjs": "^1.4.7", diff --git a/packages/priority-queue/README.md b/packages/priority-queue/README.md index f939ee9f550a61..600a82240cbb8e 100644 --- a/packages/priority-queue/README.md +++ b/packages/priority-queue/README.md @@ -38,10 +38,6 @@ queue.add( ctx2, () => console.log( 'This won\'t be printed' ) ); queue.add( ctx2, () => console.log( 'This will be printed second' ) ); ``` -_Parameters_ - -- _callbacksToProcessPerRun_ `[number]`: - _Returns_ - `WPPriorityQueue`: Queue object with `add`, `flush` and `reset` methods. diff --git a/packages/priority-queue/src/index.js b/packages/priority-queue/src/index.js index 0b8578c5ec499b..751326a8001117 100644 --- a/packages/priority-queue/src/index.js +++ b/packages/priority-queue/src/index.js @@ -63,10 +63,9 @@ import requestIdleCallback from './request-idle-callback'; * queue.add( ctx2, () => console.log( 'This will be printed second' ) ); *``` * - * @param {number} [callbacksToProcessPerRun] * @return {WPPriorityQueue} Queue object with `add`, `flush` and `reset` methods. */ -export const createQueue = ( callbacksToProcessPerRun ) => { +export const createQueue = () => { /** @type {WPPriorityQueueContext[]} */ let waitingList = []; @@ -76,13 +75,12 @@ export const createQueue = ( callbacksToProcessPerRun ) => { let isRunning = false; /** - * Callback to process as much queue as time and `callbacksToProcessPerRun` permits. + * Callback to process as much queue as time permits. * * @param {IdleDeadline|number} deadline Idle callback deadline object, or * animation frame timestamp. */ const runWaitingList = ( deadline ) => { - let tasksProcessed = 0; const hasTimeRemaining = typeof deadline === 'number' ? () => false @@ -103,12 +101,7 @@ export const createQueue = ( callbacksToProcessPerRun ) => { // loops and race conditions in the queue. callback(); elementsMap.delete( nextElement ); - tasksProcessed++; - } while ( - hasTimeRemaining() && - ( ! callbacksToProcessPerRun || - tasksProcessed < callbacksToProcessPerRun ) - ); + } while ( hasTimeRemaining() ); requestIdleCallback( runWaitingList ); }; From ac25ca520fd067fed5c563646a46b4079d21267c Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 2 Mar 2021 13:05:30 +0100 Subject: [PATCH 07/18] Refactor --- packages/block-editor/src/utils/index.js | 1 + .../src/utils}/pre-parse-patterns.js | 6 +++--- packages/edit-post/src/editor.js | 3 +++ packages/edit-site/src/components/editor/index.js | 7 +++++-- 4 files changed, 12 insertions(+), 5 deletions(-) rename packages/{edit-site/src/components/editor => block-editor/src/utils}/pre-parse-patterns.js (84%) diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index f498a6bf4740bb..509fa610d9652e 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -1,3 +1,4 @@ export { default as transformStyles } from './transform-styles'; export * from './theme'; export * from './block-variation-transforms'; +export { usePreParsePatterns as __experimentalPreParsePatterns } from './pre-parse-patterns'; diff --git a/packages/edit-site/src/components/editor/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js similarity index 84% rename from packages/edit-site/src/components/editor/pre-parse-patterns.js rename to packages/block-editor/src/utils/pre-parse-patterns.js index 4eda56c3e583f4..06ba3ce2120a17 100644 --- a/packages/edit-site/src/components/editor/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -3,17 +3,17 @@ */ import { useSelect, select } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; -import { store as blockEditorStore } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { store as editSiteStore } from '../../store'; +import { store as blockEditorStore } from '../store'; export function usePreParsePatterns() { const patterns = useSelect( ( _select ) => - _select( editSiteStore ).getSettings().__experimentalBlockPatterns, + _select( blockEditorStore ).getSettings() + .__experimentalBlockPatterns, [] ); diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 89c0e8efae5c6c..f7d5cc69a5da53 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -19,6 +19,7 @@ import { SlotFillProvider, __unstableDropZoneContextProvider as DropZoneContextProvider, } from '@wordpress/components'; +import { __experimentalPreParsePatterns as usePreParsePatterns } from '@wordpress/block-editor'; /** * Internal dependencies @@ -166,6 +167,8 @@ function Editor( { return hasThemeStyles ? settings.styles : settings.defaultEditorStyles; }, [ settings, hasThemeStyles ] ); + usePreParsePatterns(); + if ( ! post ) { return null; } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 8ab8103d4c94e3..030a2f338973d3 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -10,7 +10,11 @@ import { Button, } from '@wordpress/components'; import { EntityProvider } from '@wordpress/core-data'; -import { BlockContextProvider, BlockBreadcrumb } from '@wordpress/block-editor'; +import { + BlockContextProvider, + BlockBreadcrumb, + __experimentalPreParsePatterns as usePreParsePatterns, +} from '@wordpress/block-editor'; import { FullscreenMode, InterfaceSkeleton, @@ -35,7 +39,6 @@ import URLQueryController from '../url-query-controller'; import InserterSidebar from '../secondary-sidebar/inserter-sidebar'; import ListViewSidebar from '../secondary-sidebar/list-view-sidebar'; import { store as editSiteStore } from '../../store'; -import { usePreParsePatterns } from './pre-parse-patterns'; const interfaceLabels = { secondarySidebar: __( 'Block Library' ), From 0e0e2b5fe1eb413abc08eea489fa32954598b358 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Thu, 4 Mar 2021 13:05:29 +0100 Subject: [PATCH 08/18] Fix errors --- .../src/utils/pre-parse-patterns.js | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index 06ba3ce2120a17..67e322cd4167a0 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -18,29 +18,34 @@ export function usePreParsePatterns() { ); useEffect( () => { - if ( ! patterns ) { + if ( ! patterns?.length ) { return; } let handle; let index = -1; - window.console.time( '[usePreParsePatterns] initiate queue' ); + const callback = () => { index++; - const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ].title }`; - window.console.time( marker ); - if ( patterns.length > index ) { - select( blockEditorStore ).__experimentalGetParsedBlocks( - patterns[ index ].content, - index - ); - window.requestIdleCallback( callback ); + if ( index >= patterns.length ) { + return; } + + const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ]?.title }`; + window.console.time( marker ); + select( blockEditorStore ).__experimentalGetParsedBlocks( + patterns[ index ].content, + index + ); window.console.timeEnd( marker ); + + handle = window.requestIdleCallback( callback ); }; - window.requestIdleCallback( callback ); - window.console.timeEnd( '[usePreParsePatterns] initiate queue' ); + window.console.time( '[usePreParsePatterns] initiate' ); + window.console.timeEnd( '[usePreParsePatterns] initiate' ); + + handle = window.requestIdleCallback( callback ); return () => window.cancelIdleCallback( handle ); }, [ patterns ] ); From 4df0a4eba3e1c625d5faf8854dee773c21a97a4a Mon Sep 17 00:00:00 2001 From: David Szabo Date: Thu, 4 Mar 2021 13:51:56 +0100 Subject: [PATCH 09/18] requestIdleCallback and cancelIdleCallback fallback --- .../src/utils/pre-parse-patterns.js | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index 67e322cd4167a0..93eba23e59b65f 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -9,6 +9,24 @@ import { useEffect } from '@wordpress/element'; */ import { store as blockEditorStore } from '../store'; +const requestIdleCallback = ( () => { + if ( typeof window === 'undefined' ) { + return ( callback ) => { + setTimeout( () => callback( Date.now() ), 0 ); + }; + } + + return window.requestIdleCallback || window.requestAnimationFrame; +} )(); + +const cancelIdleCallback = ( () => { + if ( typeof window === 'undefined' ) { + return clearTimeout; + } + + return window.cancelIdleCallback || window.cancelAnimationFrame; +} )(); + export function usePreParsePatterns() { const patterns = useSelect( ( _select ) => @@ -39,14 +57,14 @@ export function usePreParsePatterns() { ); window.console.timeEnd( marker ); - handle = window.requestIdleCallback( callback ); + handle = requestIdleCallback( callback ); }; window.console.time( '[usePreParsePatterns] initiate' ); window.console.timeEnd( '[usePreParsePatterns] initiate' ); - handle = window.requestIdleCallback( callback ); - return () => window.cancelIdleCallback( handle ); + handle = requestIdleCallback( callback ); + return () => cancelIdleCallback( handle ); }, [ patterns ] ); return null; From 8f07730be74cc4634f7430328b2708c23f4fc9f1 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Fri, 5 Mar 2021 20:31:36 +0100 Subject: [PATCH 10/18] Refactor to use getParsedPattern --- .../components/block-patterns-list/index.js | 8 ++-- packages/block-editor/src/store/selectors.js | 42 ++++++++----------- .../src/utils/pre-parse-patterns.js | 6 +-- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 257d4c994b8fd8..b3169619f0d70d 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -19,11 +19,11 @@ import InserterDraggableBlocks from '../inserter-draggable-blocks'; import { store as blockEditorStore } from '../../store'; function BlockPattern( { isDraggable, pattern, onClick, composite } ) { - const { content, viewportWidth } = pattern; - const blocks = useSelect( + const { name, viewportWidth } = pattern; + const { blocks } = useSelect( ( select ) => - select( blockEditorStore ).__experimentalGetParsedBlocks( content ), - [ content ] + select( blockEditorStore ).__experimentalGetParsedPattern( name ), + [ name ] ); const instanceId = useInstanceId( BlockPattern ); const descriptionId = `block-editor-block-patterns-list__item-description-${ instanceId }`; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d15b3a98db66a3..26e26773a7f2a9 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -15,7 +15,6 @@ import { filter, mapKeys, orderBy, - every, } from 'lodash'; import createSelector from 'rememo'; @@ -1757,27 +1756,18 @@ export const __experimentalGetAllowedBlocks = createSelector( ] ); -export const __experimentalGetParsedBlocks = createSelector( - ( state, content ) => { - if ( ! content ) { - return []; +export const __experimentalGetParsedPattern = createSelector( + ( state, patternName ) => { + const patterns = state.settings.__experimentalBlockPatterns; + const pattern = patterns.find( ( { name } ) => name === patternName ); + if ( ! pattern ) { + return null; } - return parse( content ); - }, - ( state, content ) => [ content ] -); - -const __experimentalGetParsedPatterns = createSelector( - ( state ) => { - const patterns = state.settings.__experimentalBlockPatterns; - return map( patterns, ( pattern ) => ( { + return { ...pattern, - contentBlocks: __experimentalGetParsedBlocks( - state, - pattern.content - ), - } ) ); + blocks: parse( pattern.content ), + }; }, ( state ) => [ state.settings.__experimentalBlockPatterns ] ); @@ -1792,17 +1782,19 @@ const __experimentalGetParsedPatterns = createSelector( */ export const __experimentalGetAllowedPatterns = createSelector( ( state, rootClientId = null ) => { - const patterns = __experimentalGetParsedPatterns( state ); - + const patterns = state.settings.__experimentalBlockPatterns; if ( ! rootClientId ) { return patterns; } - const patternsAllowed = filter( patterns, ( { contentBlocks } ) => { - return every( contentBlocks, ( { name } ) => + const parsedPatterns = patterns.map( ( { name } ) => + __experimentalGetParsedPattern( state, name ) + ); + const patternsAllowed = filter( parsedPatterns, ( { blocks } ) => + blocks.every( ( { name } ) => canInsertBlockType( state, name, rootClientId ) - ); - } ); + ) + ); return patternsAllowed; }, diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index 93eba23e59b65f..c30a9d269810a5 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -49,10 +49,10 @@ export function usePreParsePatterns() { return; } - const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ]?.title }`; + const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ]?.name }`; window.console.time( marker ); - select( blockEditorStore ).__experimentalGetParsedBlocks( - patterns[ index ].content, + select( blockEditorStore ).__experimentalGetParsedPattern( + patterns[ index ].name, index ); window.console.timeEnd( marker ); From 9a200cd589ebf171a867cd56db066d1448d7e8c9 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Fri, 5 Mar 2021 20:44:16 +0100 Subject: [PATCH 11/18] Fix tests --- packages/block-editor/src/store/test/selectors.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 3d2e058dd844f6..afdca16a3cf22a 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -3375,10 +3375,12 @@ describe( 'selectors', () => { settings: { __experimentalBlockPatterns: [ { + name: 'pattern-a', title: 'pattern with a', content: ``, }, { + name: 'pattern-b', title: 'pattern with b', content: '', @@ -3409,10 +3411,12 @@ describe( 'selectors', () => { settings: { __experimentalBlockPatterns: [ { + name: 'pattern-a', title: 'pattern a', scope: { block: [ 'test/block-a' ] }, }, { + name: 'pattern-b', title: 'pattern b', scope: { block: [ 'test/block-b' ] }, }, From a8b3d4682c94783fe244d738433afbcddfc5552a Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 9 Mar 2021 18:38:45 +0100 Subject: [PATCH 12/18] Fix hook rerunning on render --- .../block-editor/src/utils/pre-parse-patterns.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index c30a9d269810a5..25ee67bed21bdc 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -28,12 +28,13 @@ const cancelIdleCallback = ( () => { } )(); export function usePreParsePatterns() { - const patterns = useSelect( - ( _select ) => - _select( blockEditorStore ).getSettings() - .__experimentalBlockPatterns, - [] - ); + const patterns = + useSelect( + ( _select ) => + _select( blockEditorStore ).getSettings() + .__experimentalBlockPatterns, + [] + ) || []; useEffect( () => { if ( ! patterns?.length ) { @@ -65,7 +66,7 @@ export function usePreParsePatterns() { handle = requestIdleCallback( callback ); return () => cancelIdleCallback( handle ); - }, [ patterns ] ); + }, patterns ); return null; } From b12d4d652801ff73a5e3feaa481078d2056d2feb Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 9 Mar 2021 18:39:19 +0100 Subject: [PATCH 13/18] Move hook call into BlockList --- packages/block-editor/src/components/block-list/index.js | 2 ++ packages/block-editor/src/utils/index.js | 1 - packages/edit-post/src/editor.js | 3 --- packages/edit-site/src/components/editor/index.js | 8 +------- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index f1da838a8c7526..0ece7a2c0bb03a 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -19,6 +19,7 @@ import useInsertionPoint from './insertion-point'; import BlockPopover from './block-popover'; import { store as blockEditorStore } from '../../store'; import { useScrollSelectionIntoView } from '../selection-scroll-into-view'; +import { usePreParsePatterns } from '../../utils/pre-parse-patterns'; export const BlockNodes = createContext(); export const SetBlockNodes = createContext(); @@ -28,6 +29,7 @@ export default function BlockList( { className } ) { const [ blockNodes, setBlockNodes ] = useState( {} ); const insertionPoint = useInsertionPoint( ref ); useScrollSelectionIntoView( ref ); + usePreParsePatterns(); return ( diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index 509fa610d9652e..f498a6bf4740bb 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -1,4 +1,3 @@ export { default as transformStyles } from './transform-styles'; export * from './theme'; export * from './block-variation-transforms'; -export { usePreParsePatterns as __experimentalPreParsePatterns } from './pre-parse-patterns'; diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index f7d5cc69a5da53..89c0e8efae5c6c 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -19,7 +19,6 @@ import { SlotFillProvider, __unstableDropZoneContextProvider as DropZoneContextProvider, } from '@wordpress/components'; -import { __experimentalPreParsePatterns as usePreParsePatterns } from '@wordpress/block-editor'; /** * Internal dependencies @@ -167,8 +166,6 @@ function Editor( { return hasThemeStyles ? settings.styles : settings.defaultEditorStyles; }, [ settings, hasThemeStyles ] ); - usePreParsePatterns(); - if ( ! post ) { return null; } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 030a2f338973d3..97370f369a5b00 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -10,11 +10,7 @@ import { Button, } from '@wordpress/components'; import { EntityProvider } from '@wordpress/core-data'; -import { - BlockContextProvider, - BlockBreadcrumb, - __experimentalPreParsePatterns as usePreParsePatterns, -} from '@wordpress/block-editor'; +import { BlockContextProvider, BlockBreadcrumb } from '@wordpress/block-editor'; import { FullscreenMode, InterfaceSkeleton, @@ -151,8 +147,6 @@ function Editor( { initialSettings } ) { } }, [ isNavigationOpen ] ); - usePreParsePatterns(); - // Don't render the Editor until the settings are set and loaded if ( ! settings?.siteUrl ) { return null; From 2945982c92f291ae2b946d03e8f1f7cfd6113730 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 9 Mar 2021 18:58:32 +0100 Subject: [PATCH 14/18] Fix deps --- .../block-editor/src/utils/pre-parse-patterns.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index 25ee67bed21bdc..c30a9d269810a5 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -28,13 +28,12 @@ const cancelIdleCallback = ( () => { } )(); export function usePreParsePatterns() { - const patterns = - useSelect( - ( _select ) => - _select( blockEditorStore ).getSettings() - .__experimentalBlockPatterns, - [] - ) || []; + const patterns = useSelect( + ( _select ) => + _select( blockEditorStore ).getSettings() + .__experimentalBlockPatterns, + [] + ); useEffect( () => { if ( ! patterns?.length ) { @@ -66,7 +65,7 @@ export function usePreParsePatterns() { handle = requestIdleCallback( callback ); return () => cancelIdleCallback( handle ); - }, patterns ); + }, [ patterns ] ); return null; } From eb4e1e0d604d82ccafa99a1d2c7bbf19ec163b51 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 9 Mar 2021 19:12:17 +0100 Subject: [PATCH 15/18] Remove patterns from the block preview context --- .../block-editor/src/components/block-preview/index.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 1c293fc15a2ed6..5b07b7e7404184 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -24,10 +24,11 @@ export function BlockPreview( { __experimentalLive = false, __experimentalOnClick, } ) { - const settings = useSelect( - ( select ) => select( blockEditorStore ).getSettings(), - [] - ); + const settings = useSelect( ( select ) => { + const _settings = { ...select( blockEditorStore ).getSettings() }; + _settings.__experimentalBlockPatterns = []; + return _settings; + }, [] ); const renderedBlocks = useMemo( () => castArray( blocks ), [ blocks ] ); if ( ! blocks || blocks.length === 0 ) { return null; From f402bd51172df02423027cdac4e8466a59cfdec6 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Tue, 9 Mar 2021 19:22:14 +0100 Subject: [PATCH 16/18] Memoize modified settings --- .../block-editor/src/components/block-preview/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 5b07b7e7404184..dfec2f64fab284 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -24,11 +24,15 @@ export function BlockPreview( { __experimentalLive = false, __experimentalOnClick, } ) { - const settings = useSelect( ( select ) => { - const _settings = { ...select( blockEditorStore ).getSettings() }; + const originalSettings = useSelect( + ( select ) => select( blockEditorStore ).getSettings(), + [] + ); + const settings = useMemo( () => { + const _settings = { ...originalSettings }; _settings.__experimentalBlockPatterns = []; return _settings; - }, [] ); + }, [ originalSettings ] ); const renderedBlocks = useMemo( () => castArray( blocks ), [ blocks ] ); if ( ! blocks || blocks.length === 0 ) { return null; From fb07d351c52f2bc9a6a6df5a0e508122967f743f Mon Sep 17 00:00:00 2001 From: David Szabo Date: Wed, 10 Mar 2021 09:40:17 +0100 Subject: [PATCH 17/18] Remove debug code snippets --- lib/block-patterns.php | 20 ------------------- .../src/utils/pre-parse-patterns.js | 6 ------ 2 files changed, 26 deletions(-) diff --git a/lib/block-patterns.php b/lib/block-patterns.php index a98ec22c0f5ec9..d376fb59aea1e9 100644 --- a/lib/block-patterns.php +++ b/lib/block-patterns.php @@ -62,23 +62,3 @@ ', ) ); - -for ( $i = 0; $i < 1000; $i++ ) { - register_block_pattern( - 'query/small-posts' . $i, - array( - 'title' => __( 'Small' . $i, 'gutenberg' ), - 'scope' => array( - 'inserter' => true - ), - 'content' => ' -
-
- - -
-
- ', - ) - ); -} diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index c30a9d269810a5..60929a4088c37e 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -49,20 +49,14 @@ export function usePreParsePatterns() { return; } - const marker = `[usePreParsePatterns] process ${ index } ${ patterns[ index ]?.name }`; - window.console.time( marker ); select( blockEditorStore ).__experimentalGetParsedPattern( patterns[ index ].name, index ); - window.console.timeEnd( marker ); handle = requestIdleCallback( callback ); }; - window.console.time( '[usePreParsePatterns] initiate' ); - window.console.timeEnd( '[usePreParsePatterns] initiate' ); - handle = requestIdleCallback( callback ); return () => cancelIdleCallback( handle ); }, [ patterns ] ); From 1a176d293b22ef71788d7f4f0f8ec74ac5732677 Mon Sep 17 00:00:00 2001 From: David Szabo Date: Thu, 11 Mar 2021 09:41:57 +0100 Subject: [PATCH 18/18] Remove unused argument --- packages/block-editor/src/utils/pre-parse-patterns.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/pre-parse-patterns.js b/packages/block-editor/src/utils/pre-parse-patterns.js index 60929a4088c37e..c5e1d5ad41ac59 100644 --- a/packages/block-editor/src/utils/pre-parse-patterns.js +++ b/packages/block-editor/src/utils/pre-parse-patterns.js @@ -50,8 +50,7 @@ export function usePreParsePatterns() { } select( blockEditorStore ).__experimentalGetParsedPattern( - patterns[ index ].name, - index + patterns[ index ].name ); handle = requestIdleCallback( callback );