简体   繁体   English

我如何推迟或异步此 WordPress javascript 代码段最后加载以加快页面加载时间?

[英]How do I defer or async this WordPress javascript snippet to load lastly for faster page load times?

I have various javascripts that are necessary plugins in one of my WordPress domains, and I know where in the php file it's called from.我有各种 javascript,它们是我的 WordPress 域之一中的必要插件,并且我知道它在 php 文件中的哪个位置被调用。

I'm taking every measure I can take to speed up page loading times , and every speed tester on the web says to defer javascripts if possible.我正在采取一切措施来加快页面加载时间,并且网络上的每个速度测试员都说如果可能的话推迟 javascripts。

I have read about the defer='defer' and the async functions in javascript and I think one of these will accomplish what I'm trying to accomplish.我已经阅读了关于defer='defer'和 javascript 中的异步函数的内容,我认为其中之一将完成我想要完成的任务。 But I'm not understanding how I'd do so in a php file.但我不明白如何在 php 文件中这样做。

For instance, here is a snippet from one particular plugin's php file where the javascript file is being called:例如,这里是一个特定插件的 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' );

}

I've read that it's best to do something like this for faster page loading times:我读过最好做这样的事情以加快页面加载时间:

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

But I don't know how to accomplish that within a php file.但我不知道如何在 php 文件中完成它。 I want to do this with all of my javascript files.我想用我所有的 javascript 文件来做这个。

How would I accomplish deferring or asyncing this javascript snippet to is loads last and speeds up page load times ?我将如何实现将此 javascript 代码段延迟或异步到最后加载并加快页面加载时间 What would be the ideal way to increase page load times across all browsers?在所有浏览器中增加页面加载时间的理想方法是什么? Thanks for any guidance anybody can offer!感谢任何人可以提供的任何指导!

Or more universal way:或更普遍的方式:

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);

so you can add async to any script without code changes, just add #asyncload to script url as:因此您可以在不更改代码的情况下将异步添加到任何脚本,只需将 #asyncload 添加到脚本 url 为:

wp_enqueue_script('dcsnt', '/js/jquery.social.media.tabs.1.7.1.min.js#asyncload' )

Trying to keep things somewhat modular and all encompassing, the following approach dynamically chooses how to embed the tag with the async or defer attributes by just appending a small identifier to the $handle name:为了让事情有点模块化和包罗万象,以下方法动态选择如何通过将一个小标识符附加到 $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);
}

Example usage:用法示例:

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);

Outputs:输出:

<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>

Thanks to @MattKeys @crissoca for inspiring my answer here.感谢@MattKeys @crissoca 在这里启发我的回答。

This blog post links to two plugins of interest:这篇博文链接到两个感兴趣的插件:

Asynchronous Javascript 异步 Javascript
Improve page load performance by asynchronously loading javascript using head.js通过使用 head.js 异步加载 javascript 来提高页面加载性能

WP Deferred Javascripts WP 延迟 Javascript
Defer the loading of all javascripts added with wp_enqueue_scripts, using LABJS (an asynchronous javascript library).使用 LABJS(一个异步 javascript 库)推迟加载所有使用 wp_enqueue_scripts 添加的 javascript。

Haven't tested them but checked the code and they do pretty fancy stuff with WordPress scripts enqueuing process.尚未测试它们,但检查了代码,它们使用 WordPress 脚本排队过程做了非常漂亮的事情。

But then WPSE comes to rescue :但随后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 );

Another solution using a different filter, which can be used to target a specific script handle:使用不同过滤器的另一种解决方案,可用于针对特定脚本句柄:

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 );

A simplified method.一种简化的方法。 Add to your functions.php file to make make JavaScript asynchronous in Wordpress添加到您的 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 );

Very little modification code Mike Kormendy , which allows you to add 2 attributes at once:很少修改代码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;
}

Result:结果:

<script async defer type='text/javascript' src='#URL'></script>

To gain control over which js files to defer and avoid conflicts you can append a variable to the url in the wp_register_script function like below.要控制要推迟哪些 js 文件并避免冲突,您可以将变量附加到 wp_register_script 函数中的 url 中,如下所示。

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

Then change the line:然后换行:

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

To:到:

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

The new filter looks like this.新过滤器看起来像这样。

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 );

I believe it's bad practice to defer/async WordPress jQuery.我认为延迟/异步 WordPress jQuery 是不好的做法。 Better solution would be to exclude jQuery from the filter:更好的解决方案是从过滤器中排除 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 );
}

You can use defer instead of async您可以使用defer而不是async

Incorporate the async attribute to the scripts so that they are only loaded once the whole page is loadedasync属性合并到脚本中,以便仅在加载整个页面后才加载它们

<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>

Source: Here来源: 这里

Something to add the clean_url filter solution, make sure to validate to use it only on the font-end maybe using if( ! is_admin() ){} popular plugins like ACF might give you a headache.添加clean_url过滤器解决方案的东西,确保验证仅在字体端使用它,也许使用if( ! is_admin() ){}流行的插件,如 ACF 可能会让你头疼。

Update更新

Here is my modified version of the solution:这是我修改后的解决方案版本:

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";
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM