在这篇文章中,我将讨论名为 Webshims Lib 的 HTML5 和 CSS3 功能 polyfill 库,以及如何正确使用它。
Polyfill?
在 Web 开发中,我们将模拟 HTML5 或 CSS3 规范部分的脚本称为“polyfill”。 Polyfill 可以是任何东西——一个 JavaScript 库,它为旧版本的 Internet Explorer 添加了对 CSS3 选择器的支持(例如 Selectivizr)或一个高端基于 Flash 的解决方案,它可以启用 <audio>
和 <video>
标签,一直回溯到 IE 6(例如 html5media)。
介绍 Webshims
Webshims Lib 是最完整的 polyfill 之一。 它基于 jQuery 和 Modernizr。 包含这 一个 脚本将启用各种台式机浏览器中的许多功能。
Webshims 使得 HTML5 和 CSS3 功能成为可能,例如语义标记、画布、Web 存储、地理定位、表单和多媒体。 仔细阅读这个大列表后,您首先想到的可能是这个库有多大。 这意味着巨大的下载大小和漫长的脚本执行时间。 但是,这里有一个关键点,Webshims 将自动检测用户浏览器支持哪些功能,并且它只加载模拟所有其他功能所需的功能。 这样,它不会减慢那些已经运行现代浏览器的用户的速度,比如 Firefox 或 Chrome。 即使您不需要所有功能,您也可以减少要加载的功能数量。
如何使用 Webshims
要使用 Webshims 库,您需要将依赖项 jQuery 和 Modernizr 与 Webshims Lib 一起包含。
<script src="scripts/jquery-1.8.2.min.js"></script>
<script src="scripts/modernizr-custom.js"></script>
<script src="scripts/webshim/polyfiller.js"></script>
现在您需要初始化 Webshims,并且如果需要,告诉它要使用哪些功能。
<script>
// Polyfill all unsupported features
$.webshims.polyfill();
</script>
<script>
// Polyfill only form and canvas features
$.webshims.polyfill('forms canvas');
</script>
就是这样! Webshims 将根据用户的浏览器自动检测和 polyfill 缺少的功能。 如果您好奇,完整的功能列表是
- json-storage
- es5
- geolocation
- canvas
- forms
- forms-ext
- mediaelement
- track
- details
例子
让我们使用 <video>
标签来举例。 首先,让我们在没有 Webshims 或任何其他 polyfill 的情况下创建基本页面。
<!DOCTYPE html>
<html>
<head>
<title>Video native</title>
</head>
<body>
<video width="480" height="360" controls="controls">
<source src="Video.mp4" type="video/mp4">
<source src="Video.webm" type="video/webm">
</video>
</body>
</html>
现代浏览器将正确显示此视频,但 Internet Explorer 6、7 或 8 不会。
现在,我们将示例更改为嵌入 Webshims Lib。 您会发现无需编辑任何其他内容。
<!DOCTYPE html>
<html>
<head>
<title>Video including polyfill</title>
<script src="scripts/jquery-1.8.2.min.js"></script>
<script src="scripts/modernizr-custom.js"></script>
<script src="scripts/webshim/polyfiller.js"></script>
<script>
$.webshims.polyfill('mediaelement');
</script>
</head>
<body>
<video width="480" height="360" controls="controls">
<source src="Video.mp4" type="video/mp4">
<source src="Video.webm" type="video/webm">
</video>
</body>
</html>
现代浏览器将显示其本机 <video>
标签播放器,但现在此功能在 Internet Explorer 6+ 中也可用。 您可以在 此处尝试演示。
结论
如示例所示,使用 Webshims Lib 非常简单。 无需修改代码,也不会降低使用现代浏览器的用户的速度。 它使每个人都能享用您页面提供的全部功能。 请访问 Webshims 主页 以获取下载、文档和更多演示。
这是一个非常酷且有用的库。 感谢分享!
所有代码都显示非换行空格 HTML 实体。 这使得阅读有点困难!
有趣! 一方面,Christian Heilmann 正在谈论香草网络饮食以简化网络,另一方面,我们有 polyfill 来支持地球上所有可能的浏览器上的每个其他功能……
终于有一个“一站式”的 polyfill/脚本可以用来让 IE 正常工作。 谢天谢地我订阅了 css-stricks.com :)
不过,关于您的帖子我有两个问题
1- 您的代码示例为什么显示
和&
? 如果您能修复它,那将很棒,这样我们就不必“排除扫描”不必要的标记。2- 在您的 HTML 结构中,您现在建议在
<head>
部分中添加脚本。 我们都知道这不是推荐的做法/最佳实践。但是,我看到 Webshims Lib 依赖于 jQuery 和 Modernizr 的加载,但通常 Modernizr 会放在
<head>
中,而 jQuery 则尽可能靠近</body>
标记。jQuery 和 Modernizr 的加载顺序对于 Webshims Lib 的正常工作是强制性的吗?
我认为在创建像这样的“如何正确使用”帖子时,您需要考虑这些问题。
该脚本的 Github 上的 readme.md 部分也不太有用。
谢谢。
好吧,关于问题#1,似乎您现在已经修复了它。 谢谢:)
加载顺序显然很重要(因为 Webshims 是建立在 jQuery 之上的),但我没有看到任何暗示它必须在
<head>
中完成。Github README 指出您需要等待文档完成加载才能使用任何 polyfilled 功能(这无论如何都是好建议),但也暗示您不需要等待调用
$.webshims.polyfill()
。鉴于此,我怀疑将所有内容放在页面底部(或在
<head>
中的onload
事件中,它实现了相同的基本目标)是完全安全的。感谢您对 polyfill 的精彩解释。
但是,我在 IE7 或 IE8 中的视频演示无法正常工作。 其他人能正常使用吗?
ps. 我使用 Virtualbox 在 Mac 上运行 Microsoft 提供的用于 IE 测试的 VM。 也许我的设置毕竟不是一个好的测试环境?
哎呀。 我的意思是,“但是,该 视频演示……”。
真正的 IE7——不行
真正的 IE8——可以
IE7 = 不行
Win 7 使用 Virtualbox(vista)
周四一定是新的周一
根据 Alexander Farkas 的建议在虚拟机上加载了 Flash,视频可以播放。
我的错
哎呦!这就是我的问题。只需要在我的虚拟机上安装 Flash。这就是我爱这个网站的原因:步骤 1:炫耀我的无知。步骤 2:学习东西。谢谢。
可能是个愚蠢的问题,但它是否替代了 Modernizr 或者与它一起使用? 也就是说,我需要包含两个脚本吗?
@D
不,它是 Modernizr 的补充。Modernizr 是地球上最好的功能检测脚本。Webshims 基于它进行填充。
@traq
演示在我的真实 IE6/7/8 中有效(显然您需要安装 Flash)。
@Ricardo
加载顺序至关重要,但您当然可以将 jQuery 和 webshims 添加到页面的底部。但简而言之,我认为这并不总是最好的做法。关于这条规则有很多话要说,它只是一个变通方法。实际上,我认为将 JS 放置在底部通常是一种不好的做法。如果您的 JS 对页面的 UI 和功能至关重要,您应该从头部加载它(阻塞),如果它不那么重要,您应该从头部异步加载它(使用 async 属性或脚本加载器),如果它只是添加一些小额外内容(灯箱),您可以从头部异步 + 延迟(onload/domready)加载它。您还应该考虑到,这条规则是在 IE6/IE7 时代制定的。在这个时代,在顶部添加脚本不仅会阻塞 UI 渲染,还会强制顺序下载。从那时起,这种情况发生了变化,webshims 始终异步加载填充。(将异步加载与延迟加载相结合,会在不提供很大速度提升的情况下增加 FOUC。)
@Daniel
非常感谢这篇文章!
嗯.. 需要什么版本的 Flash?
好吧,我必须说我强烈不同意您提到的几条评论。但由于您提到了几个有趣的事情,我也有几个问题
1.- “[…] 将 jquery 和 webshims 添加到页面的底部。但简而言之,我认为这并不总是最好的做法。 ” – 不确定为什么不认为在底部加载脚本是一种好习惯,许多人这样做:HTML5boilerplate、320 And Up 等,仅举几例。如果雅虎的开发人员推荐这样做,并且有充分的理由,我不确定为什么您反对这种做法。
我个人是这样做的,并将继续这样做,因为它从技术、性能和 SEO 的角度来看都是有意义的。
2.- “[…] 它只是一个变通方法 ” – 变通什么?我可能错过了什么,但我没有看到任何需要通过将脚本放置在底部来变通解决的事情。
3.- “如果您的 JS 对页面的 UI 和功能至关重要,您应该从头部加载它(阻塞)” – 凭借我们触手可及的现代 JavaScript 功能以及 jQuery 降低的学习曲线,我认为大多数人的 JavaScript 对页面的 UI 和功能至关重要。Webshims 就是一个明显的例子。
然而,我不认为回到在
<head>
部分加载所有脚本比我们已经知道的最佳实践,即在标记底部加载它们更好。4.-“[…] 从头部异步加载它(使用 async 属性或脚本加载器) […] 异步 + 延迟加载它(onload/domready) ”– 问题:没听说过“异步”加载脚本或使用脚本加载器或“延迟”加载脚本,我不是 JavaScript 开发人员/大师。你能提供一些这方面的见解吗?提前感谢。
5.- “您还应该考虑到,这条规则是在 IE6/IE7 时代制定的。” – 我们仍然处于那个时代,亚历山大,唯一的区别是我们在混合中有了更多先进的浏览器,但 IE6 和 IE7 仍然与我们同在。
除此之外,雅虎的开发人员关于在标记底部放置脚本的建议与 IE 无关。所以,我不确定你的说法是如何得到证实的。
6.- “在这个时代,在顶部添加脚本不仅会阻塞 UI 渲染,还会强制顺序下载。” – 您在添加脚本到顶部(
<head>
)会阻塞 UI 渲染方面是正确的,因此,您现在开始自相矛盾,因为您刚刚说过:“如果您的 JS 对页面的 UI 和功能至关重要,您应该从头部加载它(阻塞)”。另一方面,无论您将 JavaScripts 放置在
<head>
中还是在标记底部,都会发生顺序下载。除非我对加载 JavaScripts 有所不知。不过,我不确定 “这次” 意味着什么。顺序下载从这台“机器”创建以来就一直存在。
7.- “从那时起,这种情况发生了变化,webshims 始终异步加载填充。” – 如果您刚刚说 “在这个时代...”,那么“从那时起”发生了什么变化。另一个矛盾。很难理解你的想法…
8.- 最后一个矛盾:在您最后的陈述中,您说 “(将异步加载与延迟加载相结合,会在不提供很大速度提升的情况下增加 FOUC)”,但您之前实际上只是推荐这样做:“[…] 您应该从头部异步加载它(使用 async 属性... […] 您也可以异步 + 延迟加载它 ”。
至于 FOUC,我个人认为这不是什么大问题。是的,它很烦人,但这正是野兽的本质,只是时间问题,我们就不必再考虑它了,就像我们不再考虑
-moz-border-radius
一样(除非您使用自动包含它的混合编译 CSS)。我从这一切中学到的东西很简单
A. 没有理由不将 JavaScripts 放置在标记的底部。当然,正确的加载/堆叠顺序是强制性的,但仍然,将它们放在底部绝对没问题,并且仍然是一种最佳实践。
B. 我们仍然处于 IE6/IE7 时代。我(我们)迫不及待地希望不再考虑这些字符的那一天到来 :)
C. 我不知道 异步加载 以及 延迟加载 或 脚本加载器 是什么,也不知道它们是如何工作的。如果您或任何人有任何可以分享的信息,那就太好了。
D. 我希望我能当面进行这场对话,因为我从来没有机会与任何人进行这种水平的对话,甚至在我的工作场所都没有,我相信我需要从您和您的工作中学习很多东西。
我现在将 Webshims 添加到我的 Web 设计工具箱中 :)
谢谢。
A. 没有理由不将 JavaScripts 放置在标记的底部。当然,正确的加载/堆叠顺序是强制性的,但仍然,将它们放在底部绝对没问题,并且仍然是一种最佳实践。
肯定有。我不知道您支持哪些平台和用户类型,但我工作中 90% 的代码(不是我写的)在头部加载了 95% 的 Javascript。所以,作为一名开发人员,如果我需要关注加载顺序,我必须在头部加载,否则我会破坏东西。
B. 我们仍然处于 IE6/IE7 时代。我(我们)迫不及待地希望不再考虑这些字符的那一天到来 :)
我为你感到难过。真的。我已经两年没担心过 IE7 支持了。IE8 问题只会出现在客户特别要求 IE8 兼容性的时候。你不能再等支持中世纪浏览器的那一天了吗?那就停止支持它们! 通过继续支持它们,您就是在支持这个问题。我们很多人都已经和老板、客户等谈过这个话题。我建议你也这样做,并开始给他们提供有说服力的理由,说明旧浏览器是极大的浪费时间、资源,最终是浪费金钱。如果他们不听你的,你就没有说服力。如果你打算等着企业用户切换到现代浏览器,你将继续等待多年。
C. 我不知道异步加载以及延迟加载或脚本加载器是什么,也不知道它们是如何工作的。如果您或任何人有任何可以分享的信息,那就太好了。
关于异步加载的信息很多。我觉得你开始告诉作者他的观点是错误的,而你自己却承认“我不是 JavaScript 大师”,这有点自鸣得意。
D. 我希望我能当面进行这场对话,因为我从来没有机会与任何人进行这种水平的对话,甚至在我的工作场所都没有,我相信我需要从您和您的工作中学习很多东西。
这并不令人惊讶。
但是如果我理解正确,那么填充也会在那些具有对您填充的 HTML5 或 CSS3 功能的原生支持的浏览器中加载?
或者,我们甚至应该使用 Modernizr.load yep/nope 加载它?
“Webshims 会根据用户的浏览器自动检测和填充缺失的功能。”
抱歉… 我应该在问问题之前多读一些内容。
这个视频在我的 IE 6 – 8 中播放。令人印象深刻!
@Ricardo
如果其他人从悬崖上跳下去,你也会跟着跳吗?“但其他人也这样做”几乎从来不是一个有效的论据。
雅虎的开发人员在异步脚本加载器不存在、资源仍然是异步请求、平均 Web 服务器和 Web 代理没有设置适当的未来过期缓存头等时代提出了这个特定的建议。
我们有一个名称来称呼盲目遵循这些建议而没有定期重新评估其有效性的行为;这被称为 货物崇拜编程。
RequireJS 是值得阅读和学习的东西。它是一个使用 CommonJS 中新兴的异步模块定义 (AMD) 规范的脚本加载器。
无意冒犯,但对于我通常看到的不到 2% 的浏览器份额,我不会为了那些可能运行在过时硬件上的残疾、性能不足的浏览器而费心遵守旧的货物崇拜实践,这些浏览器正在迅速走向最终的死亡。
您不知道 IE8+ 和任何其他主要浏览器的现代版本都是并行下载脚本的。只有执行仍然是顺序进行的(您甚至可以关闭它……)。
无关紧要–
“悬崖”类比,哈哈。我确定我对这个类比已经太老了 :p
我“不会”仅仅因为 FFOI 就跳下去,事实上我根本不会跳,如果我要跳,我会和很多“大人物”一起跳。
货物崇拜编程,明白了,很有道理:我不是程序员。尽管如此,这很有趣。
是的,Require.js,我读了很多关于它的内容,但并没有真正理解它的一些概念,现在我对它有了更好的了解。
不要介意,Ron,你和我在同一条船上,有着相同的看法。但是,我通常看到的份额远远高于你的份额。我不得不说,我再也不为 IE6 做任何事情了,而且我尽我所能努力减少 IE7 的额外工作。
我不认为 IE6/IE7 正在迅速走向死亡,相反,我的朋友,我们都经历了它们无比缓慢的死亡过程。
是的,我不知道现代浏览器是并行下载脚本的。我最近了解到关于使用 `@import` 与 `link` 时 CSS 的并行顺序下载的很多信息,但没有讨论过脚本的并行顺序下载。
现在我知道了。
感谢您的信息,非常有帮助。
Derp;这应该写成:“仍然是 **同步** 请求的。”
我只安装了 IE9(不是我的常用浏览器),在浏览器模式下运行:IE7/8/9 兼容模式,它没有工作……
但后来我检查了一下,发现 IE 没有安装 Flash…… :-)
安装后,它像魅力一样工作,真是个好发现!
Atg
@Ricardo Zea /无关紧要
关于 JS 的异步和普通加载行为。通常浏览器可以同时加载每个域的 2-8 个文件(旧浏览器,如 IE6/7 或 FF3.0 加载 2 个,其他加载 4-8 个)。很明显,并行加载文件比顺序加载快得多。
将 JS 放在底部规则背后的原因如下
通常,当您将 script[src] 添加到 HTML 中时,它会阻止浏览器执行以下任务
a) 下载其他资源(仅适用于 IE6/IE7,IE8 开始改变这种情况,IE9 和其他浏览器在这方面做得非常好)
b) 将 HTML 解析成 DOM(仅适用于 IE6/IE7)
c) 渲染 UI(所有浏览器)
因此,将 JS 放在底部最小化了这个问题,因为没有其他下载资源会被阻止,并且 DOM + UI 被解析/渲染到 99%。
这条规则是在所有浏览器都阻止所有内容的时候制定的。如您所见,a) 和 b) 仅适用于 IE6/IE7,只有点 c) 在所有浏览器中都存在(并且不会改变,因为这是浏览器的工作方式)。实际上,不阻止 UI 渲染总是意味着,请创建一个 FOUC。这非常重要,需要理解。FOUC 不是“将 JS 放在底部”规则的副作用,而是预期的。因为您作为开发者这样说:我的 JS 对 UI 不重要,请最后执行 JS 操作。
脚本的异步加载 是一种非常好的技术,可以避免在所有浏览器中出现 a、b 和 c 的问题(即使在 IE6/7 中),同时您可以更好地控制 FOUC 问题。这里要点:只要您使用异步加载,就不会有任何阻塞,但由于您可以在 head 元素中开始脚本下载,因此脚本可以更早地下载、解析和执行,如果它在客户端缓存中,您就不会产生 FOUC/FOUBC。
通过延迟加载,我的意思是指,您可以延迟脚本的异步加载(在超时后、在 domready 后或在 onload 后),如果此脚本对您的 UI 不重要(例如 lightbox),这种技术可能会有所帮助,因为尽管您使用的是非阻塞脚本加载技术,但加载脚本会消耗 1 个 HTTP 请求,该请求可以用于内容图像等。
异步加载的唯一问题是,脚本的执行不再按顺序进行,这会造成竞争条件。Webshims 以异步方式加载所有内容(没有任何阻塞),并非常有效地处理竞争条件问题(类似于 requirejs)。
Alexander,您解释得很好,非常感谢。
不知道我怎么会错过 Chris 的《思考异步》一文,我会在发布此回复后立即阅读。
现在,有了您和 Ron 以上的解释,我相信我不是唯一一个重新评估在标记中放置脚本的位置和方式的人,因为现在我有了新的信息和理由来重新考虑。嗯……听起来我可能要和你们俩一起跳下悬崖了,哈哈。
我确定我工作的地方没有程序员知道我们在这里讨论的关于浏览器、异步和延迟加载脚本的任何内容,因此我一定会让他们了解一些新事物。
再次感谢您提供的信息,非常有帮助。
@traq
Flash 需要 9.0.115 版本才能播放 h.264 视频。
Webshims 可以与 HeadJS 而不是 Modernizr 一起使用吗?
目前还不行。它依赖于 Modernizr 和 jQuery 库。
这可以用于启用 SVG 吗?
热门话题!我希望 @ChrisCoyier 尽快发布一个 SceenCast,介绍在哪里以及何时加载它们。
这将与 jQuery 2.0+ 一起使用吗?因为 jQuery 2.0+ 不支持旧版 IE。
说真的,Chris,你让我在这方面彻底迷茫了,不止一件事我搞不明白。
有用的代码,非常有趣,我想我需要编码技巧才能理解它。
嗯……它解决了 Safari 不支持 HTML5 验证(Twitter Bootstrap)的问题。
我想 IE8 永远都是 IE8。反正我对微软的东西都不喜欢。
感谢您的教程。
感谢您的精彩解释。
只是好奇,我们是否可以使用 yesNope.js 来嵌入我们自己的 polyfill,用于 webshim 库中不存在的功能。否则,还有其他方法可以通过 webshim 本身来嵌入。或者,如果我使用 yesNope.js,性能如何?
提前感谢。