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

Add Non_Blocking_Scripts_Check #519

Merged
merged 14 commits into from
Jul 23, 2024
Merged

Add Non_Blocking_Scripts_Check #519

merged 14 commits into from
Jul 23, 2024

Conversation

swissspidy
Copy link
Member

@swissspidy swissspidy commented Jul 11, 2024

This runtime check is pretty basic right now but does the following:

  1. Test various URLs, similar to our other styles/scripts checks
  2. Enqueues all scripts
  3. Checks whether each enqueued script match the plugin (based on URL)
  4. For matching scripts, checks whether they're enqueued in the footer or the header and if they have a loading strategy

Warnings are reported if either is the case:

a) The script is enqueued in the header, without async/defer -> suggest adding async/defer
b) The script is enqueued in the footer -> suggest adding async/defer

Fixes #467

@swissspidy swissspidy added [Type] Enhancement A suggestion for improvement of an existing feature Checks Audit/test of the particular part of the plugin [Team] Performance Issues owned by Performance Team labels Jul 11, 2024
Copy link

github-actions bot commented Jul 11, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: swissspidy <[email protected]>
Co-authored-by: adamsilverstein <[email protected]>
Co-authored-by: ernilambar <[email protected]>
Co-authored-by: westonruter <[email protected]>
Co-authored-by: mukeshpanchal27 <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Member

@adamsilverstein adamsilverstein left a comment

Choose a reason for hiding this comment

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

Looks good! only some small feedback and a question.

array(
'posts_per_page' => 1,
'post_type' => $post_type,
'post_status' => array( 'publish', 'inherit' ),
Copy link
Member

Choose a reason for hiding this comment

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

Why inherit?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure, to be honest, I copied this from the other checks.

Copy link
Member

Choose a reason for hiding this comment

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

In PR #76, we added a first run time check. The b6e5e56 added the "inherit" post status. I don't think this check is necessary, and there has been no feedback or discussion on the PR regarding it. It appears to have been added by mistake, so we should remove it in a follow-up PR.

includes/Checker/Checks/Non_Blocking_Scripts_Check.php Outdated Show resolved Hide resolved
includes/Checker/Checks/Non_Blocking_Scripts_Check.php Outdated Show resolved Hide resolved
includes/Checker/Checks/Non_Blocking_Scripts_Check.php Outdated Show resolved Hide resolved
@swissspidy
Copy link
Member Author

Worth noting that this has some overlap with the WordPress.WP.EnqueuedResourceParameters.NotInFooter PHPCS sniff which we also run. But as per WordPress/WordPress-Coding-Standards#2420 it is limited and might even get removed.

@swissspidy swissspidy requested a review from felixarntz as a code owner July 13, 2024 12:26
array(
'posts_per_page' => 1,
'post_type' => $post_type,
'post_status' => array( 'publish', 'inherit' ),
Copy link
Member

Choose a reason for hiding this comment

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

In PR #76, we added a first run time check. The b6e5e56 added the "inherit" post status. I don't think this check is necessary, and there has been no feedback or discussion on the PR regarding it. It appears to have been added by mistake, so we should remove it in a follow-up PR.

Copy link
Member

@mukeshpanchal27 mukeshpanchal27 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Overall looks good to me. Left some feedbacks.

Copy link
Member

@mukeshpanchal27 mukeshpanchal27 left a comment

Choose a reason for hiding this comment

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

Approved. Left one non-blocking feedback.

@swissspidy swissspidy added this to the 1.1.0 milestone Jul 16, 2024
foreach ( wp_scripts()->done as $handle ) {
$script = wp_scripts()->registered[ $handle ];

// TODO: Somehow detect inline scripts added by the plugin that don't have a `src`.
Copy link
Member

Choose a reason for hiding this comment

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

Is this referring to before/after inline scripts? Or to scripts that are manually printed with wp_print_inline_script_tag() or otherwise?

Copy link
Member Author

Choose a reason for hiding this comment

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

Both I suppose :-)

Right now the detection whether a script is coming from a plugin is very basic. Something like Origination + loopback requests would be more robust.

);

if ( ! isset( $posts[0] ) ) {
throw new Exception(
Copy link
Member

Choose a reason for hiding this comment

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

maybe just skip silently here, sicne a post type could have no posts?

Copy link
Member Author

Choose a reason for hiding this comment

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

This runtime check creates exactly 1 post in every post type, so it is guaranteed to have one.

protected function get_urls() {
$urls = array( home_url() );

foreach ( $this->get_viewable_post_types() as $post_type ) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe add a sanity limit here, check at most 5 or 10 post types, I can imagine some site has 10,000 post types and this breaks site health for them

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm no other plugins are active during checks and we're checking only a specific plugin here, I doubt that a single plugin adds that many post types.

If we add a limit, then we'd need to add it to all the runtime checks, but I don't see a need for it.

Copy link
Member

@adamsilverstein adamsilverstein left a comment

Choose a reason for hiding this comment

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

overall looks good, left some small feedback

Copy link
Member

@westonruter westonruter left a comment

Choose a reason for hiding this comment

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

A suggestion, but LGTM

wp_scripts()->do_footer_items();
ob_end_clean();

foreach ( wp_scripts()->done as $handle ) {
Copy link
Member

Choose a reason for hiding this comment

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

I just realized what may be a more robust way to handle this, which will also include support for inline scripts: use HTML Tag Processor to iterate over generated markup instead of iterating over the done handles. There could be one output buffer for the head and another for the footer. This would then handle cases where a plugin is adding the strategy attribute manually via the script_loader_tag filter. It would also flag cases where a script fails to get a strategy due to a blocking dependent script depending on an async/defer script.

But that can be done in a subsequent PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

A new issue for this sounds like a good idea 👍

@swissspidy swissspidy merged commit 436bcec into trunk Jul 23, 2024
21 checks passed
@swissspidy swissspidy deleted the fix/467-strategy branch July 23, 2024 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Checks Audit/test of the particular part of the plugin [Team] Performance Issues owned by Performance Team [Type] Enhancement A suggestion for improvement of an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Non_Blocking_Scripts_Check: Warn about enqueued scripts that use neither defer nor async
5 participants