無阻塞載入和defer、async

来源:http://www.cnblogs.com/kevin2chen/archive/2017/02/06/6369058.html
-Advertisement-
Play Games

無阻塞載入 把js放在head里,瀏覽器是怎麼去執行它的呢,是按順序載入還是並行載入呢?在舊的瀏覽器下,都是按照先後順序來載入的,這就保證了載入的js依賴不會發生問題。但是少部分新的瀏覽器已經開始允許並行載入js了,也就是說可以同時下載js文件,但是還是按先後順序執行文件的。 下載是非同步的沒問題,但 ...


無阻塞載入

把js放在head里,瀏覽器是怎麼去執行它的呢,是按順序載入還是並行載入呢?在舊的瀏覽器下,都是按照先後順序來載入的,這就保證了載入的js依賴不會發生問題。但是少部分新的瀏覽器已經開始允許並行載入js了,也就是說可以同時下載js文件,但是還是按先後順序執行文件的。

下載是非同步的沒問題,但是每個javascript執行的時候還是同步的,就是先出現的script標簽一定是先執行,即使是並行下載它是最後一個下載完成的,除非標有defer的script標簽。任何javascript在執行的時候都會中斷當前html文檔解析,自然會阻止頁面渲染。

javascript載入是不會影響已經渲染的頁面,但是會中斷html文檔解析,瀏覽器會在javascript執行以後決定當前文檔是否需要進行重新渲染或者文檔重排。所以即使javascript放到最後面也會使瀏覽器暫停,但不影響之前已經解析出來的dom文檔,此時對於用戶來說是可操作的。

javascript下載完畢之後會立即執行,所有的javascript執行都會阻塞瀏覽器的其他行為,例如阻塞其他javascript的執行、其他的http請求的執行以及頁面的解析和渲染。(html文檔中外部js的下載也會阻塞瀏覽器的行為,但通過創建script元素動態js的下載不會,可能是認為動態的js不會改變頁面效果,所以允許資源並行下載。

         圖示動態腳本的下載

UI線程會根據頁面里資源(資源是指css文件,圖片等等)書寫的先後順序來載入資源,載入資源也就是使用http請求獲取資源,像css外部文件,html文件以及圖片等資源http請求處理完畢也就意味著資源載入結束,但是像外部的javascript文件的載入則不同,它的載入過程被分為兩步,第一步和載入css文件和圖片一樣,就是執行一個http請求下載外部的js文件,但是javascript完成http操作後並不意味操作完畢,UI線程接著會執行它。js腳本的下載和執行必須是一個完整的操作,是不能被割裂的。動態js的下載不會阻塞,但執行一定會會。

瀏覽器為了提升用戶體驗,加快UI線程的執行是一個無法迴避的問題,但是拆分js的下載和執行是不可行的,如是乎瀏覽器換了種方式,這個方式也就是在同一個時間能下載多個資源。

將常用的,穩定的靜態資源統一放在一個靜態資源伺服器上,由統一的功能變數名稱對外提供,這個功能變數名稱要和主體請求的功能變數名稱不一樣,原理是因為瀏覽器只通過功能變數名稱來限制連接的個數,如果一個頁面里有兩個不同的域的,那麼並行的http請求個數也會變成兩倍。有度,對DNS解析要開銷,所以2個最佳。

 

將所有外部js代碼分為UI初始化代碼和其他代碼,UI初始化代碼是在頁面載入時候執行的代碼。讓那些不會用於頁面初始化展示的js代碼的載入和執行操作通過onload事件在瀏覽器忙指示結束後觸發,即讓那些和頁面載入無關的js腳本在onload方法里執行

無阻塞載入腳本的核心技術就是動態的創建script的dom節點,而且可以跨域訪問。

         var script=document.createElement("script");

         script.type="text/javascript";

         script.src="file.js";

         document.getElementsByTagName("head")[0].appendChild(script);

動態腳本元素,就是說 <script> 標簽不是寫死在HTML中的,而是由現有的腳本生成的,因為 <script> 標簽也是DOM元素的一種,而JavaScript是可以通過DOM API操作DOM的。動態腳本只有在新建的script元素被添加到html文檔時開始下載,下載完立即執行。

無阻塞腳本的好處就是不會阻塞UI的執行,也不會影響其他同步js代碼的執行,不無阻塞腳本改變了腳本的載入順序,所以在使用無阻塞腳本時候一定要更加註意腳本之間的依賴關係,保證整個頁面的腳本都能正常執行。

使用無阻塞腳本了,代碼置於head標簽還是html文檔底部也就無關緊要了。

頁面載入的總時間不是衡量頁面載入快捷的標準,頁面同步阻塞載入的時間才是衡量頁面載入效率的準確標準,非阻塞腳本載入可能會增加整個頁面載入的時間,但是它可以減少頁面阻塞載入的時間。

腳本的非同步執行,會產生前後依賴的問題。在腳本載入執行完畢後,非ie瀏覽器會觸發該 <script> 元素的 onload 事件,ie瀏覽器下有onreadystatechange事件,我們可以將回調放到這個事件中處理。

 

每當瀏覽器解析到<script>標簽(無論內嵌還是外鏈)時,瀏覽器會優先下載、解析並執行該標簽中的javaScript代碼,而阻塞其後所有頁面內容的下載和渲染。(也就是說外部js的下載也會阻塞別的線程,目前有少部分瀏覽器支持並行下載js)

無阻塞載入腳本技術的核心就是:動態下載js腳本的時候,不會阻塞UI線程的執行。動態腳本為什麼不阻塞ui線程?可能是因為瀏覽器認為動態資源不會影響頁面渲染。

        

 

 

 

script延遲和非同步的兩個屬性:deferasync

js腳本會改變文檔輸入流的內容,所以執行js時會暫停頁面的渲染。對於內聯腳本沒什麼問題,因為腳本和html文檔被同時載入了。但對於外部引入的腳本,腳本的下載(取決於網速)也會阻塞瀏覽器文檔的解析和渲染,甚至會阻塞有些瀏覽器下載別的資源(目前有些瀏覽器已經實現並行下載)。所以出現defer和async屬性,優化頁面的顯示。

defer(延遲)是html4.0中定義的,該屬性使得瀏覽器能延遲腳本的下載,等document文檔載入和解析完成後,按照他們在文檔中出現順序再去下載解析。也就是說defer屬性的<script>就類似於將<script>放在body底部的效果,會在document的DOMContentLoaded事件之前執行。

將腳本放在body底部比給腳本增加defer屬性讓腳本延遲載入更好。

async(非同步)是HTML5新增的屬性,該屬性的作用是讓瀏覽器能並行下載腳本且不阻塞瀏覽器的文檔解析和渲染,下載完成後腳本立即執行,可能無序執行,取決於下載完成的時間)

若瀏覽器同時支持上述兩種屬性且script標簽同時具有這兩種屬性,則async屬性會優於defer生效。

在不支持async屬性的瀏覽器里,可以通過動態創建script元素並插入文檔中,實現腳本的非同步載入和執行:

 

requirejs就是使用這個方法實現的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Smobiler是一個在VS環境中使用.Net語言來開發APP的開發平臺,也許比Xamarin更方便 ...
  • 百萬行代碼架構遷移——有感 背景 身處互聯網暫不知名公司,16年6月份接受公司項目,主要職責是線上項目問題維護、項目開發SE工作附帶項目組事務管理,目前領隊十來人。由於項目整體研發已有4年,中間團隊人員換了幾波,技術總監和項目架構核心設計人員先後離職,項目前景不容樂觀。 舊項目結構描述 java系項 ...
  • 一、概述 代理模式為另一個對象提供一個替身或占位符以控制對這個對象的訪問。其實就是代理就是做到類似轉發的功能,針對不同代理,轉發的具體實現不同。 二、解決問題 從原理知道他就是控制客戶對一個對象的訪問,它跟現實中的中介代理類似,只是作為代表做一些受理工作,真正執行的並不是它自己。比如買火車票,外面有 ...
  • 1、建造者模式UML 圖1. 建造者模式UML 2、C++實現 C++實現類視圖: 圖2. 建造者模式C++實現的類視圖 其中,Product的實現代碼是(ProductA和ProductB的代碼不再列出): Builder實現代碼是: ConcreteBuilderA的實現代碼是: Concret ...
  • 定義:策略模式定義了演算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓演算法的變化獨立於使用演算法的客戶。 一個使用了策略模式案例的UML類圖:(https://github.com/sunhuace/GOF-23.git) 個人見解:策略模式通過封裝演算法族,使用多態的方式持有FlyBehavevi ...
  • 1、抽象工廠模式UML 圖1. 抽象工廠模式的UML 2、C++實現 C++實現類圖為: 圖2. 抽象工廠模式的C++實現類圖 其中,AbstractFactory的實現代碼為: ConcreteFactoryA的實現代碼為: 其中,ConcreteFactory2的代碼與ConcreteFacto ...
  • 最近研究下java語言,根據一般使用的情況,寫了個連接通訊服務的框架; 框架結構 C-Manager-S; 把所有通訊內容抽取成三個方法介面:GetData,SetData,帶返還的Get; 所有數據都處理為byte[];客戶端與服務端和管理器以及服務端有多重處理模式 管理信息: 1.不需要中心管理 ...
  • A 調用攝像頭拍照,自定義裁剪編輯頭像 【新錄針對本系統的視頻教程,手把手教開發一個模塊,快速掌握本系統】B 集成代碼生成器 [正反雙向](單表、主表、明細表、樹形表,開發利器)+快速構建表單; 技術:313596790 freemaker模版技術 ,0個代碼不用寫,生成完整的一個模塊,帶頁面、建表 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...