Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Site Editor: speed up load by preloading home and front-page templates #66579

Merged
merged 3 commits into from
Oct 31, 2024
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
2 changes: 2 additions & 0 deletions lib/compat/wordpress-6.8/preload.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) {
'url',
)
);
$paths[] = '/wp/v2/templates/lookup?slug=front-page';
$paths[] = '/wp/v2/templates/lookup?slug=home';
}

// Preload theme and global styles paths.
Expand Down
71 changes: 16 additions & 55 deletions packages/core-data/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -563,58 +563,6 @@ export const getAutosave =
await resolveSelect.getAutosaves( postType, postId );
};

/**
* Retrieve the frontend template used for a given link.
*
* @param {string} link Link.
*/
export const __experimentalGetTemplateForLink =
( link ) =>
async ( { dispatch, resolveSelect } ) => {
let template;
try {
// This is NOT calling a REST endpoint but rather ends up with a response from
// an Ajax function which has a different shape from a WP_REST_Response.
template = await apiFetch( {
url: addQueryArgs( link, {
'_wp-find-template': true,
} ),
} ).then( ( { data } ) => data );
} catch ( e ) {
// For non-FSE themes, it is possible that this request returns an error.
}

if ( ! template ) {
return;
}

const record = await resolveSelect.getEntityRecord(
'postType',
'wp_template',
template.id
);

if ( record ) {
dispatch.receiveEntityRecords(
'postType',
'wp_template',
[ record ],
{
'find-template': link,
}
);
}
};

__experimentalGetTemplateForLink.shouldInvalidate = ( action ) => {
return (
( action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS' ) &&
action.invalidateCache &&
action.kind === 'postType' &&
action.name === 'wp_template'
);
};

export const __experimentalGetCurrentGlobalStylesId =
() =>
async ( { dispatch, resolveSelect } ) => {
Expand Down Expand Up @@ -801,13 +749,26 @@ export const getNavigationFallbackId =

export const getDefaultTemplateId =
( query ) =>
async ( { dispatch } ) => {
const template = await apiFetch( {
async ( { dispatch, registry } ) => {
const response = await apiFetch( {
path: addQueryArgs( '/wp/v2/templates/lookup', query ),
parse: false,
} );
const template = await response.json();
// Endpoint may return an empty object if no template is found.
if ( template?.id ) {
dispatch.receiveDefaultTemplateId( query, template.id );
registry.batch( () => {
dispatch.receiveDefaultTemplateId( query, template.id );
dispatch.receiveEntityRecords( 'postType', 'wp_template', [
template,
] );
// Avoid further network requests.
dispatch.finishResolution( 'getEntityRecord', [
'postType',
'wp_template',
template.id,
] );
} );
}
};

Expand Down
32 changes: 0 additions & 32 deletions packages/core-data/src/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1284,38 +1284,6 @@ export function getReferenceByDistinctEdits( state ) {
return state.editsReference;
}

/**
* Retrieve the frontend template used for a given link.
*
* @param state Editor state.
* @param link Link.
*
* @return The template record.
*/
export function __experimentalGetTemplateForLink(
state: State,
link: string
): Optional< ET.Updatable< ET.WpTemplate > > | null | false {
const records = getEntityRecords< ET.WpTemplate >(
state,
'postType',
'wp_template',
{
'find-template': link,
}
);

if ( records?.length ) {
return getEditedEntityRecord< ET.WpTemplate >(
state,
'postType',
'wp_template',
records[ 0 ].id
);
}
return null;
}

/**
* Retrieve the current theme's base global styles
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,47 +31,33 @@ const postTypesWithoutParentTemplate = [
const authorizedPostTypes = [ 'page', 'post' ];

function useResolveEditedEntityAndContext( { postId, postType } ) {
const {
hasLoadedAllDependencies,
homepageId,
postsPageId,
url,
frontPageTemplateId,
} = useSelect( ( select ) => {
const { getEntityRecord, getEntityRecords } = select( coreDataStore );
const siteData = getEntityRecord( 'root', 'site' );
const base = getEntityRecord( 'root', '__unstableBase' );
const templates = getEntityRecords( 'postType', TEMPLATE_POST_TYPE, {
per_page: -1,
} );
const _homepageId =
siteData?.show_on_front === 'page' &&
[ 'number', 'string' ].includes( typeof siteData.page_on_front ) &&
!! +siteData.page_on_front // We also need to check if it's not zero(`0`).
? siteData.page_on_front.toString()
: null;
const _postsPageId =
siteData?.show_on_front === 'page' &&
[ 'number', 'string' ].includes( typeof siteData.page_for_posts )
? siteData.page_for_posts.toString()
: null;
let _frontPageTemplateId;
if ( templates ) {
const frontPageTemplate = templates.find(
( t ) => t.slug === 'front-page'
);
_frontPageTemplateId = frontPageTemplate
? frontPageTemplate.id
: false;
}
return {
hasLoadedAllDependencies: !! base && !! siteData,
homepageId: _homepageId,
postsPageId: _postsPageId,
url: base?.home,
frontPageTemplateId: _frontPageTemplateId,
};
}, [] );
const { hasLoadedAllDependencies, homepageId, postsPageId } = useSelect(
( select ) => {
const { getEntityRecord } = select( coreDataStore );
const siteData = getEntityRecord( 'root', 'site' );
const _homepageId =
siteData?.show_on_front === 'page' &&
[ 'number', 'string' ].includes(
typeof siteData.page_on_front
) &&
!! +siteData.page_on_front // We also need to check if it's not zero(`0`).
? siteData.page_on_front.toString()
: null;
const _postsPageId =
siteData?.show_on_front === 'page' &&
[ 'number', 'string' ].includes(
typeof siteData.page_for_posts
)
? siteData.page_for_posts.toString()
: null;
return {
hasLoadedAllDependencies: !! siteData,
homepageId: _homepageId,
postsPageId: _postsPageId,
};
},
[]
);

/**
* This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId
Expand Down Expand Up @@ -99,7 +85,6 @@ function useResolveEditedEntityAndContext( { postId, postType } ) {
getEditedEntityRecord,
getEntityRecords,
getDefaultTemplateId,
__experimentalGetTemplateForLink,
} = select( coreDataStore );

function resolveTemplateForPostTypeAndId(
Expand All @@ -111,15 +96,7 @@ function useResolveEditedEntityAndContext( { postId, postType } ) {
postTypeToResolve === 'page' &&
homepageId === postIdToResolve
) {
// We're still checking whether the front page template exists.
// Don't resolve the template yet.
if ( frontPageTemplateId === undefined ) {
return undefined;
}

if ( !! frontPageTemplateId ) {
return frontPageTemplateId;
}
return getDefaultTemplateId( { slug: 'front-page' } );
Copy link
Member

Choose a reason for hiding this comment

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

Should we leave previous logic/step related comments? They should still apply, right?

Copy link
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 think so? This returns the resolving selector right away so it will either return undefined or the ID. Worth noting it's already the same below for postsPageId which already returned a resolving selector before.

}

const editedEntity = getEditedEntityRecord(
Expand All @@ -135,8 +112,7 @@ function useResolveEditedEntityAndContext( { postId, postType } ) {
postTypeToResolve === 'page' &&
postsPageId === postIdToResolve
) {
return __experimentalGetTemplateForLink( editedEntity.link )
?.id;
return getDefaultTemplateId( { slug: 'home' } );
}
// First see if the post/page has an assigned template and fetch it.
const currentTemplateSlug = editedEntity.template;
Expand Down Expand Up @@ -194,20 +170,9 @@ function useResolveEditedEntityAndContext( { postId, postType } ) {
}

// If we're not rendering a specific page, use the front page template.
if ( url ) {
const template = __experimentalGetTemplateForLink( url );
return template?.id;
}
return getDefaultTemplateId( { slug: 'front-page' } );
},
[
homepageId,
postsPageId,
hasLoadedAllDependencies,
url,
postId,
postType,
frontPageTemplateId,
]
[ homepageId, postsPageId, hasLoadedAllDependencies, postId, postType ]
);

const context = useMemo( () => {
Expand Down
Loading