将脚本入队时使用wp_脚本和is_IE有何优势

时间:2016-01-05 作者:Bryan Willis

我读了WP文件,which pointed to this gist 为IE排队的正确方法是使用$wp_styles. 我猜这对于脚本也是正确的。

以这些例子为例

Option One - 使用wp_scripts

add_action(\'wp_print_scripts\', function() {
    global $wp_scripts;
    wp_enqueue_script( \'html5shiv\', \'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\', array( \'bootstrap\' )  );
    $wp_scripts->add_data( \'html5shiv\', \'conditional\', \'lt IE 9\' );
} );
Option Two - 使用wp_scripts 随着is_IE

add_action(\'wp_print_scripts\', function() {
    global $wp_scripts, $is_IE;
    if($is_IE) {
        wp_enqueue_script( \'html5shiv\', \'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\', array( \'bootstrap\' )  );
        $wp_scripts->add_data( \'html5shiv\', \'conditional\', \'lt IE 9\' );
    }
} );
Option Three - 只要在脑海中回响一下:

add_action(\'wp_head\', function(){
    echo \'<!--[if lt IE 9]><script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script><![endif]-->\' . "\\n";
});
Option Four - 将其排到头部:

add_action(\'wp_print_scripts\', function(){
        wp_enqueue_script( \'html5shiv\', \'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\', array( \'bootstrap\' )  );
});
第二种选择。看起来很酷,因为它在非IE浏览器上看起来更干净。但我不确定它是否真的有任何速度优势,或者单是检查是否会使速度减慢更多。除此之外,我似乎不明白为什么选项1比选项3或4更好。

这个问题的原因我使用的是Genesis框架they include HTML5shiv 就像下面的例子,我觉得不太合适:

add_action( \'wp_head\', \'genesis_html5_ie_fix\' );
/**
 * Load the html5 shiv for IE8 and below. Can\'t enqueue with IE conditionals.
 */
function genesis_html5_ie_fix() {
    if ( ! genesis_html5() )
        return;
    echo \'<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->\' . "\\n";
}

3 个回复
最合适的回答,由SO网友:Bryan Willis 整理而成

扩展到@gmazzap 建议在可以使用时不要使用全局变量wp_scripts(), 有一个快捷方式wp_scripts() 用于添加条件注释调用wp_script_add_data 同样地wp_style_add_data 用于条件样式。

因此,从Wordpress 4.2开始,使用条件句的正确方法如下:

/**
 * IE enqueue HTML5shiv with conditionals
 * @link http://tiny.cc/html5shiv
 */
function wpse_213701_enqueue_html5shiv()  {
    wp_enqueue_script( \'html5shiv\',
        \'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\',
        array(),
        false,
        false
    );
    wp_script_add_data( \'html5shiv\', \'conditional\', \'lt IE 9\' );
}
add_action(\'wp_enqueue_scripts\', \'wpse_213701_enqueue_html5shiv\');
然而,上面的例子使用的是HTML5shiv,这是一种独特的情况。从那以后has to 如果你担心一个插件,比如Roots Soil 从头部删除所有脚本。

不过,你很可能不会遇到这种情况。这是一件非常不稳定的事情,因为需要在头部加载很多脚本。在页脚中放置脚本应通过设置$in_footer 将脚本排队时,将变量设置为true。因此,如果你确实使用了根或任何缓存插件,不要计划一切都按照你想要的方式立即运行。

下面是一个你能做的丑陋的例子:

add_action( \'wp_head\', \'wpse_213701_check_html5shiv\', 1 );
function wpse_213701_check_html5shiv() {
    remove_action( \'wp_head\', \'genesis_html5_ie_fix\' );
    if ( !has_filter( \'wp_head\', \'wp_enqueue_scripts\' ) && !wp_script_is( \'html5shiv\', \'done\' ) ) {
        add_action(\'wp_head\', \'wpse_213701_echo_html5shiv\');
        wp_dequeue_script(\'html5shiv\');
    }
}
function wpse_213701_echo_html5shiv() {
    echo \'<!--[if lt IE 9]><script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script><![endif]-->\' . "\\n";
}
尽管这有点过头了,但仍不能保证它会起作用。在过去的4年中,html5shiv有许多名称,这导致它被注册/排队使用几个不同的句柄(html5、html5shiv、html5shim、themename-html5shiv、html5 ie补丁和html5 polyfill,仅举几例)。此外bundled with modernizr. 考虑到这一点,如果您认为上面的示例很荒谬,那么您最好将脚本添加到wp_head 在您的子主题中,因为插件html5shiv句柄很可能会命名为其他名称。

更新(使用这种方法将脚本移动到页脚):

这引发了Roots/Soil Github页面。下面可能是最好的方法(如@grappler ) 并且仍然将脚本移动到页脚。类似的方法发布在@kaiser\'s blog 几年前。

function grappler_move_js_to_footer() 
    $scripts = wp_scripts();
    foreach( $scripts->registered as $script ) {
        if ( \'html5\' == $script->handle ) {
            wp_script_add_data( $script->handle, \'group\', 0 );
        } else {
            wp_script_add_data( $script->handle, \'group\', 1 );
        }
    }
}
add_action( \'wp_enqueue_scripts\', \'grappler_move_js_to_footer\', 99 );
至于马克·卡普兰的建议toscho mentioned here , you shouldn\'t be using option 2\'s $is_IE method. 显然,如果HTTP标头发生变化:用户代理未被发送,您将向缓存后面的用户发送错误的输出,从而导致这些用户的输出中断。关于浏览器侧检测here is a long thread of examples 关于如何做到这一点。即使客户端检测也有它的缺陷。

归根结底,最好的答案可能是不要使用这些方法中的任何一种,忘记旧浏览器,因为Microsoft has dropped support for them as of January 12.

SO网友:Mark Kaplun

选项5是在客户端检测它是什么浏览器,并为您的脚本直接创建一个脚本元素到dom中,就像google analytics和FB SDK一样。

这样做的好处是,只在应该进行浏览器检测的地方进行浏览器检测,并且只在需要时加载IE特定的脚本。

从精神上讲,它与您的第三个选项非常相似,只是更加通用。

旁注:is_IE 像所有其他服务器端浏览器一样,应该避免检测,因为它们会破坏缓存。

SO网友:gmazzap

一般来说,脚本和样式不应直接打印到页面上。

原因是另一个插件或主题可能会再次添加相同的脚本,而您会得到相同的脚本添加2次或更多次。

如果您以正确的方式将资产排队,如果其他代码再次将同一资产排队,则将添加一次。

因此,您应该跳过选项3和4。

关于选项2,如Mark Kaplun pointed out, 它利用服务器端浏览器检测,这从来都不是很实惠的,即使可以,也不要让您选择浏览器的版本,在您的情况下,即使在现代IE版本中,它也会包含脚本,而这并不需要它。

因此,实际上,选项1是您提议的选项中最好的。

我要做的唯一改变是:

使用\'wp_enqueue_scripts\' 操作,而不是\'wp_print_scripts\'使用wp_scripts() 功能istead访问全局类似:

add_action(\'wp_enqueue_scripts\', function() {
    wp_enqueue_script(
       \'html5shiv\',
       \'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\',
       array( \'bootstrap\' ),
       \'3.7.2\',
       false
    );
    wp_scripts()->add_data( \'html5shiv\', \'conditional\', \'lt IE 9\' );
} );
如果另一个插件排队\'html5shiv\' 脚本,它将只添加一次。

请注意,使用上面的代码段,页面上打印的内容是:

<!--[if lt IE 9]>
<script type=\'text/javascript\' src=\'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\'></script>
<![endif]-->
这个条件是由浏览器(客户端)解析的,而不是服务器端解析的,因此它价格合理,并且允许您仅为要针对的IE版本添加脚本。

如果您需要了解有关客户端平台的更多信息(操作系统、屏幕类型和分辨率、浏览器的特定详细版本…)然后,唯一的方法是使用一些javascript来嗅探这些细节,并将脚本动态添加到DOM中(按照Mark Kaplun 解决方案),但如果了解“浏览器系列”和主要版本就足够了,我的建议是使用此解决方案。