問題描述

我閱讀了 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_scriptsis_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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。