WordPress.org

Make WordPress Core

Opened 2 years ago

Last modified 2 months ago

#42438 assigned defect (bug)

Add support for preload links (similar to resource hints)

Reported by: nico23 Owned by: swissspidy
Milestone: Future Release Priority: normal
Severity: normal Version: 4.9
Component: Script Loader Keywords: needs-unit-tests needs-patch
Focuses: Cc:
PR Number:

Description

<link rel="preload" ...

is currently not possible, while others like prefetch are.

Attachments (1)

add_preload_to_ressource_hints.patch (716 bytes) - added by nico23 2 years ago.
patch

Download all attachments as: .zip

Change History (18)

#1 @swissspidy
20 months ago

  • Keywords has-patch needs-unit-tests added
  • Milestone changed from Awaiting Review to 5.0
  • Owner set to swissspidy
  • Status changed from new to assigned

Previously: #34292, #38121

Browser support looks much better now: https://caniuse.com/#feat=link-rel-preload

#2 @swissspidy
20 months ago

  • Component changed from General to Script Loader

#3 @igrigorik
20 months ago

Hey folks! Would love to see preload available in core. A couple of drive-by thoughts..

Resource Hints [1] and Preload [2] have different semantics; Resource Hints != Preload.

  • dns-prefect, preconnect, prefetch, prerender are speculative optimization hints
  • preload is a directive to the UA to fetch the resource

Addy Osmani has a nice writeup on the differences [3]. My recommendation would be to keep Preload and RH as separate APIs, because they have different processing behavior and attributes. Case in point, current wp_resource_hints() exposes "as" attribute, but that only applies to rel=preload resources. On a related note "pr" attribute is now deprecated, so that can be removed from the function as well.

Concretely, I'd propose...

  1. Do some cleanup on wp_resource_hints() to remove "pr" and "as".
  2. Expose new wp_preload() function to emit preload links.

WDYT? Crazytalk? :)

---
[1] https://w3c.github.io/resource-hints/
[2] https://w3c.github.io/preload/
[3] https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf

#4 @swissspidy
17 months ago

  • Keywords needs-patch added; has-patch removed

#5 follow-up: @westonruter
16 months ago

I just ran across this as I was looking to add <link rel="preload" as="script" href="https://cdn.ampproject.org/v0.js"> to the AMP plugin.

While preload != resource hints it seems the existing resource hints API in WordPress is well suited for preload. For example, with add_preload_to_ressource_hints.patch:

<?php
add_filter( 'wp_resource_hints', function( $urls, $relation_type ) {
        if ( 'preload' === $relation_type ) {
                $urls[] = array(
                        'rel'  => 'preload',
                        'as'   => 'script',
                        'href' => 'https://cdn.ampproject.org/v0.js',
                );
        }
        return $urls;
}, 10, 2 );

@igrigorik Would this be bad?

As for the pr attribute in wp_resource_hints(), it's just allowing for the attribute to be used, it doesn't mandate it. We could add a special condition to _doing_it_wrong() if that attribute is provided. Likewise, we could call _doing_it_wrong() if the as attribute is used with anything other than rel=preload.

Also, does it matter the order of the links? Should preload links come after resource hint links?

#6 in reply to: ↑ 5 ; follow-up: @igrigorik
16 months ago

Replying to westonruter:

I just ran across this as I was looking to add <link rel="preload" as="script" href="https://cdn.ampproject.org/v0.js"> to the AMP plugin.

While preload != resource hints it seems the existing resource hints API in WordPress is well suited for preload. For example, with add_preload_to_ressource_hints.patch:

<?php
add_filter( 'wp_resource_hints', function( $urls, $relation_type ) {
        if ( 'preload' === $relation_type ) {
                $urls[] = array(
                        'rel'  => 'preload',
                        'as'   => 'script',
                        'href' => 'https://cdn.ampproject.org/v0.js',
                );
        }
        return $urls;
}, 10, 2 );

@igrigorik Would this be bad?

Not sure if "bad" is the right term, but at a risk of being pedantic.. personally I _would_ prefer if preload was exposed as standalone and separate API: "hints" have a different semantic and UA behavior from preload and merging them into the same API might cause unnecessary confusion for a bunch of folks.

If I could make a wish, I think it would be:

  • deprecate as and pr attributes on wp_resource_hints
  • introduce wp_preload with support for as *and* enforce that as must be provided

Splitting these into separate top level APIs matches the spec behavior and intent, and I think it would help developers navigate the requirements much more clearly too.

As for the pr attribute in wp_resource_hints(), it's just allowing for the attribute to be used, it doesn't mandate it. We could add a special condition to _doing_it_wrong() if that attribute is provided. Likewise, we could call _doing_it_wrong() if the as attribute is used with anything other than rel=preload.

Yeah, I think could work. This wouldn't be my first choice from overall design perspective, but it would get the job done.

Q: Is there a much higher lift to implement and ship separate wp_preload API?

Also, does it matter the order of the links? Should preload links come after resource hint links?

No, the order does not matter.

#7 in reply to: ↑ 6 ; follow-up: @westonruter
16 months ago

Replying to igrigorik:

Not sure if "bad" is the right term, but at a risk of being pedantic.. personally I _would_ prefer if preload was exposed as standalone and separate API: "hints" have a different semantic and UA behavior from preload and merging them into the same API might cause unnecessary confusion for a bunch of folks.

If I could make a wish, I think it would be:

  • deprecate as and pr attributes on wp_resource_hints
  • introduce wp_preload with support for as *and* enforce that as must be provided

Splitting these into separate top level APIs matches the spec behavior and intent, and I think it would help developers navigate the requirements much more clearly too.

That sounds good. I think wp_preload_links would be marginally better name for this function/filter. A benefit to having a separate function as you proposed is that it simplifies the filter. Instead of as above having to check 'preload' === $relation_type the filter could be instead added simply as:

<?php
add_filter( 'wp_preload_links', function( $urls ) {
        $urls[] = array(
                'as'   => 'script',
                'href' => 'https://cdn.ampproject.org/v0.js',
        );
        return $urls;
} );

Aside: I've opened a PR to add the requisite preload links for the AMP plugin via the post-processor. This works in the AMP plugin because we have the output loaded in a DOMDocument for manipulation which isn't an approach available in WordPress normally.

#8 @westonruter
16 months ago

Stepping back a bit: what in WordPress core today would benefit from preload links? We should have some good use cases in core (or bundled themes) prior to adding this.

#9 in reply to: ↑ 7 @igrigorik
16 months ago

Replying to westonruter:

I think wp_preload_links would be marginally better name for this function/filter. A benefit to having a separate function as you proposed is that it simplifies the filter.

Thumbs up for wp_preload_links. I'll defer on the shape of the WP function to the other experts here though. :-)

Stepping back a bit: what in WordPress core today would benefit from preload links? We should have some good use cases in core (or bundled themes) prior to adding this.

There's a lot of good content — e.g., see (1), (2), (3) — on various preload use cases that can be useful within core and themes. I'll just highlight a few...

  • early load of late discovered resources: fonts, stylesheets, hero images, media, etc.
  • decoupling fetch and execution: simple "async CSS" (with help of onload), manual scheduling of JS parse+execute, etc.
  • as a mechanism to signal H2 push to servers/CDNs

Not an exhaustive list, but I believe each of the above has definite use cases in WP ecosystem.


  1. https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
  2. https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/
  3. https://developers.google.com/web/updates/2016/03/link-rel-preload

#10 @westonruter
16 months ago

@igrigorik of those use cases I think “early load of late discovered resources” is going to be the one that will make the most sense to start with in WordPress. It's continuing what was started in #37171 to add preconnect resource hint for the Google Fonts used in the core themes. Similar patches could be added to add support for preloading the header image and featured image that would be used on a given theme template.

#11 @westonruter
16 months ago

  • Summary changed from preload is missing from ressource hints. to Add support for preload links (similar to resource hints)

#12 @westonruter
15 months ago

For the preloading of images, this seems to be largely blocked by the implementation srcset and imgsizes attributes on link rel=preload in browsers. Since images in WordPress almost always get served with sizes and srcset, it doesn't seem feasible to preload the image since we don't know which image size will be used, and the browser could very well preload the wrong image and waste bandwidth. In fact, when I tried adding preloading for the header image in Twenty Seventeen, I got an warning in DevTools:

The resource … was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate as value and it is preloaded intentionally.

#13 @pento
13 months ago

  • Milestone changed from 5.0 to 5.1

#14 @swissspidy
10 months ago

  • Milestone changed from 5.1 to 5.2

#15 @westonruter
9 months ago

The imagesrcset and imagesizes attributes have landed in Chrome 73 beta: https://www.chromestatus.com/feature/5164259990306816

#16 @swissspidy
8 months ago

  • Milestone changed from 5.2 to 5.3

#17 @azaozz
2 months ago

  • Milestone changed from 5.3 to Future Release

Is add_preload_to_ressource_hints.patch something we still want in 5.3? Following the above discussion from about a year ago, seems preloading would need more?

Moving to future release for now, please feel free to bring back to 5.3 if feasible.

CC: @swissspidy

Note: See TracTickets for help on using tickets.