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

Send preload links via HTTP Link headers in addition to LINK tags #1323

Merged
merged 10 commits into from
Jul 8, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,27 @@ static function ( array $carry, array $link ): array {
);
}

/**
* Adds media features to the links.
*
* @phpstan-param Link $link
* @param array $link Link array.
* @phpstan-return Link
* @return array Link array with media features added.
AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved
*/
private function add_media_features( array $link ): array {
$media_features = array( 'screen' );
if ( null !== $link['minimum_viewport_width'] && $link['minimum_viewport_width'] > 0 ) {
$media_features[] = sprintf( '(min-width: %dpx)', $link['minimum_viewport_width'] );
}
if ( null !== $link['maximum_viewport_width'] && PHP_INT_MAX !== $link['maximum_viewport_width'] ) {
$media_features[] = sprintf( '(max-width: %dpx)', $link['maximum_viewport_width'] );
}
$link['attributes']['media'] = implode( ' and ', $media_features );

return (array) $link;
}
AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved

/**
* Gets the HTML for the link tags.
*
Expand All @@ -145,14 +166,7 @@ public function get_html(): string {
$link_tags = array();

foreach ( $this->get_adjacent_deduplicated_links() as $link ) {
$media_features = array( 'screen' );
if ( null !== $link['minimum_viewport_width'] && $link['minimum_viewport_width'] > 0 ) {
$media_features[] = sprintf( '(min-width: %dpx)', $link['minimum_viewport_width'] );
}
if ( null !== $link['maximum_viewport_width'] && PHP_INT_MAX !== $link['maximum_viewport_width'] ) {
$media_features[] = sprintf( '(max-width: %dpx)', $link['maximum_viewport_width'] );
}
$link['attributes']['media'] = implode( ' and ', $media_features );
$link = $this->add_media_features( (array) $link );
AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved

$link_tag = '<link data-od-added-tag rel="preload"';
foreach ( $link['attributes'] as $name => $value ) {
Expand All @@ -166,6 +180,33 @@ public function get_html(): string {
return implode( '', $link_tags );
}

/**
* Constructs the Link HTTP response header.
*
* @return string|null Link HTTP response header, or null if there are none.
*/
public function get_response_header(): ?string {
$link_headers = array();

foreach ( $this->get_adjacent_deduplicated_links() as $link ) {
AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved
$link = $this->add_media_features( (array) $link );

$link_header = '<' . esc_url_raw( $link['attributes']['href'] ?? '' ) . '>; rel="preload"';
AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved
foreach ( $link['attributes'] as $name => $value ) {
if ( 'href' !== $name ) {
$link_header .= sprintf( '; %s="%s"', $name, rawurlencode( $value ) );
}
AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved
}

$link_headers[] = $link_header;
}
if ( count( $link_headers ) === 0 ) {
return null;
}

AhmarZaidi marked this conversation as resolved.
Show resolved Hide resolved
return 'Link: ' . implode( ', ', $link_headers );
}

/**
* Counts the links.
*
Expand Down
6 changes: 5 additions & 1 deletion plugins/optimization-detective/optimization.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,12 @@ function od_optimize_template_output_buffer( string $buffer ): string {
$generator->next();
}

// Inject any preload links at the end of the HEAD.
// Send any preload links in a Link response header and in a LINK tag injected at the end of the HEAD.
if ( count( $preload_links ) > 0 ) {
$response_header_links = $preload_links->get_response_header();
if ( ! is_null( $response_header_links ) && ! headers_sent() ) {
header( $response_header_links, false );
}
$walker->append_head_html( $preload_links->get_html() );
}

Expand Down
Loading