Home > Back-end >  PHP: How to preload assets in head?
PHP: How to preload assets in head?

Time:10-26

I'm using two Google fonts and I'm looking to preload those assets, rather than enqueuing them so that they're not flagged in Page Speed Insights.

When I enqueue the fonts, the fonts load correctly. This works:

wp_enqueue_style( 'poppins', '//fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,600;0,700;1,700&display=swap' );

However, when I preload the assets and hook into wp_head, the fonts do not load. This doesn't work (in functions.php):

<?php

function preload_assets() {

    $font_1 = "https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,600;0,700;1,700&display=swap";
    $font_2 = "https://fonts.googleapis.com/css2?family=Roboto Serif:ital,opsz,wght@0,8..144,300;0,8..144,400;1,8..144,200&display=swap";

    // connect to domain of font files
    $preload = '<link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>';

    // optionally increase loading priority
    $preload .= '<link rel="preload" as="style" href="'.$font_1.'">
    <link rel="preload" as="style" href="'.$font_2.'">';


    // async CSS
      $preload .= '<link rel="stylesheet" media="print" onl oad="this.onload=null;this.removeAttribute('."media".');" href="'.$font_1.'">
    <link rel="stylesheet" media="print" onl oad="this.onload=null;this.removeAttribute('."media".');" href="'.$font_2.'">';

    // no-JS fallback
    $preload .= '<noscript>
    <link rel="stylesheet" href="'.$font_1.'">
    <link rel="stylesheet" href="'.$font_2.'">
    </noscript>';

    echo $preload;

}

add_action( 'wp_head', 'preload_assets' );

Why is this? Upon inspecting the source code, I can see the font files being referenced correctly, but the font doesn't show on the front end?

CodePudding user response:

If you refer to the Plugin API/Action Reference, wp_enqueue_scripts is triggered before wp_head which is why.

You should use the script_loader_tag hook filter which filters the HTML script tag of an enqueued script.

<?php

add_action( 'wp_enqueue_scripts', function () {

    $fonts = array(
        array(
            'handle' => 'google-fonts-popins',
            'url' => 'https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,600;0,700;1,700&display=swap',
        ),
        array(
            'handle' => 'google-fonts-roboto',
            'url' => 'https://fonts.googleapis.com/css2?family=Roboto Serif:ital,opsz,wght@0,8..144,300;0,8..144,400;1,8..144,200&display=swap',
        ),
    );

    $i = 0;
    foreach ( $fonts as $font ) {
        $i  ;

        wp_enqueue_style( $font['handle'], $font['url'], array(), 'all' );

        add_filter( 'style_loader_tag', function ( $tag, $handle, $href, $media ) use ( $font, $i ) {
        
            if ( $font['handle'] === $handle ) {
    
                $tag = str_replace(
                    'media="all">',
                    'media="all"><link rel="preload" as="style" href="' . $href . '">
                    <link rel="stylesheet" media="print" onl oad="this.onload=null;this.removeAttribute(\'media\');" href="' . $href . '">
                    <noscript><link rel="stylesheet" href="' . $href . '"></noscript>',
                    $tag
                );

                if ( 1 === $i ) {

                    $tag .= '<link rel="preconnect" href="https://fonts.googleapis.com">
                    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>';

                };
    
            };
    
            return $tag;
    
        }, 10, 4 );

    };

} );
  • Related