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

Implement speculative loading of the search form #1297

Draft
wants to merge 5 commits into
base: trunk
Choose a base branch
from

Conversation

westonruter
Copy link
Member

@westonruter westonruter commented Jun 11, 2024

Summary

Fixes #1291

This speeds up searches by doing speculative loading of the search results page when the user has entered a search query and is signaling they are about to perform a search.

Here's a test site with this patched version of the plugin installed: https://speculative-loading-test.instawp.xyz/search/

Screen.recording.2024-06-11.03.22.30.webm

(Note the TTFB of 0 ms. This was recorded on airplane wifi!)

Relevant technical choices

The Interactivity API is leveraged to listen for events which signal that a pending search has been entered, namely on the change event as well as whenever a submit button gets a focus event or pointerover. Additionally, when hitting Enter in the search input field it will start to speculatively-load at keydown which could in theory save a few milliseconds. (Alternatively to this, a debounced input event may make more sense.)

The HTML Tag Processor is used to inject the Interactivity API directives on the search form, both in the Search block variant as well as in the classic variant returned by get_search_form().

It seems the key is how the form submit event is handled. If the default form submission handling is done, then the speculative prerender is not reused. However, if the submit event handler does preventDefault and then manually navigates to the URL that the search submission was going to go to anyway, then it works!

handleFormSubmit: ( event ) => {
event.preventDefault();
const form = event.target;
const formData = new FormData( form );
const url = new URL( form.action );
url.search = new URLSearchParams( formData ).toString();
location.href = url.href;
},

This seems like a hacky workaround for something the browser should be doing automatically for GET form submissions.

@westonruter westonruter added [Type] Feature A new feature within an existing module [Plugin] Speculative Loading Issues for the Speculative Loading plugin (formerly Speculation Rules) labels Jun 11, 2024
@westonruter westonruter added this to the speculation-rules n.e.x.t milestone Jun 11, 2024
handleInputKeydown: ( event ) => {
// Eke out a few milliseconds when hitting enter on the input to submit.
if ( event.key === 'Enter' ) {
actions.updateSpeculativeLoadUrl();
Copy link
Member Author

Choose a reason for hiding this comment

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

An action calling another action. Is this bad?

Copy link
Member

Choose a reason for hiding this comment

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

That's fine. Even expected 🙂

Comment on lines +85 to +88
// TODO: Should there be namespaced context?
if ( ! $p->get_attribute( 'data-wp-context' ) ) {
$p->set_attribute( 'data-wp-context', '{}' );
}
Copy link
Member Author

Choose a reason for hiding this comment

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

See wp_interactivity_data_wp_context() which has a $store_namepace argument. The logic in that function could be replicated here. However, it seems this would conflict when there is already a data-wp-context attribute present.

Copy link
Member

Choose a reason for hiding this comment

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

I have created a discussion to see how we can solve that problem in a general way for all the directives:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Plugin] Speculative Loading Issues for the Speculative Loading plugin (formerly Speculation Rules) [Type] Feature A new feature within an existing module
2 participants