前端小誌(轉型中)

一個用來記錄人老會忘記的地方

JS CSS in body( position)

2018年09月02日
天啊,原本預計一個月一篇文章,由於本人跑去當了full stack,變得太忙了,周末只想好好休息耍廢。最近新專案終於要上了,處理的也差不多了。只剩一些小bug與performance需要調整我會想辨法,我會努力把文章補回。未來再來看看要不要加一些後端文章(那就不是前端小誌了XD)

這篇先來個簡單的東西吧,就是script tag, link到底要放在html的哪裡呢

直接先講結論

放在body之後絕對沒毛病

從最簡單講起,大多數人一定知道loading js會block browser的render機制

很多之前的概念要知道

GUI與JS thread是戶斥的,因為當repaint的時候會觸發GUI thread,但JS執行後很有可能會造成多次repaint,於是乎JS在執行的時候會先block GUI thread,待JS結束後才換GUI thread。

於似乎我們可以用async defer這兩個關鍵字去處理,這蠻簡單的,直接看圖吧

js_async_n_defer

如果使用了defer,放在header跟body後就根本沒差別了,其他的case放在body後是個保險的寫法

但有一個很重要的點

defer不保証執行順序 defer不保証執行順序 defer不保証執行順序(由上到下)

實際上碰到的,專案裡有一個external file是公司寫好的logger module(es5 CMD),並不是build在webpack的entry裡。

原本是兩個檔案 A & B

因為defer不保証順序,所以我這樣寫

<header>
  <script async src='a.js'></script>
</header>
<body>
</body>
  <script defer src='b.js'></script>

async load完就執行,defer要等到DOMContentLoaded之前執行

覺得OK(X) 好像失敗了(O)

在正常開發人員always clean cache every refresh下完全ok

但是在browser有cache的情況下,不保証執行順序就炸了(都是0秒 loading time)

最後的解法是將兩個檔案放在一起(在最後的版本我開了一個webpack entry還是bundle了)



寫到這裡,先轉個話題談談css

為什麼css必須放在header呢

原因是css屬於關鍵渲染路徑(critical render path)中的一環

過慢的loading會delay domContentLoaded的時間,而因為網頁的評分中將未加載css的網頁視為沒載完(因為很醜無法閱讀),沒辨法跟js一樣async loading

這篇文章說的很好,配上上面的之前文章,直接拿結論

  1. css 不會影響dom tree parsing
  2. css 會影響 dom tree rendering(因為css dom tree還沒建好)
  3. css 與js互斥,原因上面講了

隨便提一個 do not use @import(我用google font的時候被偵測到),原因是又delay loading

(之後開個文章把所有有用的tunning都寫進去)

又回到js部份,這也是真的該理解的部份

既然js會block render,那反正js放header跟放body後不都一樣

這說法是對的也是錯的。

如果所謂的block render指的是complete anything and can intereact with users 那答案是yes,根本就沒差

tricky的地方其實是我們關心的是first time render view,而dom tree會在一個網頁被開啟時被重覆更新好幾次(only by js, css必定先讀完)

我在網頁文章中的理解是css dom tree的parse決定第一次paint的時間(css 不會影響dom tree parsing,會影響 dom tree rendering)結束parse才觸發js執行,而parse js的行為是會先將js前面的已經ok的dom先paint過一次

  1. css loading time > js loading time 畫面白掉無法paint
  2. css loading time < js loading time paint到js的那行之前

所以假設

<html>
  <nav></nav>
  <script > heavy js</script>


  <body>
    <h1></h1>
    ...
    <p></p>
  </body>
</html>

js執行會阻止下方dom render

使用者會在first time render view只看到nav,經過了heavy js execute之後才會繼續向下。

那才是為什麼script要放body之後

這些東西我以前知道script放body之後,近期才真正弄懂它


不過最後思考一個問題,在spa的頁面中,請問script放在body之後有好處嗎

我的理解(請反白)

沒啥鳥用,因為你的頁面是heavy js,first time render view = 空白 root element,除非有做ssr那就另當別論

這算是老觀念了,我覺得有一些outdated的部份,所以才特別重新review與思考,充份了解還是聊勝於無啊。

參考1

參考2


展開Disqus
分類
最近文章
友站連結
© 2019 Ernie Yang