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

Improve the initial loading of the site editor #36044

Merged
merged 7 commits into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions docs/reference-guides/data/data-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -626,11 +626,9 @@ _Returns_

### receiveThemeSupports

Returns an action object used in signalling that the index has been received.

_Parameters_
> **Deprecated** since WP 5.9, this is not useful anymore, use the selector direclty.

- _themeSupports_ `Object`: Theme support for the current theme.
Returns an action object used in signalling that the index has been received.

_Returns_

Expand Down
20 changes: 15 additions & 5 deletions lib/full-site-editing/edit-site-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ function gutenberg_edit_site_init( $hook ) {
*/
$current_screen->is_block_editor( true );

$custom_settings = array(
$custom_settings = array(
'siteUrl' => site_url(),
'postsPerPage' => get_option( 'posts_per_page' ),
'styles' => gutenberg_get_editor_styles(),
Expand All @@ -98,9 +98,10 @@ function gutenberg_edit_site_init( $hook ) {
'__experimentalBlockPatterns' => WP_Block_Patterns_Registry::get_instance()->get_all_registered(),
'__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
);
$site_editor_context = new WP_Block_Editor_Context();
$settings = gutenberg_get_block_editor_settings( $custom_settings, $site_editor_context );

$site_editor_context = new WP_Block_Editor_Context();
$settings = gutenberg_get_block_editor_settings( $custom_settings, $site_editor_context );
$active_global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_custom_post_type_id();
$active_theme = wp_get_theme()->get_stylesheet();
gutenberg_initialize_editor(
'edit_site_editor',
'edit-site',
Expand All @@ -111,7 +112,16 @@ function gutenberg_edit_site_init( $hook ) {
'/wp/v2/types?context=edit',
'/wp/v2/taxonomies?context=edit',
'/wp/v2/pages?context=edit',
'/wp/v2/themes?status=active',
'/wp/v2/categories?context=edit',
'/wp/v2/posts?context=edit',
'/wp/v2/tags?context=edit',
'/wp/v2/templates?context=edit',
'/wp/v2/template-parts?context=edit',
'/wp/v2/settings',
'/wp/v2/themes?context=edit&status=active',
'/wp/v2/global-styles/' . $active_global_styles_id . '?context=edit',
'/wp/v2/global-styles/' . $active_global_styles_id,
'/wp/v2/themes/' . $active_theme . '/global-styles',
),
'initializer_name' => 'initialize',
'editor_settings' => $settings,
Expand Down
14 changes: 11 additions & 3 deletions packages/api-fetch/src/middlewares/preloading.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { normalizePath } from '@wordpress/url';
import { getQueryArg, normalizePath } from '@wordpress/url';

/**
* @param {Record<string, any>} preloadedData
Expand All @@ -15,9 +15,17 @@ function createPreloadingMiddleware( preloadedData ) {

return ( options, next ) => {
const { parse = true } = options;
if ( typeof options.path === 'string' ) {
/** @type {string | void} */
let rawPath = options.path;
if ( ! rawPath && options.url ) {
const pathFromQuery = getQueryArg( options.url, 'rest_route' );
if ( typeof pathFromQuery === 'string' ) {
rawPath = pathFromQuery;
}
}
if ( typeof rawPath === 'string' ) {
const method = options.method || 'GET';
const path = normalizePath( options.path );
const path = normalizePath( rawPath );

if ( 'GET' === method && cache[ path ] ) {
const cacheData = cache[ path ];
Expand Down
6 changes: 2 additions & 4 deletions packages/core-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,9 @@ _Returns_

### receiveThemeSupports

Returns an action object used in signalling that the index has been received.

_Parameters_
> **Deprecated** since WP 5.9, this is not useful anymore, use the selector direclty.

- _themeSupports_ `Object`: Theme support for the current theme.
Returns an action object used in signalling that the index has been received.

_Returns_

Expand Down
12 changes: 8 additions & 4 deletions packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { v4 as uuid } from 'uuid';
*/
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import deprecated from '@wordpress/deprecated';

/**
* Internal dependencies
Expand Down Expand Up @@ -136,14 +137,17 @@ export function __experimentalReceiveCurrentGlobalStylesId(
/**
* Returns an action object used in signalling that the index has been received.
*
* @param {Object} themeSupports Theme support for the current theme.
* @deprecated since WP 5.9, this is not useful anymore, use the selector direclty.
*
* @return {Object} Action object.
*/
export function receiveThemeSupports( themeSupports ) {
export function receiveThemeSupports() {
deprecated( "wp.data.dispatch( 'core' ).receiveThemeSupports", {
since: '5.9',
} );

return {
type: 'RECEIVE_THEME_SUPPORTS',
themeSupports,
type: 'DO_NOTHING',
};
}

Expand Down
10 changes: 9 additions & 1 deletion packages/core-data/src/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const defaultEntities = [
label: __( 'Base' ),
name: '__unstableBase',
kind: 'root',
baseURL: '',
baseURL: '/',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the / is preloaded.

},
{
label: __( 'Site' ),
Expand Down Expand Up @@ -136,6 +136,14 @@ export const defaultEntities = [
plural: 'globalStylesVariations', // should be different than name
getTitle: ( record ) => record?.title?.rendered || record?.title,
},
{
label: __( 'Themes' ),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This adds the "themes" entity allowing us to rely on the redux cache and avoid multiple /wp/v2/themes requests.

name: 'theme',
kind: 'root',
baseURL: '/wp/v2/themes',
baseURLParams: { context: 'edit' },
key: 'stylesheet',
},
];

export const kinds = [
Expand Down
42 changes: 0 additions & 42 deletions packages/core-data/src/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,46 +136,6 @@ export function currentGlobalStylesId( state = undefined, action ) {
return state;
}

/**
* Reducer managing installed themes.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
export function themes( state = {}, action ) {
switch ( action.type ) {
case 'RECEIVE_CURRENT_THEME':
return {
...state,
[ action.currentTheme.stylesheet ]: action.currentTheme,
};
}

return state;
}

/**
* Reducer managing theme supports data.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
export function themeSupports( state = {}, action ) {
switch ( action.type ) {
case 'RECEIVE_THEME_SUPPORTS':
return {
...state,
...action.themeSupports,
};
}

return state;
}

/**
* Higher Order Reducer for a given entity config. It supports:
*
Expand Down Expand Up @@ -590,8 +550,6 @@ export default combineReducers( {
currentGlobalStylesId,
currentUser,
taxonomies,
themes,
themeSupports,
entities,
undo,
embedPreviews,
Expand Down
39 changes: 17 additions & 22 deletions packages/core-data/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import apiFetch from '@wordpress/api-fetch';
*/
import { STORE_NAME } from './name';
import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities';
import { ifNotResolved, getNormalizedCommaSeparable } from './utils';
import { forwardResolver, getNormalizedCommaSeparable } from './utils';

/**
* Requests authors from the REST API.
Expand Down Expand Up @@ -115,18 +115,12 @@ export const getEntityRecord = ( kind, name, key = '', query ) => async ( {
/**
* Requests an entity's record from the REST API.
*/
export const getRawEntityRecord = ifNotResolved(
getEntityRecord,
'getEntityRecord'
);
export const getRawEntityRecord = forwardResolver( 'getEntityRecord' );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The difference between the two approaches is that there are actually "two caches" for resolvers: the one that is in the state which ifNotResolved relied on but that one ignores the temporary cache used to track resolvers that are set to be triggered after a setTimeout call (see

resolversCache.isRunning( selectorName, args ) ||
). This means with ifNotResolved there's a change of running the same resolver twice if we call the same selector twice no the same tick, one with getEntityRecord and one time with getRawEntityRecord. (This was actually happening in the site editor)

Copy link
Member

Choose a reason for hiding this comment

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

This is a great idea. The forwardResolver name says much more clearly what it does than ifNotResolved.


/**
* Requests an entity's record from the REST API.
*/
export const getEditedEntityRecord = ifNotResolved(
getRawEntityRecord,
'getRawEntityRecord'
);
export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' );

/**
* Requests the entity's records from the REST API.
Expand Down Expand Up @@ -224,22 +218,20 @@ getEntityRecords.shouldInvalidate = ( action, kind, name ) => {
/**
* Requests the current theme.
*/
export const getCurrentTheme = () => async ( { dispatch } ) => {
const activeThemes = await apiFetch( {
path: '/wp/v2/themes?status=active',
} );
export const getCurrentTheme = () => async ( { dispatch, resolveSelect } ) => {
const activeThemes = await resolveSelect.getEntityRecords(
'root',
'theme',
{ status: 'active' }
);

dispatch.receiveCurrentTheme( activeThemes[ 0 ] );
};

/**
* Requests theme supports data from the index.
*/
export const getThemeSupports = () => async ( { dispatch } ) => {
const activeThemes = await apiFetch( {
path: '/wp/v2/themes?status=active',
} );
dispatch.receiveThemeSupports( activeThemes[ 0 ].theme_supports );
};
export const getThemeSupports = forwardResolver( 'getCurrentTheme' );

/**
* Requests a preview from the from the Embed API.
Expand Down Expand Up @@ -421,10 +413,13 @@ __experimentalGetTemplateForLink.shouldInvalidate = ( action ) => {

export const __experimentalGetCurrentGlobalStylesId = () => async ( {
dispatch,
resolveSelect,
} ) => {
const activeThemes = await apiFetch( {
path: '/wp/v2/themes?status=active',
} );
const activeThemes = await resolveSelect.getEntityRecords(
'root',
'theme',
{ status: 'active' }
);
const globalStylesURL = get( activeThemes, [
0,
'_links',
Expand Down
13 changes: 11 additions & 2 deletions packages/core-data/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ import { getQueriedItems } from './queried-data';
import { DEFAULT_ENTITY_KEY } from './entities';
import { getNormalizedCommaSeparable, isRawAttribute } from './utils';

/**
* Shared reference to an empty object for cases where it is important to avoid
* returning a new object reference on every invocation, as in a connected or
* other pure component which performs `shouldComponentUpdate` check on props.
* This should be used as a last resort, since the normalized data should be
* maintained by the reducer result in state.
*/
const EMPTY_OBJECT = {};

/**
* Shared reference to an empty array for cases where it is important to avoid
* returning a new array reference on every invocation, as in a connected or
Expand Down Expand Up @@ -688,7 +697,7 @@ export function hasRedo( state ) {
* @return {Object} The current theme.
*/
export function getCurrentTheme( state ) {
return state.themes[ state.currentTheme ];
return getEntityRecord( state, 'root', 'theme', state.currentTheme );
}

/**
Expand All @@ -710,7 +719,7 @@ export function __experimentalGetCurrentGlobalStylesId( state ) {
* @return {*} Index data.
*/
export function getThemeSupports( state ) {
return state.themeSupports;
return getCurrentTheme( state )?.theme_supports ?? EMPTY_OBJECT;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions packages/core-data/src/utils/forward-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Higher-order function which forward the resolution to another resolver with the same arguments.
*
* @param {string} resolverName forwarded resolver.
*
* @return {Function} Enhanced resolver.
*/
const forwardResolver = ( resolverName ) => ( ...args ) => async ( {
resolveSelect,
} ) => {
await resolveSelect[ resolverName ]( ...args );
};

export default forwardResolver;
22 changes: 0 additions & 22 deletions packages/core-data/src/utils/if-not-resolved.js

This file was deleted.

2 changes: 1 addition & 1 deletion packages/core-data/src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export { default as conservativeMapItem } from './conservative-map-item';
export { default as getNormalizedCommaSeparable } from './get-normalized-comma-separable';
export { default as ifMatchingAction } from './if-matching-action';
export { default as ifNotResolved } from './if-not-resolved';
export { default as forwardResolver } from './forward-resolver';
export { default as onSubKey } from './on-sub-key';
export { default as replaceAction } from './replace-action';
export { default as withWeakMapCache } from './with-weak-map-cache';
Expand Down
Loading