最新赞助活动温馨提示:自愿赞助服务器费用,学生和没有工作的整站资源免费下载!
头像

为什么把 Script 标签放在 body 结束标签之后 html 结束标签之前?-H5教程

来源:http://erdangjiade.com/topic/133596.html H5程序员 2017-10-27 12:55浏览(454)

新浪微博、谷歌等,为什么把Script标签放在body结束标签之后html结束标签之前?
而不是之前推荐的body结束标签之前?
问题关键:放在body结束标签之前与之后有什么差别?

回复内容:

Google并没有把<script>插入在</body>之后,而只是没有写</body>和</html>闭合标签。 【这样做是符合标准的。不仅是html5标准,从第一个HTML正式标准HTML 2.0开始,这样做都是允许的。相反,在</body>之后插入其他元素,从HTML 2.0起就是不合标准的。】

新浪微博确实有在</body>之后输出<script>。

新浪微博所用的doctype是XHTML 1.0,但是其response的content type头并没有用XHTML mimetype,所以浏览器仍然会按HTML语法进行parsing。【顺便说一句,虽然新浪微博用了XHTML 1.0 DTD,但是其实际内容连well-formed也没有做到,是典型的挂羊头卖狗肉的XHTML。新浪的前端同学们应该检讨一下啊!当然了,腾讯微博也是用XHTML 1.0的DTD,并且也不是well-formed的,跟新浪微博是难兄难弟啊!如果说一定要较个高下,那企鹅还是略胜一筹——其网页出现第一个解析错误的行数更靠后一点。】

按照HTML5标准中的HTML语法规则,如果在</body>后再出现<script>或任何元素的开始标签,都是parse error,浏览器会忽略之前的</body>,即视作仍旧在body内。所以实际效果和写在</body>之前是没有区别的。

总之,这种写法虽然也能work,但是并没有带来任何额外好处,实际上出现这样的写法很可能是误解了“将script放在页面最末端”的教条。所以还是不要这样写为好。

【补充】
有同志说因为新浪微博使用bigpipe,所以“从直觉触发,为了避免浏览器出现未知异常,应该在首次吐出的页面框架中闭合body”。但是这个逻辑上说不通。因为在body以外写script也可能存在其他异常嘛。有什么理由能让开发者推断出后者会更安全呢?实际上在没有充分测试的前提下,如果要进行推断,那么可以推断出后者的风险更大。

第一,这是不合标准的行为,而且从有HTML标准以来都是不合标准的,因此浏览器实现不一致或者在这种情况下有bug的风险显然更大。

第二,虽然将<script>写在</body>之后,但最终的DOM树里,<script>元素还是会成为body的子节点,这一点很容易在firebug等调试器里验证。既然如此,如果将<script>写在</body>之前会有问题,你又如何保证写在之后(并在DOM里又变成了和写在之前一样的结构)就没有问题? 基于规则 %html.content "HEAD|BODY" HTML 标签的子元素只能是 HEAD BODY。
但是浏览器对HTML(XHTML)均有容错机制。 错误嵌套的标签、以及位置放置错误的标签都会在paser HTML 过程中尝试修复。修复后得到合法的HTML后在由布局引擎建立相应的DOM对象。

在<script>标签放置于</body>标签之后时,源码被所有浏览器【泛指PC上常见的】修复为正常形式,即<script></script></body>。

由此,Google 这种利用基于浏览器修复【或规范中可以不闭合标签条款的】机制,处理是可以的。它的意图是尽可能少输出内容,由客户端浏览器来辅助它处理HTML,最终目的是为了提速与尽可能加大服务端吞吐量。

至于新浪微博的问题,比较复杂,只能推测下。
新浪微博默认采用【非IE6下】bigpipe机制分块输出页面内容。这需要在首块时候就吐出页面框架结构给浏览器。那么这个先吐出的页面结构是否需要闭合</body>标签呢?
从直觉触发,为了避免浏览器出现未知异常,应该在首次吐出的页面框架中闭合body。那么,之后分块输出的 script 标签必然会被打印在 </body>之后,然后依赖浏览器修复机制执行代码。
新浪微博当时的工程师们可能并不知道修复机制,仅仅是为了避免项目风险,经过测试后发现这么做可行,就这么做了。
不管怎样,基于bigpipe机制分块吐出机制,在body没有闭合,页面数据继续到达的情况下,之后被吐出的script代码很可能存在操作document.body对象,这样可能会导致异常,你我做如此实现时候都必须掂量下是否要冒风险不闭合body标签。

此外,对于贺老祖的一些解释,偶表示部分不认同。
content type 的问题。
rfc3236 规定了 application/xhtml+xml 这样的 XHTML mimetype 来表示一个XHTML文件。但是浏览器并不一定按照这个 mimetype 来解析,偶从开源浏览器代码中【Gecko/Webkit】只看到 parser HTML 部分的实现,这部分内容对于 XHTML 是无特殊处理的,就是说即使是 XHTML 也会被当做 HTML parser。唯一有一点不同的是,页面的 DTD 如何写会被浏览器嗅探,用来触发三种不同的文档模式【怪异、近乎标准、标准】。至于当前文档的 mimetype 是什么,对解析 HTML 或者渲染的影响,没有得到很明显的源码证据。
【当然,基于network层是会区分mimetype 的,它会筛选出它认为是HTML的类型交付HTML parse 处理。事实上IE会比其他浏览器做的要更多,对于非二进制类型,会启用“HTML嗅探机制”,如果首200字符内有特定HTML标记,则会将文档交由HTML parse 处理】。

贺老祖【】内表述的挂羊头卖狗肉行为偶就不细说了,仅当做 贺老祖 个人情绪发泄。个人感觉没必要太学院了,实际适用就好。



恩恩,惯例,最后来个总结。
说了这么多,两种方式实际使用上没有什么区别,唯一差异在于你是否要利用浏览器的自动修复机制。
当然,理论上讲,利用了自动修复机制必然会导致性能有损失。
至于性能损失多大,是否要如此用,偶说不好,由看官自行判断。 从实际效果来看,应该是没有区别的。但是放在 html 结束标签之前应该是不规范的(通不过 HTML 验证),放在 body 结束之前才对。当然你完全可以选择无视验证。具体选择这么做的原因,还真不清楚。 IE 8-(8 不确定)有一个 bug,如果 <script> 在 <body> 内并且执行了一些 DOM 增减/修改操作(似乎限定于和 <script> 有父子关系或结构影响的元素),有可能会引起 IE core error(不是 JS error),某些情况会引起 crash。

这个问题我是在用 yepnope.js 1.0 版本还有一些早期 JS loader 时发现的,它的工作方式是往 <body> 插入 <script>。

不确定这是不是真实理由。 请问提问者在哪个地方看到的是“放在body结束标签之后html结束标签之前”?麻烦提供下具体页面……
script确实是放在页面底部是最好(主要是为了放防止页面阻塞),但是这个页面底部应该也是body结束标签之前。放在body标签之后,恕个人能力有限,在我看来这应该是不符合相关标准的页面。 感觉于前端性能而言应该没差别.
查了一下, 有个差别, 说是放在</body>之前可以通过验证, 放在</body>之后就不行了.
stackoverflow.com/quest
quora.com/Why-put-scrip 或许是为了规避body内的js错误。在某些浏览器中,当body内js错误,则后续js脚本不再执行,但是body之外的script还是可以继续执行的。有道云笔记 目前来说没有太大差异,对于<script>标签的再认识学习,应该对脚本采用“分而治之”的办法:那些负责让页面更好看,更好用的脚本应该先加载,也就是放在<head></head>里面,而那写可以呆一会再加载的功能脚本(比如验证的 ,弹出的等)可以放在下面,也就是</body>之前,至于放在</body></html>之前这样写是否正确,目前来说功能上是基本无碍的,以前我也这样写过,目前H5来了,稍微规范一下,养成习惯就好了,还是看页面的速度和功能优先从而合理安排脚本的位置。
评论0
头像

友情提示:垃圾评论一律封号 加我微信:826096331拉你进VIP群学习群

1 2