HTML5逸事:一袋“膩子粉”的故事(待續)

李鬆峰發表於2012-12-24

前端就像原始叢林,很多東西等待Web開發人員去探索去開拓。

HTML5的很多功能並不是所有瀏覽器都支援。為了解決跨瀏覽器相容性問題,Introducing HTML5一書的合著者Remy Sharp在該書中首次提到了ployfilling的概念(見圖)。

enter image description here

Remy在自己2010年10月8日的部落格中專文介紹了這個新詞的來源:What is a Polyfill?。這個詞其實源英國的一種牆面填料,品牌為Polyfilla,這種填料在美國叫Spackling Paste(Spackle是美國抹牆粉的一個品牌),當然在我們中國一般叫“膩子”或“填泥”(對應的英文單詞是putty和filler)。

在文中,Remy解釋說With that in mind: think of the browsers as a wall with cracks in it. These polyfillers help smooth out the cracks and give us a nice smooth wall of browsers to work with.(把瀏覽器想象成有裂縫的牆面,而用膩子可以把這些裂縫填平,最後得到的是光滑的瀏覽器“牆面”。)

他給出的定義是:

A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.(一段程式碼或外掛,可以讓開發人員使用應有的技術,就像瀏覽器原生提供該功能一樣。換句話說,它能幫你抹平API之牆。)

Polyfill中的poly,我理解是“多功能”的意思。polyfit-“多項式擬合”。

文中提到Alex Sexton將ployfill歸類為一種“迴歸增強”(Regressive Enhancement)。同時,也提到了Paul的定義:

A shim that mimics a future API providing fallback functionality to older browsers.(一種模仿未來API併為舊瀏覽器提供後備功能的“襯墊”)

enter image description here

文中提到他在2010年6月ThinkVitamin談HTML5 Storage APIs時,實驗性地提到polyfill這個新詞兒(他的其他參會日程)。而最關鍵的是,他已經在Introducing HTML5中“偷偷地”用了這個詞,希望能夠得到讀者和業界的認同。

結果,在2010年JS Conf上,Paul Irish發表了“一組polyfill和shim”。然後,Polyfill這個詞就不脛而走,得到了社群的認同。

Modernizr的文件頁面上,也對polyfill給出了定義和詳細解釋。以下是對Polyfills and Modernizr一節中相關內容的編譯:

Modernizr庫只能幫你在IE中用上HTML5新的區塊元素,但除此之外不會“現代化”(modernize)任何功能(換言之,它只能檢測是否存在原生功能,不能提供該功能的實現)。之所以叫Modernizr,目的就是讓前端開發以及我們自己現代化、跟上時代步伐。儘管Modernizr不能提供現代化的功能,但有很多指令碼可以實現瀏覽器不支援的功能。一般來說,這些指令碼就叫做polyfill。

“polyfill(n):一種JavaScript“襯墊”,用於在舊瀏覽器中提供標準API。”

因此,websocket polyfill會建立一個window.WebSocket物件,提供與原生實現相同的屬性和方法。這意味著你可以使用真正API面向未來開發啦!只要在不支援該API的瀏覽器中載入相容性polyfill即可。

好訊息是,Modernizr檢測的每一個HTML5功能,現在都有了對應的polyfill。沒錯,絕大多數情況下,即使是在不支援相關HTML5和CSS3功能的瀏覽器,都可以再現這些功能。是的,不僅現在可以使用HTML5,過去其實也是可以的!

不過,還是要給大家一個大大的警告:不能因為能用polyfill就亂用。最關鍵的是還是要關注最佳使用者體驗,換句話說就是——快!在IE7裡要載入5個相容性指令碼,然後可以讓它跟Chrome和Opera一樣,並不是一個明智的選擇。沒有一成不變的規則,但也不要忘了頁面載入的指令碼一多,就可能影響到使用者體驗。而且,請你記住:沒有任何人會在兩個瀏覽器中比較你的站點;即使它在不同使用者那裡的外觀和行為不一致,也沒有問題。

至於polyfill這個詞的中文譯法,目前沒有找到公認的譯法,畢竟是一個新詞。在Adobe開發人員社群中,著名圖書作者David Powers於2011年8月發表的一篇文章“使用Modernizr 檢測HTML5和CSS3瀏覽器支援功能”中提到了這個詞。

在Remy的這篇文章下面,一位開發人員alexander farkas提出問題:

希望能進一步分清什麼是polyfill,什麼是shim。因為有很多shim好像是實現標準的API,而有很多shim又好像只是在其他一兩種技術基礎上加了一個抽象層。怎麼區分polyfill與shim?

Remy舉一個例子,並解釋:

如果瀏覽器X支援標準規定的功能,那麼polyfill可以讓瀏覽器Y的行為與瀏覽器X一樣。

比如,jQuery不是polyfill,但下面這段程式碼是:

// 首先包含jQuery
if (!document.querySelectorAll) {
  Element.prototype.querySelectorAll = function (q) {
    return $(this).find(q).get();
  };

  // document物件不是Element物件的後代,
  // 因此手工重寫
  document.querySelectorAll = Element.prototype.querySelectorAll;
}

關於如何開發polyfill,Modernizr給出的polyfill列表中,還推薦了Addy Osmani的一篇文章,2011年8月12日發表:“The Developer's Guide To Writing Cross-Browser JavaScript Polyfills”,值得翻譯。

最後還有一個小插曲。有人給Remy留言說,為什麼不乾脆美國化,把這種指令碼稱為Spackle?Remy答曰:因為我是英國人,哈哈。

相關文章