我在 Internet Explorer 8 上使用了一天的網絡
已發表: 2022-03-10這篇文章是我嘗試在各種限制下使用網絡的系列文章的一部分,代表給定的用戶群體。 我希望提高真實人們面臨的困難的形象,如果我們以一種同情他們需求的方式進行設計和開發,這些困難是可以避免的。
上次,我使用屏幕閱讀器瀏覽了一天的網絡。 這一次,我使用了 Internet Explorer 8,它於十年前的今天,即 2009 年 3 月 19 日發布。
世界上誰在使用 IE8?
在我們開始之前; 免責聲明:我不會告訴你你需要開始支持 IE8。
完全有理由不支持 IE8。 微軟三年多前正式停止支持 IE8、IE9 和 IE10,微軟高管甚至告訴你停止使用 Internet Explorer 11。
但是,儘管我們開發人員希望它消失,但它只是。 慣於。 死。 IE8 繼續出現在瀏覽器統計數據中,尤其是在西方世界的泡沫之外。
瀏覽器統計數據必須謹慎對待,但目前對全球 IE8 使用量的估計約為桌面市場份額的 0.3% 至 0.4%。 估計的下限來自 w3counter:

較高的估計來自 StatCounter(“我可以使用”使用表使用的相同數據源)。 它估計全球 IE8 桌面瀏覽器的比例在 0.37% 左右。

我懷疑我們可能會在某些地理區域看到更高的 IE8 使用率,因此按大陸深入研究數據。
按地區劃分的 IE8 使用情況
這是每個大陸的 IE8 桌面比例(2018 年 2 月至 2019 年 1 月的數據):
1. | 大洋洲 | 0.09% |
2. | 歐洲 | 0.25% |
3. | 南美洲 | 0.30% |
4. | 北美 | 0.35% |
5. | 非洲 | 0.48% |
6. | 亞洲 | 0.50% |
亞洲人使用 IE8 的可能性是大洋洲人的五倍。
我更仔細地查看了亞洲的統計數據,注意到每個國家/地區的 IE8 使用比例。 IE8 使用率排名前六位的國家非常明確,之後數字下降到與世界平均水平相當:
1. | 伊朗 | 3.99% |
2. | 中國 | 1.99% |
3. | 北朝鮮 | 1.38% |
4. | 土庫曼斯坦 | 1.31% |
5. | 阿富汗 | 1.27% |
6. | 柬埔寨 | 1.05% |
7. | 也門 | 0.63% |
8. | 台灣 | 0.62% |
9. | 巴基斯坦 | 0.57% |
10. | 孟加拉國 | 0.54% |
這些數據總結在下面的地圖中:

令人難以置信的是,IE8 約佔伊朗桌面用戶的 4%——是大洋洲 IE8 用戶比例的40 倍。
接下來,我查看了非洲的國家統計數據,因為它的 IE8 總體使用率與亞洲大致相同。 有一個明顯的贏家(厄立特里亞),其次是一些使用率高於或接近 1% 的國家:
1. | 厄立特里亞 | 3.24% |
2. | 博茨瓦納 | 1.37% |
3. | 蘇丹和南蘇丹 | 1.33% |
4. | 尼日爾 | 1.29% |
5. | 莫桑比克 | 1.19% |
6. | 毛里塔尼亞 | 1.18% |
7. | 幾內亞 | 1.12% |
8. | 剛果民主共和國 | 1.07% |
9. | 贊比亞 | 0.94% |
這在下面的地圖中進行了總結:

亞洲的 IE8 使用率高於正常水平的國家在地理上大致分批在一起,而非洲似乎沒有這種模式。 我能看到的唯一模式——除非是巧合——是一些世界上最大的 IE8 使用國家以審查互聯網訪問而聞名,因此可能不鼓勵或允許更新到更安全的瀏覽器。
如果您的網站針對的是純粹的西方受眾,那麼您不太可能關心 IE8。 但是,如果您有一個蓬勃發展的亞洲或非洲市場——特別是如果您關心中國、伊朗或厄立特里亞的用戶——您可能會非常關心您網站的 IE8 體驗。 是的——即使是在 2019 年!
誰還在使用 IE?
那麼,這些人是誰? 他們真的走在我們中間嗎?!
無論他們是誰,您都可以打賭他們使用舊瀏覽器並不是為了惹惱您。 沒有人故意選擇更糟糕的瀏覽體驗。
由於以下原因,有人可能正在使用舊瀏覽器:
- 缺乏認識
他們根本不知道他們正在使用過時的技術。 - 教育的缺失
他們不知道向他們開放的升級選項和替代瀏覽器。 - 缺乏規劃
忽略升級提示,因為它們很忙,但沒有在安靜時期升級的先見之明。 - 厭惡改變
上次他們升級軟件時,他們不得不學習新的用戶界面。 “如果它沒有壞,就不要修理它。” - 厭惡風險
他們最後一次升級時,他們的機器慢得像爬行,或者他們失去了他們最喜歡的功能。 - 軟件限制
他們的操作系統太舊,無法升級,或者他們的管理員權限可能被鎖定。 - 硬件限制
較新的瀏覽器通常對您的硬盤空間、內存和 CPU 要求更高。 - 網絡限制
數據上限或連接速度較慢意味著他們不想下載 75MB 的軟件。 - 法律限制
它們可能位於僅允許使用一種特定瀏覽器的公司機器上。
世界上還有人死守IE8,真的有這麼大的驚喜嗎?
我決定設身處地為其中一位匿名人士著想,並使用 IE8 瀏覽網頁一天。 你可以在家一起玩! 從 Microsoft 網站下載“Windows 7 上的 IE8”虛擬機,然後在 VirtualBox 等虛擬機中運行它。
IE8 虛擬機:糟糕的開端
我啟動了我的 IE8 虛擬機,期待地點擊了 Internet Explorer 程序,這就是我所看到的:

嗯,好吧。 看起來 IE8 拉出的默認網頁不再存在。 嗯,這個數字。 微軟已經正式停止對 IE8 的支持,為什麼還要確保 IE8 登陸頁面仍然有效?
我決定切換到世界上使用最廣泛的網站。
谷歌

這是一個簡單的網站,因此很難出錯 - 但公平地說,它看起來很棒! 我試著搜索一些東西:

搜索工作正常,儘管佈局看起來與我習慣的有點不同。 然後我想起來了——當我在互聯網上使用了一天並且關閉了 JavaScript 時,我看到了相同的搜索結果佈局。
作為參考,以下是啟用 JavaScript 的現代瀏覽器中搜索結果的外觀:

因此,看起來 IE8 獲得了無 JS 版本的 Google 搜索。 我認為這不一定是一個深思熟慮的設計決定——可能只是 JavaScript 出錯了:

儘管如此,最終結果對我來說還是不錯的——我得到了我的搜索結果,這就是我想要的。
我點擊觀看了 YouTube 視頻。
YouTube

這個頁面有很多問題。 所有這些都與 IE 中的小怪癖有關。
例如,徽標被放大和裁剪。 這歸結為 IE8 不支持 SVG,而我們實際看到的是 YouTube 提供的後備選項。 他們應用了background-image
CSS 屬性,以便在不支持 SVG 的情況下,您將嘗試顯示徽標。 只有他們似乎沒有正確設置background-size
,所以放大了一點。

span
上設置了一個background-img
,它會引入一個 sprite。 (大預覽)作為參考,這是 Chrome 中的同一頁面(請參閱 Chrome 如何呈現 SVG):

那自動播放切換呢? 它呈現為一個看起來很奇怪的複選框:

這似乎歸結為使用了自定義元素(紙張切換按鈕,這是一個 Material Design 元素),IE 不理解:

paper-toggle-button
是一個自定義元素。 (屏幕截圖來自 Chrome DevTools,以及自動播放切換應該如何呈現。)(大預覽) 我並不驚訝這沒有正確呈現; IE8 甚至無法處理我們這些天使用的基本語義標記。 嘗試使用<aside>
或<main>
,它基本上會將它們呈現為 div,但忽略您應用於它們的任何樣式。
要啟用 HTML5 標記,您必須明確告訴瀏覽器這些元素存在。 然後可以將它們設置為正常樣式:
<!--[if lt IE 9]> <script> document.createElement('header'); document.createElement('nav'); document.createElement('section'); document.createElement('article'); document.createElement('aside'); document.createElement('footer'); </script> <![endif]-->
順便說一句,它包含在 IE 條件中。 <!--[if lt IE 9]>
是大多數瀏覽器的 HTML 註釋——因此會被跳過——但在 IE 中它是一個條件,它只傳遞“如果小於 IE 9”,它在其中執行/呈現 DOM 節點在其中。
所以,視頻頁面是失敗的。 直接訪問 YouTube.com 也好不到哪裡去:

沒有被嚇倒,我忽略了警告並嘗試在 YouTube 的搜索欄中搜索視頻。

IE8 流量顯然很可疑,以至於 YouTube 不相信我是真正的用戶,因此決定不處理我的搜索請求!
註冊 Gmail
如果我要花一天時間在 IE8 上,我將需要一個電子郵件地址。 所以我開始嘗試建立一個新的。
首先,我嘗試了 Gmail。

這裡的圖像和文字有點不對勁。 我認為這歸結於 IE8 不支持媒體查詢這一事實——所以它試圖在桌面上向我展示移動圖像。
解決這個問題的一種方法是使用 Sass 生成兩個樣式表; 一種用於現代瀏覽器,一種用於舊版 IE。 您可以通過使用 mixin 進行媒體查詢來獲得 IE 友好、移動優先的 CSS(請參閱 Jake Archibald 的教程)。 mixin 會“扁平化”你的舊版 IE CSS 以將 IE 視為總是一個特定的預定義寬度(例如 65em),只給出與該寬度相關的 CSS。 在這種情況下,我會看到我假設的屏幕尺寸的正確background-image
,並獲得更好的體驗。
無論如何,它並沒有阻止我點擊“創建帳戶”。 它在 IE8 和現代瀏覽器中的外觀有一些差異:

雖然乍一看很有希望,但表格填寫起來卻很麻煩。當您開始填寫字段時,“標籤”不會妨礙您,因此您的輸入文本會被混淆:

這個標籤的標記實際上是一個<div>
,一些聰明的 JS 在輸入焦點時將文本移開。 JS 在 IE8 上沒有成功,所以文本固執地保持在原地。

div
,它使用 CSS 覆蓋在表單輸入上。 (大預覽)填寫完所有詳細信息後,我點擊“下一步”,然後等待。 沒啥事兒。
然後我注意到我的 IE 窗口左下方的黃色小警告符號。 我點擊它,看到它在抱怨 JS 錯誤:

我放棄了 Gmail,轉而使用 MSN。
註冊 Hotmail
我開始擔心電子郵件可能會成為使用了 10 年的瀏覽器的禁區。 但是當我訪問 Hotmail 時,註冊表單看起來還不錯——到目前為止還不錯:

然後我注意到一個驗證碼。 我想,“我不可能熬過這個……”

令我驚訝的是,驗證碼有效!
表單上唯一奇怪的是標籤位置有些錯誤,但註冊在其他方面是無縫的:

你覺得那個截圖還可以嗎? 你能發現故意的錯誤嗎?
最左邊的輸入應該是我的名字,而不是我的姓氏。 當我稍後返回並檢查此頁面時,我單擊“名字”標籤並將焦點應用於最左側的輸入,這就是我可以首先檢查我是否填寫了正確的框。 這顯示了可訪問標記的重要性——即使沒有 CSS 和視覺關聯,我也可以準確地確定哪個輸入框應用於哪個標籤(儘管是第二次!)。
無論如何,我能夠完成註冊過程並被重定向到 MSN 主頁,這非常棒。

我什至可以閱讀文章並忘記我使用的是 IE8:

註冊了我的電子郵件後,我已經準備好去看看互聯網的其餘部分了!
我訪問了 Facebook 網站並立即被重定向到移動網站:

這是一個聰明的後備策略,因為 Facebook 需要在低端移動設備上支持大量的全球受眾,所以無論如何都需要提供 Facebook 的基本版本。 為什麼不向舊的桌面瀏覽器提供相同的體驗基準呢?
我嘗試註冊並能夠創建一個帳戶。 偉大的! 但是當我登錄該帳戶時,我受到了懷疑——就像我在 YouTube 上搜索東西時一樣——並且面臨著驗證碼。
只是這一次,可沒那麼容易。

我嘗試了幾次請求新代碼並刷新頁面,但驗證碼圖像從未加載,因此我實際上被鎖定在我的帳戶之外。
那好吧。 讓我們嘗試更多的社交媒體。
推特
我訪問了 Twitter 網站並獲得了完全相同的移動重定向體驗。

但是這次我什至無法註冊一個帳戶:

奇怪的是,Twitter 很樂意讓你登錄,但不是讓你首先註冊。 我不知道為什麼——也許它的註冊頁面上有類似的 CAPTCHA 場景,這在舊版瀏覽器上不起作用。 無論哪種方式,我都無法創建新帳戶。
使用我現有的 Twitter 帳戶登錄時,我感到很尷尬。 稱我為偏執狂,但像 2013 年的 CFR Watering Hole 攻擊這樣的漏洞——在 IE8 中訪問特定 URL 的行為就會將惡意軟件安裝到你的機器上——讓我擔心我可能會危及我的帳戶。
但是,為了教育,我堅持了下來(用一個臨時的新密碼):

我也可以發推文,儘管使用的是非常基本的<textarea>
:

總之,Twitter 在 IE8 中基本上沒問題——只要你已經有一個帳戶!
我已經完成了這一天的社交媒體。 我們去看看一些新聞。
英國廣播公司的新聞

新聞主頁看起來非常基本且笨拙,但基本上可以正常工作——儘管有混合內容安全警告。
看看標誌。 正如我們已經在 YouTube 上看到的,IE8 不支持 SVG,所以我們需要一個 PNG 後備。
BBC 使用<image>
後備技術在 IE 上渲染 PNG:

…並在 SVG 可用時忽略 PNG:

image
部分被忽略, svg
渲染得很好。 (大預覽) 這種技術利用了舊瀏覽器過去同時遵守<image>
和<img>
標籤的事實,因此將忽略未知的<svg>
標籤並呈現回退,而現代瀏覽器在 SVG 中忽略呈現<image>
。 Chris Coyier 更詳細地解釋了這項技術。
我嘗試查看一篇文章:

它是可讀的。 我可以看到標題、導航、特色圖片。 但是其餘的文章圖片都不見了:

這是意料之中的,並且是由於 BBC 延遲加載圖像。 IE8 不是“受支持的瀏覽器”意味著它沒有獲得啟用延遲加載的 JavaScript,因此圖像根本不會加載。
出於興趣,我想看看如果我嘗試訪問 BBC iPlayer 會發生什麼:

這讓我想知道另一個流媒體服務。
網飛
當我在 IE8 中加載 Netflix 時,我有一半期待一個空白頁面。 當我真正看到一個不錯的目標網頁時,我感到很驚喜:

我將此與現代 Chrome 版本進行了比較:


號召性用語(按鈕文本)略有不同——可能取決於多變量測試,而不是我使用的瀏覽器。
渲染的不同之處在於集中的文本和半透明的黑色覆蓋。
缺少集中文本是因為 Netflix 使用 Flexbox 來對齊項目:

justify-content: center
來對齊其文本。 (大預覽) 此類上的text-align: center
可能會修復 IE8(實際上是所有舊瀏覽器)的居中問題。 為了獲得最大的瀏覽器支持,您可以使用舊的“安全”CSS 遵循 CSS 後備方法,然後為支持它的瀏覽器使用更現代的 CSS 來加強佈局。
缺少背景是由於使用了rgba()
,IE8 及更低版本不支持。

rgba(0,0,0,.5)
背景對舊版瀏覽器毫無意義。 (大預覽)傳統上提供這樣的 CSS 回退是很好的,它為舊瀏覽器顯示黑色背景,但為現代瀏覽器顯示半透明背景:
rgb(0, 0, 0); /* IE8 fallback */ rgba(0, 0, 0, 0.8);
這是一個非常特定於 IE 的修復程序,但是,基本上所有其他瀏覽器都支持rgba
。 此外,在這種情況下,你會完全失去花哨的 Netflix 磁貼,所以最好根本沒有背景過濾器! 確保跨瀏覽器支持的可靠方法是將過濾器烘焙到背景圖像本身中。 簡單但有效。
無論如何,到目前為止,一切都很好——IE8 實際上很好地呈現了主頁! 我今天真的要在 IE8 上觀看《絕命毒師》嗎?
當我查看登錄頁面時,我已經初步的樂觀情緒立即被擊落:

儘管如此,我還是能夠登錄,並看到一個精簡的儀表板(沒有花哨的自動擴展拖車):

我帶著模糊的期待點擊了一個程序,當然,只看到一個黑屏。
亞馬遜
好的,社交媒體和視頻都出來了。 剩下的就是去購物了。
我查看了亞馬遜,被震撼了——這與你在現代瀏覽器中獲得的體驗幾乎沒有區別:

我以前被一個好的主頁吸引。 所以讓我們點擊一個產品頁面,看看這是否只是僥倖。

不! 產品頁面看起來也不錯!
亞馬遜並不是唯一一個讓我在向後兼容性方面感到驚訝的網站。 維基百科和 Gov.UK 政府網站看起來都很棒。 在 IE8 中擁有一個看起來不像完全車禍的網站並不容易。 我的大部分經歷顯然都沒有那麼完美……!

但是,過時的警告通知或時髦的佈局並不是我今天看到的最糟糕的事情。
完全破碎的網站
有些網站太壞了,我什至無法連接到它們!

我想知道這是否可能是臨時的 VM 網絡問題,但每次我刷新頁面時都會發生這種情況,即使當天晚些時候回到同一個站點也是如此。
這一天發生在幾個不同的站點上,我最終得出結論,這從未影響 HTTP 上的站點——僅在 HTTPS 上(但不是所有HTTPS 站點)。 那麼,問題出在哪裡?
使用 Wireshark 分析網絡流量,我嘗試再次連接到 GitHub。 我們可以看到由於致命錯誤“描述:協議版本”而無法建立連接。

查看 IE8 中的默認設置,僅啟用了 TLS 1.0——但 GitHub 在 2018 年 2 月放棄了對 TLSv1 和 TLSv1.1 的支持。

我檢查了 TLS 1.1 和 TLS 1.2 的複選框,重新加載了頁面,然後——瞧! — 我可以查看 GitHub!

非常感謝我非常有才華的朋友 Aidan Fewster 幫助我調試了這個問題。
我完全支持向後兼容,但這提出了一個有趣的困境。 根據 PCI 安全標準委員會,TLS 1.0 不安全,不應再使用。 但是通過強制使用 TLS 1.1 或更高版本,一些用戶總是會被鎖定(並且並非所有用戶都可能精通技術以在其高級設置中啟用 TLS 1.2)。
通過允許舊的、不安全的標準並讓用戶繼續連接到我們的網站,我們並沒有幫助他們——我們正在傷害他們,因為我們沒有給他們一個轉向更安全技術的理由。 那麼在支持舊版瀏覽器方面應該走多遠呢?
如何開始支持舊版瀏覽器?
當一些人想到“支持舊版瀏覽器”時,他們可能會想到那些針對 IE 的專有舊 hack,就像那個時候 BBC 不得不做一些令人難以置信的粗糙的事情來支持 IE7 中的 iframed 內容。
或者他們可能正在考慮讓事情在 Internet Explorer“怪癖模式”中運行; 一種特定於 IE 的操作模式,它使事物與標準非常不同。
但“支持舊瀏覽器”與“為 IE 破解”有很大不同。 我不提倡後者,但我們應該務實地嘗試做前者。 作為一名 Web 開發人員,我試圖遵循的口頭禪是:
“為大多數人優化,為少數人努力,從不犧牲安全。”
我現在要離開 IE8 的世界,談談對舊版瀏覽器支持的一般、可持續的解決方案。
支持舊版瀏覽器有兩種廣泛的策略,均以 P 開頭:
- 填充
通過填寫缺少的瀏覽器功能,爭取所有人的功能平等。 - 漸進增強
從核心體驗開始,然後使用特徵檢測對功能進行分層。
這些策略並不相互排斥。 它們可以串聯使用。 在這兩種方法中都有許多實現決策,每個決策都有自己的細微差別,我將在下面更詳細地介紹。
填充
對於某些網站或網頁,JavaScript 對功能非常重要,您只想將有效的 JavaScript 提供給盡可能多的瀏覽器。
有很多方法可以做到這一點,但首先是歷史課。
ECMAScript 簡史
ECMAScript 是一個標準,而 JavaScript 是該標準的實現。 這意味著 ES5 是“ECMAScript 版本 5”,而 ES6 是“ECMAScript 版本 6”。 令人困惑的是,ES2015 與 ES6 相同。
ES6 是該版本發布前的通俗名稱,但 ES2015 是官方名稱,後續的 ECMAScript 版本都與發布年份相關聯。
注意: Brandon Morelli 在一篇很棒的博客文章中對這一切進行了有益的解釋,該文章解釋了 JavaScript 版本的完整歷史。
在撰寫本文時,最新標準是 ES2018 (ES9)。 大多數現代瀏覽器至少支持 ES2015。 幾乎所有瀏覽器都支持 ES5。
從技術上講,IE8 不是 ES5。 它甚至不是 ES4(它不存在——項目被放棄了)。 IE8 使用 Microsoft 實現的 ECMAScript 3,稱為 JScript。 IE8 確實有一些 ES5 支持,但在 ES5 標準發布前幾個月發布,因此支持不匹配。
轉譯與 Polyfilling
你可以編寫 ES5 JavaScript,它幾乎可以在所有古老的瀏覽器中運行:
var foo = function () { return 'this is ES5!'; };
你也可以繼續這樣編寫所有的 JavaScript —— 以實現永遠的向後兼容性。 但是你會錯過在不斷發展的 JavaScript 版本中可用的新特性和語法糖,允許你編寫如下內容:
const foo = () => { return 'this is ES6!'; };
嘗試在較舊的瀏覽器中運行該 JavaScript,它會出錯。 我們需要將代碼轉換成瀏覽器能夠理解的早期版本的 JavaScript(即使用自動化工具將我們的ES6代碼轉換成 ES5)。
現在假設我們的代碼使用標準的 ES5 方法,例如Array.indexOf
。 大多數瀏覽器都有本機實現並且可以正常工作,但 IE8 會中斷。 還記得 IE8 是在 ES5 標準發布前幾個月發布的,所以支持不匹配嗎? 一個例子是indexOf
函數,它是為String
實現的,但不是為Array
實現的。
如果我們嘗試在 IE8 中運行Array.indexOf
方法,它將失敗。 但是如果我們已經在用 ES5 編寫代碼,我們還能做什麼呢?
我們可以polyfill缺失方法的行為。 開發人員傳統上通過複製和粘貼代碼或通過引入外部第三方 polyfill 庫來填充他們需要的每個功能。 許多 JavaScript 特性在它們各自的 Mozilla MDN 頁面上都有很好的 polyfill 實現,但值得指出的是,有多種方法可以填充相同的特性。
例如,為了確保您可以在 IE8 中使用Array.indexOf
方法,您可以像這樣複製並粘貼一個 polyfill:
if (!Array.prototype.indexOf) { Array.prototype.indexOf = (function (Object, max, min) { // big chunk of code that replicates the behaviour in JavaScript goes here! // for full implementation, visit: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexof#Polyfill })(Object, Math.max, Math.min); }
只要您在引入任何自己的 JS 之前調用 polyfill,並且不使用除Array.indexOf
之外的任何 ES5 JavaScript 功能,您的頁面就可以在 IE8 中運行。
Polyfills 可用於填補各種缺失的功能。 例如,有用於啟用 CSS3 選擇器的 polyfill,例如:last-child
(IE8 不支持)或placeholder
屬性(IE9 不支持)。
Polyfill 的大小和有效性各不相同,有時還依賴於外部庫,例如 jQuery。
您可能還聽說過“墊片”而不是“polyfills”。 不要太拘泥於命名——人們可以互換使用這兩個術語。 但從技術上講,shim 是攔截 API 調用並提供抽象層的代碼。 polyfill 是瀏覽器中的一種填充程序。 它專門使用 JavaScript 來改進舊瀏覽器中的新 HTML/CSS/JS 功能。
“手動導入 polyfills”策略總結:
- 完全控制 polyfills 的選擇;
- 適用於基礎網站;
- ️ 沒有額外的工具,你不得不用原生 ES5 JavaScript 編寫;
- ️ 難以對所有的 polyfill 進行微觀管理;
- ️ 開箱即用,您的所有用戶都將獲得 polyfill,無論他們是否需要。
Babel Polyfill
我已經討論過將 ES6 代碼轉換為 ES5。 您可以使用轉譯器來執行此操作,其中最流行的是 Babel。
Babel 可以通過項目根目錄中的.babelrc
文件進行配置。 在其中,您指向各種 Babel 插件和預設。 您需要的每個語法轉換和瀏覽器 polyfill 通常都有一個。
對這些進行微觀管理並使其與瀏覽器支持列表保持同步可能會很痛苦,因此現在的標准設置是將微觀管理委託給 @babel/preset-env 模塊。 通過這個設置,你只需給 Babel 一個你想要支持的瀏覽器版本列表,它就會為你完成艱苦的工作:
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "targets": { "chrome": "58", "ie": "11" } } ] ] }
@babel/preset-env
的useBuiltIns
配置選項是魔術發生的地方,結合應用程序入口點中的import "@babel/polyfill"
(另一個模塊)。
- 省略時,
useBuiltIns
什麼也不做。@babel/polyfill
的全部內容都包含在您的應用程序中,這非常重。 - 當設置為
"entry"
時,它將@babel/polyfill
導入轉換為多個更小的導入,導入最小的 polyfill 來填充您在.babelrc
中列出的目標瀏覽器(在本例中,Chrome 58 和 IE 11) . - 設置為
"usage"
通過進行代碼分析並僅導入實際正在使用的功能的 polyfill 來更進一步。 它被歸類為“實驗性”,但在“polyfill 太多”而不是“太少”方面犯了錯誤。 無論如何,我看不出它怎麼可能創建比"entry"
或false
更大的捆綁包,所以這是一個不錯的選擇(也是我們在 BBC 的方式)。
使用 Babel,您可以在部署到生產環境之前編譯和填充您的 JavaScript,並在特定的最低瀏覽器基線中提供支持。 注意,另一個流行的工具是 TypeScript,它有自己的轉譯器,可以轉譯為 ES3,理論上支持 IE8 開箱即用。
使用@babel/preset-env
進行 polyfill 的總結:
- 將 polyfill 的微觀管理委託給工具;
- 自動化工具有助於防止包含您不需要的 polyfill;
- 擴展到更大、更複雜的站點;
- ️ 開箱即用,您的所有用戶都將獲得 polyfill,無論他們是否需要它們;
- ️ 很難準確地看到被拉入應用程序包的內容。
使用 Webpack 和動態導入延遲加載 Polyfill
可以利用新的import()
提議在初始化應用程序之前進行功能檢測和動態下載 polyfill。 在實踐中看起來像這樣:
import app from './app.js'; const polyfills = []; if (!window.fetch) { polyfills.push(import(/* webpackChunkName: "polyfill-fetch" */ 'whatwg-fetch')); } Promise.all(polyfills) .then(app) .catch((error) => { console.error('Failed fetching polyfills', error); });
這個示例代碼無恥地複制自非常好的文章“使用 Webpack 和動態導入延遲加載 Polyfills”,該文章更詳細地研究了該技術。
概括:
- 不會用不必要的 polyfill 使現代瀏覽器膨脹;
- ️ 需要手動管理每個 polyfill。
polyfill.io
polyfill.io 是由金融時報構建的 polyfill 即服務。 它通過您的頁面向 polyfill.io 發出單個腳本請求來工作,可選擇列出您需要 polyfill 的特定功能。 然後他們的服務器分析用戶代理字符串並相應地填充腳本。 這使您不必手動提供自己的 polyfill 解決方案。
這是 polyfill.io 為從 IE8 發出的請求返回的 JavaScript:

這是相同的 polyfill.io 請求,但請求來自現代 Chrome:

您的站點所需要的只是一個腳本調用。
概括:
- 易於包含到您的網絡應用程序中;
- 將 polyfill 知識的責任委託給第三方;
- ️ 另一方面,您現在依賴第三方服務;
- ️ 進行阻塞
<script>
調用,即使對於不需要任何 polyfill 的現代瀏覽器也是如此。
漸進增強
Polyfilling 是一種非常有用的支持舊版瀏覽器的技術,但可能會導致網頁膨脹並且範圍有限。
另一方面,漸進增強技術是保證所有瀏覽器的基本體驗的好方法,同時在現代瀏覽器上為用戶保留全部功能。 它應該在大多數網站上都可以實現。
原則是這樣的:從 HTML 的基線(和样式,可選)開始,並使用 JavaScript 功能“逐步增強”頁面。 這樣做的好處是,如果瀏覽器是舊版瀏覽器,或者 JavaScript 在交付過程中的任何時候出現故障,您的網站應該仍然可以正常運行。
術語“漸進式增強”通常與“不顯眼的 JavaScript”互換使用。 它們的意思本質上是一樣的,但後者更進一步,因為你不應該在你的 HTML 中亂扔很多只被 JavaScript 使用的屬性、ID 和類。
切芥末
BBC 的“切芥末”(CTM) 技術是一種經過驗證的漸進增強實施。 原則是編寫可靠的 HTML 基線體驗,並在下載任何增強的 JavaScript 之前,檢查最低級別的支持。 原始實現檢查是否存在標準 HTML5 功能:
if ('querySelector' in document && 'localStorage' in window && 'addEventListener' in window) { // Enhance for HTML5 browsers }
隨著新功能的出現和舊版瀏覽器變得越來越過時,我們的芥末底線將會改變。 例如,新的 JavaScript 語法(如 ES6 箭頭函數)意味著這種內聯 CTM 檢查甚至無法在舊版瀏覽器中解析——甚至無法安全地執行和 CTM 檢查失敗——因此可能會產生意想不到的副作用,例如破壞其他第三方 JavaScript (例如穀歌分析)。
為了避免嘗試解析未轉譯的現代 JS,我們可以在 CTM 技術上應用這種“現代方式”,取自 @snugug 的博客,其中我們利用舊瀏覽器不理解type="module"
的事實type="module"
聲明並將安全地跳過它。 相反,現代瀏覽器將忽略<script nomodule>
聲明。
<script type="module" src="./mustard.js"></script> <script nomodule src="./no-mustard.js"></script> <!-- Can be done inline too --> <script type="module"> import mustard from './mustard.js'; </script> <script nomodule type="text/javascript"> console.log('No Mustard!'); </script>
如果您樂於將 ES6 瀏覽器作為新的最低功能基線(在撰寫本文時大約 92% 的全球瀏覽器),這種方法是一種很好的方法。
然而,正如 JavaScript 的世界在不斷發展一樣,CSS 的世界也在不斷發展。 現在我們有了 Grid、Flexbox、CSS 變量等(每個都有不同的回退效果),不知道舊瀏覽器可能具有哪些 CSS 支持組合可能導致“現代”和“遺留”的混雜樣式,其結果看起來很糟糕。 因此,越來越多的網站選擇 CTM 他們的樣式,所以現在 HTML 是核心基線,CSS 和 JS 都被視為增強。
如果您使用 JavaScript 的存在以任何方式應用 CSS,我們目前看到的基於 JavaScript 的 CTM 技術有幾個缺點:
- 內聯 JavaScript 被阻塞。 在你獲得任何樣式之前,瀏覽器必須下載、解析和執行你的 JavaScript。 因此,用戶可能會看到一閃而過的無樣式文本。
- 一些用戶可能擁有現代瀏覽器,但選擇禁用 JavaScript。 基於 JavaScript 的 CTM 會阻止他們獲得樣式化的網站,即使他們完全有能力獲得它。
“終極”方法是使用 CSS 媒體查詢作為您的切入點試金石。 這種“CSSCTM”技術在 Springer Nature 等網站上得到了積極使用。
<head> <!-- CSS-based cuts-the-mustard --> <!-- IMPORTANT: the JS depends on having this rule somewhere in the CSS: `body { clear: both }` --> <link rel="stylesheet" href="mq-test.css" media="only screen and (min-resolution: 0.1dpcm), only screen and (-webkit-min-device-pixel-ratio:0) and (min-color-index:0)"> </head> <body> <!-- content here... --> <script> (function () { // wrap in an IIFE to prevent global scope pollution function isSupported () { var val = ''; if (window.getComputedStyle) { val = window.getComputedStyle(document.body, null).getPropertyValue('clear'); } else if (document.body.currentStyle) { val = document.body.currentStyle.clear; } if (val === 'both') { // references the `body { clear: both; }` in the CSS return true; } return false; } if (isSupported()) { // Load or run JavaScript for supported browsers here. } })(); </script> </body>
這種方法很脆弱——不小心覆蓋了你的body
選擇器上的clear
屬性會“破壞”你的網站——但它確實提供了最好的性能。 這個特定的實現使用了至少在 IE 9、iOS 7 和 Android 4.4 中才支持的媒體查詢,這是一個非常明智的現代基線。
“切芥末”,以各種形式,實現了兩個主要原則:
- 廣泛的用戶支持;
- 有效地應用開發工作。
站點根本不可能容納每個瀏覽器/操作系統/網絡連接/用戶配置組合。 根據Yahoo!的分級瀏覽器支持模型,諸如減少芥末醬之類的技術有助於將瀏覽器合理化為 C 級和 A 級瀏覽器! .
Cuts-The-Mustard:一種反模式?
有一種觀點認為,應用“核心”與“高級”的全局二元決策對於我們的用戶來說並不是最好的體驗。 它為原本令人生畏的技術問題提供了理智,但是如果瀏覽器支持全球 CTM 測試中 90% 的功能,而這個特定頁面甚至沒有利用它失敗的 10% 功能怎麼辦? 在這種情況下,用戶將獲得核心體驗,因為 CTM 檢查將失敗。 但我們本可以給他們完整的經驗。
給定頁面確實使用了瀏覽器不支持的功能的情況呢? 好吧,在向組件化邁進的過程中,我們可以有一個特定於功能的回退(或錯誤邊界),而不是頁面級的回退。
我們每天在 Web 開發中都這樣做。 考慮引入網絡字體; 不同的瀏覽器有不同級別的字體支持。 我們做什麼? 我們提供了一些字體文件變體,讓瀏覽器決定下載哪個:
@font-face { font-family: FontName; src: url('path/filename.eot'); src: url('path/filename.eot?#iefix') format('embedded-opentype'), url('path/filename.woff2') format('woff2'), url('path/filename.woff') format('woff'), url('path/filename.ttf') format('truetype'); }
我們對 HTML5 視頻有類似的回退。 現代瀏覽器將選擇他們想要使用的視頻格式,而不了解<video>
元素是什麼的舊版瀏覽器將簡單地呈現後備文本:
<video width="400" controls> <source src="mov_bbb.mp4" type="video/mp4"> <source src="mov_bbb.ogg" type="video/ogg"> Your browser does not support HTML5 video. </video>
我們之前看到的 BBC 用於 SVG 的 PNG 後備的嵌套方法是<picture>
響應式圖像元素的基礎。 現代瀏覽器將根據提供的media
屬性呈現最合適的圖像,而不了解<picture>
元素是什麼的舊版瀏覽器將呈現<img>
後備。
<picture> <source media="(min-width: 650px)"> <source media="(min-width: 465px)"> <img src="img_orange_flowers.jpg" alt="Flowers"> </picture>
HTML 規範多年來經過精心發展,為所有瀏覽器提供基本的回退機制,同時允許理解它們的現代瀏覽器的功能和優化。
我們可以將類似的原則應用於我們的 JavaScript 代碼。 想像一個這樣的 Feature,其中foo
方法包含一些複雜的 JS:
class Feature { browserSupported() { return ('querySelector' in document); // internal cuts-the-mustard goes here } foo() { // etc } } export default new Feature();
在調用foo
之前,我們通過調用它的browserSupported
方法來檢查該瀏覽器是否支持該功能。 如果它不受支持,我們甚至不會嘗試調用否則會導致我們的頁面出錯的代碼。
import Feature from './feature'; if (Feature.browserSupported()) { Feature.foo(); }
這種技術意味著我們可以避免引入 polyfill,只使用每個瀏覽器原生支持的內容,如果不支持,可以優雅地降低單個功能。
請注意,在上面的示例中,我假設代碼被轉換為 ES5,以便所有瀏覽器都能理解語法,但我不假設任何代碼都是polyfill 。 如果我們想避免轉譯代碼,我們可以應用相同的原則,但使用type="module"
採取削減-the-mustard,但需要注意的是它已經具有最低 ES6 瀏覽器要求,因此只有可能會在幾年內開始成為一個很好的解決方案:
<script type="module"> import Feature from './feature.js'; if (Feature.browserSupported()) { Feature.foo(); } </script>
我們已經介紹了 HTML,也介紹了 JavaScript。 我們也可以在 CSS 中應用本地化後備; CSS 中有一個@supports
關鍵字,它允許您根據是否支持 CSS 功能有條件地應用 CSS。 然而,具有諷刺意味的是,它並未得到普遍支持。 它只需要仔細應用; 有一篇很棒的 Mozilla 博客文章介紹瞭如何在 CSS 中使用功能查詢。
在一個理想的世界裡,我們不應該需要一個全球性的簡單檢查。 相反,每個單獨的 HTML、JS 或 CSS 功能都應該是自包含的,並且有自己的錯誤邊界。 在 Web 組件、影子 DOM 和自定義元素的世界中,我希望我們會看到更多地轉向這種方法。 但這確實使預測和測試整個站點變得更加困難,並且如果一個組件的樣式影響另一個組件的佈局,則可能會產生意想不到的副作用。
兩種主要的向後兼容性策略
作為一種策略的 polyfilling總結:
- 可以為大多數用戶提供客戶端 JS 功能。
- 將向後兼容性問題委託給 polyfill 時,可以更容易地編寫代碼。
- ️ 根據實施情況,可能不利於不需要 polyfill 的用戶的性能。
- ️ 根據應用程序的複雜性和瀏覽器的年齡,可能需要大量的 polyfill,因此運行效果很差。 我們冒著向最不准備接受它的瀏覽器發送數兆字節的 polyfill 的風險。
漸進式增強策略總結:
- 傳統的 CTM 使您的代碼分段和手動測試變得容易。
- 保證所有用戶的體驗基線。
- ️ 可能不必要地向可以處理高級體驗的用戶提供核心體驗。
- ️ 不太適合需要客戶端 JS 功能的網站。
- ️ 有時很難在穩健的漸進增強策略和高性能的首次渲染之間取得平衡。 存在過度優先考慮“核心”體驗的風險,這會損害 90% 獲得“完整”體驗的用戶(例如,為 noJS 提供小圖像,然後在延遲加載時用高分辨率圖像替換意味著我們'已經在甚至從未查看過的資產上浪費了很多下載容量)。
結論
IE8 曾經是最前沿的瀏覽器。 (不,說真的。)今天的 Chrome 和 Firefox 也是如此。
如果今天的網站在 IE8 中完全無法使用,那麼十年後的網站可能在今天的現代瀏覽器中也無法使用——儘管它們是基於 HTML、CSS 和 JavaScript 的開放技術構建的。
停下來想一想。 是不是有點嚇人? (也就是說,如果你不能在十年後放棄瀏覽器並且在構建它的公司已經棄用它之後,你什麼時候可以?)
IE8 是今天的替罪羊。 明天是 IE9,明年是 Safari,一年後可能是 Chrome。 您可以將 IE8 換成“首選的舊瀏覽器”。 關鍵是,開發人員構建的瀏覽器與人們使用的瀏覽器之間總會存在一些分歧。 我們應該停止對此嗤之以鼻,並開始投資於強大、包容的工程解決方案。 這些策略的副作用往往會在可訪問性、性能和網絡彈性方面產生紅利,因此這裡有更大的前景。
我們傾向於不考慮屏幕閱讀器的數量。 我們只是理所當然地認為,盡我們最大的努力支持沒有其他方式消費我們內容的用戶在道德上是正確的,這不是我們自己的過錯。 同樣的原則也適用於使用舊版瀏覽器的人。
我們已經介紹了一些構建健壯網站的高級策略,這些網站應該在一定程度上可以在廣泛的傳統和現代瀏覽器中繼續工作。
再次聲明:不要為 IE 破解東西。 那將失去重點。 但是請注意,各種各樣的人出於各種原因使用各種瀏覽器,並且我們可以採取一些可靠的工程方法來使每個人都可以訪問網絡。
為多數人優化,為少數人努力,從不犧牲安全。
關於 SmashingMag 的進一步閱讀:
- 網絡標準:什麼、為什麼和如何
- 智能捆綁:如何僅向舊版瀏覽器提供舊版代碼
- 不要使用佔位符屬性
- 為無瀏覽器 Web 設計