Javascript 的 async 跟 defer 有什麼不同

紅寶鐵軌客
來關注...
關注/停止關注:紅寶鐵軌客
關注有什麼好處?:當作者有新文章發佈時,「思書」就會自動通知您,讓您更容易與作者互動。
現在就加入《思書》,你就可以關注本作者了!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,讓你寫作不再受限,討論更深入真實,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入
寫程式中、折磨中、享受中 ......
1.12k   0  
·
2019/03/07
·
4分鐘


網站,少不了要用到外部的 Javascript,fontawesome、google analytics、adsense 等等,通常都有一大串,這外部的 Javascript 其實很容易拖累網頁的下載速度,所以,就有了以下三種寫法:

<script src="script.js"></script>
<script async src="script.js"></script>
<script defer src="script.js"></script>

可是,這三種有什麼不同呢?簡單說:就是不同的擋不擋 HTML parsing 與 script 執行的時間點,這關係到您的網頁呈現的速度! 我在 google 的說明中,找到了以下這張圖,我覺得是最簡單易懂的。

A visualization comparing the impact ofusing script vs script async vs script defer. Defer is showing as executingafter script fetch and HTML parsing is done.

Async 或 Defer? 來源:Loading Third-Party JavaScript

用文字簡單的說就是:有 Async 下載時,不會擋 HTML parsing,用 defer 則是都不擋 parsing,但是會在 HTML parsing 完後,才執行 script。

在 Rails 中怎麼寫?很簡單:

<%= javascript_include_tag('javascriptAsync', async: true) %>
<%= javascript_include_tag('javascriptDefer', defer: true) %>

想要知道更深嗎?就請繼續看下去!

1、沒有 Async 也沒有 Defer

我們先來看看都沒加的情況,你可以在 <head> </head> 間加入,或是加在 <body> </body> 間,這兩個有很大的差別:

  • <head> </head> 間:當瀏覽器看到這行 script 時,他就全部暫停執行網頁上的 HTML parsing 動作,等下載跟執行完後,才會再繼續網頁上的 HTML parsing,所以,這時 HTML parsing 還沒完!
  • <body> </body> 間:瀏覽器會做完所有的 HTML parsing 後,才下載跟執行這個 script,這也很慢,但是這時,HTML parsing 完了。
2、Async 同步

這就是下載時,同時 HTML parsing 並沒有停止,只有執行時,會暫停 HTML parsing。Async 很像沒有寫 Async 在 <head> </head> 間的 script,只是快多了,少了等待下載時間! 行為也像,這時 HTML parsing 還沒完 ! 要注意一點,因為是同步下載,所以沒人知道那一個 async 的 script 先執行,你如果有很多 script,執行的先後是不確定的。

3、Defer 延緩

這跟 Async 一樣,下載時 HTML parsing 並沒有停止,但是,它會等到 HTML parsing 完了後,才執行,所以叫做「Defer 延緩」,這跟寫在 <body> </body> 間沒有寫 Async/Defer 時的 script 行為很像,只是少了等待下載時間,快多了,執行時,HTML parsing 已經完了。 更細的說,當瀏覽器 HTML parsing 完後,發出 domInteractive event,Defer 的 script 開始執行,同時,image 跟其他的 CSS Assets 開始 render,都完了後,瀏覽器就會發出 domComplete event,在發出 onLoad。

Async vs Defer

Async 跟 Defer 都只能用在 <head> 間,兩個都放,就會看瀏覽器版本了,很早的版本不認識 Async,它就會用 Defer,不過如上面說的,同時都用很沒有道理。

在 HTML parsing 中,Async 會擋,defer 不會擋,這是很大的不同,

兩個都不能保證 HTML render 完成於否,你還是要自己用 onLoad 還是其他方法來確定, 

誰最好?

我覺得 Async 跟 Defer 都好,要看用的地方,不過看起來,Defer 出問題的機率少一些,畢竟它是在 HTML parsing 完後,但是,都比不加好,快多了!

Turbolinks 5 使用者要注意

你如果用 Turbolinks 5,恭喜,又有一件事要注意了,turbolinks 5 因為會 cache head 間的 assets,所以,當然也會 cache 住 script,當 turbolinks 5 發現之前這個 script 已經存在 cache 裡面時,turbolinks 5 就不執行它了,這很重要,那怎麼辦,沒怎麼辦,就要多記一個例外,討厭的例外,如:

<script async src="script.js" data-turbolinks-eval="false"></script>

加上這 data-turbolinks-eval="false" 後,turbolinks 就不會去驗證 cache 了,我不喜歡這種用法,但是我還是在用 turbolinks,它... 已經挖了夠多的坑給我了。

希望對大家有幫助,講錯了請指正!

附上一些不錯的參考:

Efficiently load JavaScript with defer and async — When loading a script on an HTML page, you need to be careful not to harm the loading performance of the page. Depending on where and how you add your scripts to an HTML page will influence the loading time flaviocopes.com



喜歡作者的文章嗎?馬上按「關注」,當作者發佈新文章時,思書™就會 email 通知您。

思書是公開的寫作平台,創新的多筆名寫作方式,能用不同的筆名探索不同的寫作內容,無限寫作創意,如果您喜歡寫作分享,一定要來試試! 《 加入思書》

思書™是自由寫作平台,本文為作者之個人意見。


文章資訊

分類於:
標籤:
日期:
創作於:2019/03/07,最後更新於:2021/04/16。
合計:960字


分享這篇文章:
關於作者

很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯




參與討論!
現在就加入《思書》,馬上參與討論!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,用筆名來區隔你討論內容,讓你的討論更深入,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入


×
登入
申請帳號

需要幫助
關於思書

暗黑模式?
字體大小
成人內容未過濾
更改語言版本?