Javascript 的 async 跟 defer 有什麼不同

紅寶鐵軌客
Join to follow...
Follow/Unfollow Writer: 紅寶鐵軌客
By following, you’ll receive notifications when this author publishes new articles.
Don't wait! Sign up to follow this writer.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.
寫程式中、折磨中、享受中 ......
992   0  
·
2019/03/07
·
4 mins read


網站,少不了要用到外部的 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



WriterShelf™ is a unique multiple pen name blogging and forum platform. Protect relationships and your privacy. Take your writing in new directions. ** Join WriterShelf**
WriterShelf™ is an open writing platform. The views, information and opinions in this article are those of the author.


Article info

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


Share this article:
About the Author

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




Join the discussion now!
Don't wait! Sign up to join the discussion.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.