問題描述
我閲讀了 WP 文檔,which pointed to this gist,正確的方式來排列 IE 的樣式是通過使用 $wp_styles 。我猜測這對於腳本也是如此。
以這些例子為例
選項一 – 使用 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' );
} );
選項二 – 使用 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' );
}
} );
選擇三 – 只是回頭説:
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";
});
選項四 – 將其排列在頭上:
add_action('wp_print_scripts', function(){
wp_enqueue_script( 'html5shiv', 'https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js', array( 'bootstrap' ) );
});
第二個選擇。看起來很酷,因為它在 non-IE 瀏覽器上看起來有點乾淨。但是我不知道它是否具有任何速度優勢,或者單獨的檢查會減慢。除此之外,我似乎無法弄清楚選項一比選項 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";
}
最佳解決方案
而選項 5 是在客户端檢測它是什麼瀏覽器,併為您的腳本直接創建一個腳本元素到 dom,像 google 分析一個 FB SDK 。
這樣做的優點是隻在需要完成的地方進行瀏覽器檢測,瀏覽器和僅在需要時加載 IE 特定的腳本。
在精神上,它非常類似於你的第三個選擇,只是更通用。
Sidenote:is_IE 像所有其他服務器端瀏覽器檢測一樣應該避免,因為它們會中斷緩存。
次佳解決方案
一般來説,腳本和樣式不應直接打印到頁面。
原因是另一個插件或主題可能再次添加相同的腳本,並且您獲得相同的腳本添加了兩次或更多次。
如果您以正確的方式排隊資產,如果其他代碼再次排入同一個資產,則會添加一次。
因此,您應該跳過選項 3 和 4 。
關於方案 2,作為 Mark Kaplun pointed out,它利用 server-side 瀏覽器檢測,這是永遠不會很實惠的,即使這樣,不要讓你選擇瀏覽器的版本,在你的情況下,它將包括腳本甚至在現代的 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 版本添加腳本。
如果您需要更多地瞭解客户端平台 (OS,屏幕類型和分辨率,瀏覽器的具體詳細版本…),則唯一的方法是使用一些 javascript 來嗅探這些細節,並將腳本動態添加到 DOM(按照 Mark Kaplun 解決方案),但是如果知道”browser family” 和主要版本對你來説足夠了,我的建議是使用這個解決方案。
第三種解決方案
要擴展使用 wp_scripts()時,不要使用全局變量的 @gmazzap 建議,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,這是一個獨特的情況。因為它必須被加載到頭部,所以你可以像下面的例子那樣做一些例子,如果你擔心像 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-fix 和 html5-polyfill 等等) 。此外,它通常是 bundled with modernizr 。考慮到這一點,如果你認為上面的例子是荒謬的,那麼你也可以將腳本添加到你的孩子主題中的 wp_head 中,因為插件 html5shiv 句柄最有可能命名為別的東西。
更新 (使用此方法將腳本移動到頁腳):
這引發了對 Roots/Soil Github 頁面的一些操作。這可能是最好的方法 (由 @grappler 建議),仍然將腳本移動到頁腳。幾年前,@ kaiser 的 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 );
至於 Mark Kaplan 的建議和什麼 toscho mentioned here,你不應該使用選項 2 的 $ is_IE 方法。顯然,如果 HTTP 標頭 Vary:User-Agent 沒有被髮送,你將向高速緩存中的用户發送錯誤的輸出,導致這些用户中斷。關於瀏覽器端檢測 here is a long thread of examples 可以做些什麼。即使是 client-side 檢測也有其陷阱。
在一天結束的時候,也許最好的答案是不要使用任何這些方法,並忘記了自 Microsoft has dropped support for them as of January 12 以來的遺留瀏覽器。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。