IE 都更持續進行中,現階段有部分網頁需同時支援 IE、Edge、Chrome,甚至要區別 IE 文件模式決定回傳 HTML5 或是 IE Only 內容。

目前會遇到的 IE 清一色都是 IE11,只差在會切換不同的文件模式(如下圖),而文件模式主要由 HTML 中的 <meta http-equiv="x-ua-compatible" content="IE=N"> 控制。當 IE=Edge,由 F12 可觀察到文件模式的預設值為 11:

X-UA-Compatible 會改變 UserAgent,一般在伺服器端會用它判斷 IE 模式:

var m = Regex.Match(Request.UserAgent, "MSIE (?<n>[0-9]+)");
if (!m.Success) {
    //IE=Edge, HTML5
}
else {
    var ieVer = int.Parse(m.Groups["n"].Value);
    //ieVer = 5, 7, 8, 9, 10
}

依我的認知,若網頁有加 <meta http-equiv="x-ua-compatible" content="IE=Edge">,除非使用者開 F12 強制改模式,否則 UserAgent 應為 Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko,程式可依此判斷傳回 IE-Only 或 HTML5 內容。

不料,接獲通報部分使用者的 IE11 在 X-UA-Compatible IE=Edge 時仍看到 IE-Only 內容。

調查過程,先發現一件事:IE11 跟著作業系統,不同版本的 Windows 10,IE11 版本不同,行為可能存在小差異 (登楞!)。

隨意抽樣一些 Windows 10 LTSC 的 IE11,有 1607 (OS Build 14393.5192)、1809 (OS Build 11763.3046)、1909 (OS Build 18363.1734)... 等版號。我自己的 1909 機器沒問題,而能重現問題的兩台機器剛好都是 1607,在 X-UA-Compatible IE=Edge 時,傳送的 UserAgent 卻是 Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)。於是,這很容易導出「問題出在 1607 IE11 版本」的推論。但科學辦案講求大膽假設,小心求證,繼續再試了幾台機器,發現另一台 1809 也觀察到 compatible; MSIE 7.0;, 1607 幸獲不在場證明,無保請回。(也幸好夠謹慎,沒有草率下結論砸了招牌。)

進一步推敲,想到另一個可能 - 相容性檢視設定!

用個實驗驗證,開啟 IE11 連上 User Agent String.Com,正常情況下會判定為 IE11:

動個手腳將 useragentstring.com 加入相容性檢視網站清單:

IE11 便會被識別成 IE7,跟我程式遇到的狀況一樣:

但要注意,上面所說的 UserAgent 指的是伺服器端接受到瀏覽器資訊,前端 JavaScript 讀取到的 navigator.userAgent 及實際文件模式仍由 <meta http-equiv="x-ua-compatible" content="IE=*"> 決定,用以下 ASP.NET 來驗證:

<%@Page Language="C#"%>
<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="x-ua-compatible" content="IE=Edge">
		<style>
			div { font-size: 9pt; font-family: Consolas; }
			span { color: purple; }
		</style>
	</head>
	<body>
		<div>Server UserAgent = <span><%=Request.UserAgent%></span></div>
		<div>Client userAgent = <span id=ua></span></div>
		<div>msCrypto = <span id=crypto></span></div>
		<script>
			document.getElementById('ua').innerText = navigator.userAgent;
			document.getElementById('crypto').innerText = window.msCrypto; //IE11 才支援的 API
		</script>
	</body>
</html>

故意將網站加入相容性檢視網站清單 (1),ASP.NET 端收到的 Request.UserAgent 變成 MSIE 7.0 (2),但如果回傳 <meta http-equiv="x-ua-compatible" content="IE=Edge">(3),IE 仍會以其為準切成 IE11 文件模式 (4),JavaScript 讀取的也是 IE11 的 navigator.userAgent (5)。

這個發現,打破了『當遇到舊 IE 相容模式要配合輸出 IE Only 內容』的迷思,若網頁己改為適用 IE11 的 HTML5 版本,即使 IE 將網站設成相容性檢視,我們仍可無視傳入的 UserAgent 內容,透過 X-UA-Compatible IE=Edge 強迫設定 IE 文件模式,大方顯示 HTML5 內容。

Study of user agent behavior of IE under compatible view and different document modes.


Comments

Be the first to post a comment

Post a comment