69

我在我的一个 WordPress 域中有各种 javascript,它们是必要的插件,我知道它在 php 文件中的哪个位置被调用。

我正在采取我可以采取的一切措施来加快页面加载时间,并且网络上的每个速度测试人员都说尽可能推迟 javascripts。

我已经阅读了 javascript 中的defer='defer'异步函数,我认为其中之一将完成我想要完成的任务。但我不明白如何在 php 文件中这样做。

例如,下面是一个特定插件的 php 文件的片段,其中调用了 javascript 文件:

function add_dcsnt_scripts() {

    wp_enqueue_script( 'jquery' );
    wp_enqueue_script( 'dcsnt', dc_jqsocialtabs::get_plugin_directory() . '/js/jquery.social.media.tabs.1.7.1.min.js' );

}

我读过最好做这样的事情来加快页面加载时间:

<script defer async src="..."></script>

但我不知道如何在 php 文件中实现这一点。我想对我所有的 javascript 文件执行此操作。

我将如何完成将此 javascript 片段延迟或异步到最后加载并加快页面加载时间?在所有浏览器中增加页面加载时间的理想方法是什么?感谢任何人都可以提供的任何指导!

4

10 回答 10

62

或更通用的方式:

function add_async_forscript($url)
{
    if (strpos($url, '#asyncload')===false)
        return $url;
    else if (is_admin())
        return str_replace('#asyncload', '', $url);
    else
        return str_replace('#asyncload', '', $url)."' async='async"; 
}
add_filter('clean_url', 'add_async_forscript', 11, 1);

因此,您可以在不更改代码的情况下将异步添加到任何脚本,只需将 #asyncload 添加到脚本 url,如下所示:

wp_enqueue_script('dcsnt', '/js/jquery.social.media.tabs.1.7.1.min.js#asyncload' )
于 2013-12-19T02:21:31.040 回答
52

为了让事情在某种程度上保持模块化和包罗万象,下面的方法动态地选择如何通过在 $handle 名称上附加一个小标识符来嵌入带有 async 或 defer 属性的标签:

/**
* Add async or defer attributes to script enqueues
* @author Mike Kormendy
* @param  String  $tag     The original enqueued <script src="...> tag
* @param  String  $handle  The registered unique name of the script
* @return String  $tag     The modified <script async|defer src="...> tag
*/
// only on the front-end
if(!is_admin()) {
    function add_asyncdefer_attribute($tag, $handle) {
        // if the unique handle/name of the registered script has 'async' in it
        if (strpos($handle, 'async') !== false) {
            // return the tag with the async attribute
            return str_replace( '<script ', '<script async ', $tag );
        }
        // if the unique handle/name of the registered script has 'defer' in it
        else if (strpos($handle, 'defer') !== false) {
            // return the tag with the defer attribute
            return str_replace( '<script ', '<script defer ', $tag );
        }
        // otherwise skip
        else {
            return $tag;
        }
    }
    add_filter('script_loader_tag', 'add_asyncdefer_attribute', 10, 2);
}

示例用法:

function enqueue_my_scripts() {

    // script to load asynchronously
    wp_register_script('firstscript-async', '//www.domain.com/somescript.js', '', 2, false);
    wp_enqueue_script('firstscript-async');

    // script to be deferred
    wp_register_script('secondscript-defer', '//www.domain.com/otherscript.js', '', 2, false);
    wp_enqueue_script('secondscript-defer');


    // standard script embed
    wp_register_script('thirdscript', '//www.domain.com/anotherscript.js', '', 2, false);
    wp_enqueue_script('thirdscript');
}
add_action('wp_enqueue_scripts', 'enqueue_my_scripts', 9999);

输出:

<script async type='text/javascript' src='//www.domain.com/somescript.js'></script>
<script defer type='text/javascript' src='//www.domain.com/otherscript.js'></script>
<script type='text/javascript' src='//www.domain.com/anothercript.js'></script>

感谢@MattKeys @crissoca 在这里启发了我的回答。

于 2016-11-11T18:02:12.530 回答
40

博客文章链接到两个感兴趣的插件:

异步 Javascript
通过使用 head.js 异步加载 javascript 来提高页面加载性能

WP Deferred Javascripts
使用 LABJS(一个异步 javascript 库)延迟加载使用 wp_enqueue_scripts 添加的所有 javascripts。

还没有测试过它们,但检查了代码,它们在 WordPress 脚本排队过程中做了非常漂亮的事情。

但随后WPSE 来救援

// Adapted from https://gist.github.com/toscho/1584783
add_filter( 'clean_url', function( $url ) {
    if ( FALSE === strpos( $url, '.js' ) ) {
        // not our file
        return $url;
    }
    // Must be a ', not "!
    return "$url' defer='defer";
}, 11, 1 );
于 2013-09-22T14:59:03.337 回答
18

另一种使用不同过滤器的解决方案,可用于针对特定脚本句柄:

function frontend_scripts()
{
    wp_enqueue_script( 'my-unique-script-handle', 'path/to/my/script.js' );
}
add_action( 'wp_enqueue_scripts', 'frontend_script' );

function make_script_async( $tag, $handle, $src )
{
    if ( 'my-unique-script-handle' != $handle ) {
        return $tag;
    }

    return str_replace( '<script', '<script async', $tag );
}
add_filter( 'script_loader_tag', 'make_script_async', 10, 3 );
于 2015-02-05T01:41:19.800 回答
16

一种简化的方法。添加到您的 functions.php 文件以使 JavaScript 在 Wordpress 中异步

// Make JavaScript Asynchronous in Wordpress
add_filter( 'script_loader_tag', function ( $tag, $handle ) {    
    if( is_admin() ) {
        return $tag;
    }
    return str_replace( ' src', ' async src', $tag );
}, 10, 2 );
于 2015-09-01T19:59:39.003 回答
6

很少修改代码Mike Kormendy,它允许您一次添加 2 个属性:

// Async load
function add_asyncdefer_attribute($tag, $handle)
{
    $param = '';
    if ( strpos($handle, 'async') !== false ) $param = 'async ';
    if ( strpos($handle, 'defer') !== false ) $param .= 'defer ';
    if ( $param )
        return str_replace('<script ', '<script ' . $param, $tag);
    else
        return $tag;
}

结果:

<script async defer type='text/javascript' src='#URL'></script>
于 2017-02-08T10:37:23.030 回答
5

要控制要延迟的 js 文件并避免冲突,您可以将变量附加到 wp_register_script 函数中的 url,如下所示。

wp_register_script( 'menu', get_template_directory_uri() . '/js/script.js?defer', array('jquery'), '1.0', true );

然后换行:

if ( FALSE === strpos( $url, '.js' ))

至:

if ( FALSE === strpos( $url, '.js?defer' ))

新过滤器看起来像这样。

add_filter( 'clean_url', function( $url )
{
    if ( FALSE === strpos( $url, '.js?defer' ) )
    { // not our file
    return $url;
    }
    // Must be a ', not "!
    return "$url' defer='defer";
}, 11, 1 );
于 2014-04-02T14:32:32.320 回答
3

我认为延迟/异步 WordPress jQuery 是不好的做法。更好的解决方案是从过滤器中排除 jQuery :

if (!is_admin()) {
    add_filter( 'script_loader_tag', function ( $tag, $handle ) {    
        if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") ) {
            return $tag;
        }
        return str_replace( ' src', ' async src', $tag );
    }, 10, 2 );
}

您可以使用defer而不是async

于 2016-12-08T11:21:00.533 回答
1

添加clean_url过滤器解决方案的东西,确保验证仅在字体端使用它,也许使用if( ! is_admin() ){}像 ACF 这样的流行插件可能会让你头疼。

更新

这是我修改后的解决方案:

if( ! is_admin() ){
  add_filter( 'clean_url', 'so_18944027_front_end_defer', 11, 1 );
  function so_18944027_front_end_defer( $url ) {
    if ( FALSE === strpos( $url, '.js' ) )
    { // not our file
        return $url;
    }
    // Must be a ', not "!
    return "$url' defer='defer";
  }
}
于 2015-04-28T02:04:48.953 回答
1

async属性合并到脚本中,以便仅在加载整个页面后才加载它们

<script type="text/javascript">
    function ngfbJavascript( d, s, id, url ) {
        var js, ngfb_js = d.getElementsByTagName( s )[0];
        if ( d.getElementById( id ) ) return;
        js = d.createElement( s );
        js.id = id;
        js.async = true;
        js.src = url;
        ngfb_js.parentNode.insertBefore( js, ngfb_js );
    };
</script>

来源:这里

于 2013-12-28T09:17:34.393 回答