1.script標籤是如何加載的?
當瀏覽器遇到一個 < script>標籤時,瀏覽器會停下來,運行JavaScript代碼,而後再繼續解析、翻譯頁面。一樣的事情發生在使用 src 屬性加載 JavaScript 的過程當中。瀏覽器必須首先下載外部文件的代碼,須要佔用一些時間,而後解析並運行此JavaScript代碼。此過程當中,頁面解析和用戶交互是被徹底阻塞的。
2.script標籤該放在何處?
HTML 4 文檔指出,一個< script>標籤能夠放在 HTML 文檔的或標籤中,能夠在其中屢次出現。瀏覽器
這些代碼存在性能問題:在< head>部分加載了三個 JavaScript 文件。由於每一個< script>標籤阻塞了頁面的解析過程,直到它完整地下載並運行了外部 JavaScript 代碼以後,頁面 處理才能繼續進行。用戶必須忍受這種能夠察覺的延遲。瀏覽器在遇到< body>標籤以前,不會渲染頁面的任何部分。用這種方法把腳本放在頁面的頂端,將致使一個能夠察覺的延遲,一般表現爲:頁面打開時,首先顯示爲一幅空白的頁面,而此時用戶即不能閱讀,也不能與頁面進行交互操做。異步
能夠用一張圖片來表示這些資源的加載過程,紅色箭頭表示js代碼執行所用的時間async
能夠看到,第一個 JavaScript 文件開始下載,並阻塞了其餘文件的下載過程。在 file1.js 下載完以後和 file2.js 開始下載以前有一個延時,這是 file1.js 徹底運行所需的時間。每一個文件必須等待前一個文件下載完成並運行完以後,才能開始本身的下載過程。當這些文件下載時,用戶面
對一個空白的屏幕。
不過隨着瀏覽器的發展,Internet Explorer 8, Firefox 3.5, Safari 4, 和 Chrome 2 容許並行下載 JavaScript 文件。這代表,當一個< script>標籤正在下載外部資源時,沒必要阻塞其餘< script>標籤。不幸的是,JavaScript 的下載仍然要阻塞其餘資源的下載過程,例如圖片。即便腳本之間的下載過程互不阻塞,頁面仍舊要等待全部 JavaScript代碼下載並執行完成以後才能繼續。因此,當瀏覽器經過容許並行下載提升性能以後,該問題並無徹底解決。腳本阻塞仍舊是一個問題。
由於腳本阻塞其餘頁面資源的下載過程,因此推薦的辦法是:將全部< script>標籤放在儘量接近< body>標籤底部的位置,儘可能減小對整個頁面下載的影響。
3.減小外部JavaScript文件的數量
因爲每一個 HTTP 請求都會產生額外的性能負擔,下載一個 100KB 的文件比下載四個 25KB 的文件要快。當一個大型網站或網頁應用須要屢次請求 JavaScript 文件。能夠將這些文件整合成一個文件,只須要一個< script>標籤引用,就能夠減小性能損失。
4.採用非阻塞腳本
保持 JavaScript 文件短小,並限制 HTTP 請求的數量,只是建立反應迅速的網頁應用的第一步。一個應用程序所包含的功能越多,所須要的 JavaScript 代碼就越大。儘管下載一個大 JavaScript 文件只產生一次 HTTP 請求,卻會鎖定瀏覽器一大段時間。爲避開這種狀況,須要向頁面中逐步添加 JavaScript,某種程度上說不會阻塞瀏覽器。
非阻塞腳本的祕密在於,等頁面完成加載以後,再加載 JavaScript 源碼。這意味着在window 的 load 事件發出以後開始下載代碼。有幾種方法能夠實現這種效果。
1. 使用defer(延時腳本)和async(異步腳本)函數
defer 屬性指明元素中所包含的腳本不打算修改 DOM,所以代碼能夠稍後執行。注意:defer屬性只對外部腳本有用
一個帶有 defer 屬性的< script>標籤能夠放置在文檔的任何位置。對應的 JavaScript 文件將在< script>被解析時啓動下載,但代碼不會被執行,直到 DOM 加載完成。當一個 defer的 JavaScript 文件被下載時,它不會阻塞瀏覽器的其餘處理過程,因此這些文件能夠與頁面的其餘資源一塊兒並行下載。性能
async用於異步加載腳本,與defer的區別是:async加載完成後自動執行,defer須要等到頁面完成後(window.onload)才執行, 注意:多個標記爲 async 的腳本並不保證按照指定它們的前後順序執行(有多是file3.js, file2.js, file4.js,取決於誰先返回),覺得他們是異步加載的
2. 使用動態腳本元素
< script>元素與頁面其餘元素沒有什麼不一樣,因此他能夠從文檔中移動、刪除,也能夠被建立。一個新的< script>元素能夠很是容易地經過標準 DOM 函數建立:網站
新的< script>元素加載 file1.js 源文件。此文件當元素添加到頁面以後馬上開始下載。此技術的重點在於:不管在何處啓動下載,文件的下載和運行都不會阻塞其餘頁面處理過程。甚至能夠將這些代碼放在< head>部分而不會對其他部分的頁面代碼形成影響。
翻譯