為什么把 Script 標簽放在 body 結束標簽之后 html 結束標簽之前?(轉)


 
作者:賀師俊
鏈接:https://www.zhihu.com/question/20027966/answer/13727164
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

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里又變成了和寫在之前一樣的結構)就沒有問題?
 
 
 
 
 
作者:貘吃饃香
鏈接:https://www.zhihu.com/question/20027966/answer/13727477
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

基於規則 %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 處理】。

賀老祖【】內表述的掛羊頭賣狗肉行為偶就不細說了,僅當做 賀老祖 個人情緒發泄。個人感覺沒必要太學院了,實際適用就好。



恩恩,慣例,最后來個總結。
說了這么多,兩種方式實際使用上沒有什么區別,唯一差異在於你是否要利用瀏覽器的自動修復機制。
當然,理論上講,利用了自動修復機制必然會導致性能有損失。
至於性能損失多大,是否要如此用,偶說不好,由看官自行判斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



猜您在找