Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产一区二区高清视频,亚洲精品一区国产二区,激情免费视频

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          瀏覽器層面優化前端性能(2):Reader引擎線程與模塊分析優化點

          eader 引擎線程與模塊分析


          首先是網頁內容,加載完輸入到HTML解釋器,解釋后構成DOM樹,這期間如果遇到JavaScript代碼就交給JavaScript引擎去處理,如果網頁中包含CSS,就交給CSS解釋器;DOM樹簡歷的時候,渲染引擎接收來自CSS解釋器的樣式信息,構建一個新的你日不會吐模型,該模型由布局模塊計算模型內部各個元素的位置和大小信息

          渲染流程有四個主要步驟:

          1. 解析HTML生成DOM樹 - 渲染引擎首先解析HTML文檔,生成DOM樹
          2. 構建Render樹 - 接下來不管是內聯式,外聯式還是嵌入式引入的CSS樣式會被解析生成CSSOM樹,根據DOM樹與CSSOM樹生成另外一棵用于渲染的樹-渲染樹(Render tree),
          3. 布局Render樹 - 然后對渲染樹的每個節點進行布局處理,確定其在屏幕上的顯示位置
          4. 繪制Render樹 - 最后遍歷渲染樹并用UI后端層將每一個節點繪制出來

          DOM樹與Render樹

          renderer與DOM元素是相對應的,但并不是一一對應,有些DOM元素沒有對應的renderer,而有些DOM元素卻對應了好幾個renderer,對應多個renderer的情況是普遍存在的,就是為了解決一個renderer描述不清楚如何顯示出來的問題,譬如有下拉列表的select元素,我們就需要三個renderer:一個用于顯示區域,一個用于下拉列表框,還有一個用于按鈕。

          另外,renderer與DOM元素的位置也可能是不一樣的。那些添加了float或者position:absolute的元素,因為它們脫離了正常的文檔流,構造Render樹的時候會針對它們實際的位置進行構造。

          布局與繪制

          上面確定了renderer的樣式規則后,然后就是重要的顯示元素布局了。當renderer構造出來并添加到Render樹上之后,它并沒有位置跟大小信息,為它確定這些信息的過程,接下來是布局(layout)。

          瀏覽器進行頁面布局基本過程是以瀏覽器可見區域為畫布,左上角為(0,0)基礎坐標,從左到右,從上到下從DOM的根節點開始畫首先確定顯示元素的大小跟位置,此過程是通過瀏覽器計算出來的,用戶CSS中定義的量未必就是瀏覽器實際采用的量。如果顯示元素有子元素得先去確定子元素的顯示信息

          布局階段輸出的結果稱為box盒模型(width,height,margin,padding,border,left,top,…),盒模型精確表示了每一個元素的位置和大小,并且所有相對度量單位此時都轉化為了絕對單位。

          在繪制(painting)階段,渲染引擎會遍歷Render樹,并調用renderer的 paint() 方法,將renderer的內容顯示在屏幕上。繪制工作是使用UI后端組件完成的。

          回流與重繪

          回流(reflow)當瀏覽器發現某個部分發生了點變化影響了布局,需要倒回去重新渲染。reflow 會從<html>這個 root frame 開始遞歸往下,依次計算所有的結點幾何尺寸和位置。reflow 幾乎是無法避免的。現在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯示與隱藏)等,都將引起瀏覽器的 reflow。鼠標滑過、點擊……只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響著。


          重繪(repaint):改變某個元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內部布局的屬性時,屏幕的一部分要重畫,但是元素的幾何尺寸沒有變。


          關鍵渲染路徑與阻塞渲染

          在瀏覽器拿到HTML、CSS、JS等外部資源到渲染出頁面的過程,有一個重要的概念關鍵渲染路徑(Critical Rendering Path)。

          例如為了保障首屏內容的最快速顯示,通常會提到一個漸進式頁面渲染,但是為了漸進式頁面渲染,就需要做資源的拆分,那么以什么粒度拆分、要不要拆分,不同頁面、不同場景策略不同。

          現代瀏覽器總是并行加載資源,例如,當 HTML 解析器(HTML Parser)被腳本阻塞時,解析器雖然會停止構建 DOM,但仍會識別該腳本后面的資源,并進行預加載。

          • CSS 被視為渲染阻塞資源(包括JS),這意味著瀏覽器將不會渲染任何已處理的內容,直至 CSSOM 構建完畢,才會進行下一階段。
          • 存在阻塞的 CSS 資源時,瀏覽器會延遲 JavaScript 的執行和 DOM 構建
            • css加載不會阻塞DOM樹的解析
            • css加載會阻塞DOM樹的渲染
            • css不會阻塞JS的加載
            • css加載會阻塞后面js語句的執行
          • JavaScript 被認為是解釋器阻塞資源,HTML解析會被JS阻塞,它不僅可以讀取和修改 DOM 屬性,還可以讀取和修改 CSSOM 屬性。
            • 當瀏覽器遇到一個 script 標記時,DOM 構建將暫停,直至腳本完成執行。
            • JavaScript 可以查詢和修改 DOM 與 CSSOM。
            • CSSOM 構建時,JavaScript 執行將暫停,直至 CSSOM 就緒。
            • 沒有js的理想情況下,html與css會并行解析,分別生成DOM與CSSOM,然后合并成Render Tree,進入Rendering Pipeline;但如果有js,css加載會阻塞后面js語句的執行,而(同步)js腳本執行會阻塞其后的DOM解析(所以通常會把css放在頭部,js放在body尾)

          CSS 優先:引入順序上,CSS 資源先于 JavaScript 資源。JavaScript 應盡量少影響 DOM 的構建。

          改變腳本加載次序defer/async/document.createElement

          defer

          defer 屬性表示延遲執行引入 JavaScript,即 JavaScript 加載時 HTML 并未停止解析,這兩個過程是并行的。整個 document 解析完畢且 defer-script 也加載完成之后(這兩件事情的順序無關),會執行所有由 defer-script 加載的 JavaScript 代碼,再觸發DOMContentLoaded(初始的 HTML 文檔被完全加載和解析完成之后觸發,無需等待樣式表圖像和子框架的完成加載) 事件。

          defer 不會改變 script 中代碼的執行順序,示例代碼會按照 1、2、3 的順序執行。所以,defer 與相比普通 script,有兩點區別:載入 JavaScript 文件時不阻塞 HTML 的解析,執行階段被放到 HTML 標簽解析完成之后。

          async

          async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在于,如果已經加載好,就會開始執行,無論此刻是 HTML 解析階段還是 DOMContentLoaded 觸發(HTML解析完成事件)之后。需要注意的是,這種方式加載的 JavaScript 依然會阻塞 load 事件。換句話說,async-script 可能在 DOMContentLoaded 觸發之前或之后執行,但一定在 load 觸發之前執行。

          從上一段也能推出,多個 async-script 的執行順序是不確定的,誰先加載完誰執行。值得注意的是,向 document 動態添加 script 標簽時,async 屬性默認是 true。

          document.createElement

          使用 document.createElement 創建的 script 默認是異步的

          通過動態添加 script 標簽引入 JavaScript 文件默認是不會阻塞頁面的。如果想同步執行,需要將 async 屬性人為設置為 false。

          優化渲染性能

          chrome 官方文檔:https://developers.google.com/web/fundamentals/performance/?hl=en

          翻譯:https://x5.tencent.com/tbs/document/doc-chrome.html

          優化JS的執行效率

          動畫實現使用requestAnimationFrame

          setTimeout(callback)和setInterval(callback)無法保證callback函數的執行時機,很可能在幀結束的時候執行,從而導致丟幀。

          requestAnimationFrame(callback)可以保證callback函數在每幀動畫開始的時候執行。拓展閱讀《頻率史—從電源頻率到音頻采樣頻率與視頻幀率:29.97/44.1》、《弄懂javascript的執行機制:事件輪詢|微任務和宏任務》

          長耗時的JS代碼放到Web Workers中執行

          JS代碼運行在瀏覽器的主線程上,與此同時,瀏覽器的主線程還負責樣式計算、布局、繪制的工作,如果JavaScript代碼運行時間過長,就會阻塞其他渲染工作,很可能會導致丟幀。

          前面提到每幀的渲染應該在16ms內完成,但在動畫過程中,由于已經被占用了不少時間,所以JavaScript代碼運行耗時應該控制在3-4毫秒。

          如果真的有特別耗時且不操作DOM元素的純計算工作,可以考慮放到Web Workers中執行。

          CSS渲染與布局優化

          添加或移除一個DOM元素、修改元素屬性和樣式類、應用動畫效果等操作,都會引起DOM結構的改變,從而導致瀏覽器要repaint或者reflow。

          降低樣式選擇器的復雜度

          • 盡量保持class的簡短,或者使用Web Components框架(如:Omi)。
          • 降低樣式選擇器的復雜度;使用基于class的方式,比如BEM(Block, Element, Modifier)。
          • 減少css嵌套,如sass使用@at-root
          • 減少需要執行樣式計算的元素的個數
          • 對于樣式計算來說,范圍越小、規則越簡單的話,處理效率越高。
            • 在過去,如果你修改了body元素的class屬性,那么頁面里所有元素都要重新計算樣式。現代的瀏覽器中不再這樣做了,瀏覽器不會檢查所有受到樣式變化影響的元素。因為會對每個DOM元素維護一個獨有的樣式規則小集合,如果這個集合發生改變,才重新計算該元素的樣式。所以,樣式計算一般是直接對那些目標元素執行。因此我們應該盡可能減少需要執行樣式計算的元素的個數
            • 一般來說在最壞的情況下,樣式計算量 = 元素個數 x 樣式選擇器個數因為對每個元素最少需要檢查一次所有的樣式,以確認是否
            • Web Components中的樣式計算不會跨越Shadow DOM范圍,僅在單個的Web Component中進行,而不是在整個頁面的DOM樹上進行

          避免大規模、復雜的布局

          布局,就是瀏覽器計算DOM元素的幾何信息的過程:元素大小和在頁面中的位置。每個元素都有一個顯式或隱式的大小信息,決定于其CSS屬性的設置、或是元素本身內容的大小、抑或是其父元素的大小。在Blink/WebKit內核的瀏覽器和IE中,這個過程稱為布局。在基于Gecko的瀏覽器(比如Firefox)中,這個過程稱為Reflow。

          盡可能避免觸發布局

          布局的時間消耗主要在于:

          • 需要布局的DOM元素的數量
          • 布局過程的復雜程度

          一份詳細的能觸發布局、繪制或渲染層合并的CSS屬性清單:CSS Triggers

          使用flexbox替代老的布局模型

          新的Flexbox比舊的Flexbox和基于浮動的布局模型更高效。

          在任何情況下,不管是是否使用Flexbox,你都應該努力避免同時觸發所有布局,特別在頁面對性能敏感的時候(比如執行動畫效果或頁面滾動時)。

          避免強制同步布局事件的發生

          將一幀畫面渲染到屏幕上的處理順序如下所示:

          • 在JavaScript腳本運行的時候,它能獲取到的元素樣式屬性值都是上一幀畫面的,都是舊的值。
          • 如果想在這一幀開始的時候,讀取一個元素屬性值,就需要修改當前元素的某個屬性(可能觸發重繪與回流)。
          • 為了避免觸發不必要的布局過程,你應該首先批量讀取元素樣式屬性,然后再對樣式屬性進行寫操作。

          大多數情況下,都不需要先修改然后再讀取元素的樣式屬性值,使用上一幀的值就足夠了。過早地同步執行樣式計算和布局是潛在的頁面性能的瓶頸之一

          避免快速連續的布局

          比強制同步布局更糟:連續快速的多次執行它。如:

          for (var i = 0; i < paragraphs.length; i++) {
               paragraphs[i].style.width = box.offsetWidth + 'px';
          }

          FastDom是一個輕量的庫,它提供一個公共接口,能讓DOM的讀/寫操作捆綁在一起。

          https://github.com/wilsonpage/fastdom

          簡化繪制的復雜度、減小繪制區域

          繪制并非總是在內存中的單層畫面里完成的。實際上,瀏覽器在必要時將會把一幀畫面繪制成多層畫面,然后將這若干層畫面合并成一張圖片顯示到屏幕上。

          這種繪制方式的好處是,使用tranforms來實現移動效果的元素將會被正常繪制,同時不會觸發對其他元素的繪制。這種處理方式和思想跟圖像處理軟件(比如Sketch/GIMP/Photoshop)是一致的,它們都是可以在圖像中的某個單個圖層上做操作,最后合并所有圖層得到最終的圖像。

          提升移動或漸變元素的繪制層

          • 在頁面中創建一個新的渲染層的最好方式就是使用CSS屬性will-change,同時再與transform屬性一起使用,就會創建一個新的組合層:will-change: transform;
          • 對于那些目前還不支持will-change屬性、但支持創建渲染層的瀏覽器,以使用一個3D transform屬性來強制瀏覽器創建一個新的渲染層:transform: translateZ(0);

          減少繪制區域

          有時候盡管把元素提升到了一個單獨的渲染層,渲染工作依然是必須的。渲染過程中一個比較有挑戰的問題是,瀏覽器會把兩個相鄰區域的渲染任務合并在一起進行,這將導致整個屏幕區域都會被繪制。比如,你的頁面頂部有一個固定位置的header,而此時屏幕底部有某個區域正在發生繪制的話,整個屏幕都將會被繪制。

          注意:在DPI較高的屏幕上,固定定位的元素會自動地被提升到一個它自有的渲染層中。但在DPI較低的設備上卻并非如此,因為這個渲染層的提升會使得字體渲染方式由子像素變為灰階(詳細內容請參考:Text Rendering),我們需要手動實現渲染層的提升。

          減少繪制區域通常需要對動畫效果進行精密設計,以保證各自的繪制區域之間不會有太多重疊,或者想辦法避免對頁面中某些區域執行動畫效果。

          簡化繪制的復雜度

          比如js 獲取元素的offsetTop ffsetTop 比如getBoundingClientRect 消耗更少。

          在css里面,重繪 backgroun 比如 box-shadow 消耗更好。

          那些能性能更加耗資源,我也不知道,道友若知,請留言賜教,多謝。手工就 paint profiler 分析對比咯

          優先使用渲染層合并屬性、控制層數量

          • 只使用transform/opacity來實現動畫效果
          • 應用了transforms/opacity屬性的元素必須獨占一個渲染層。為了對這個元素創建一個自有的渲染層,你必須提升該元素。在合成層上面的元素,也會合并到此圖層中。
          • 用will-change/translateZ屬性把動畫元素提升到單獨的渲染層中
          • 避免濫用渲染層提升:更多的渲染層需要更多的內存和更復雜的管理
          • 過多的渲染層來帶的開銷而對頁面渲染性能產生的影響,甚至遠遠超過了它在性能改善上帶來的好處。由于每個渲染層的紋理都需要上傳到GPU處理,因此我們還需要考慮CPU和GPU之間的帶寬問題、以及有多大內存供GPU處理這些紋理的問題。

          從性能方面考慮,最理想的渲染流水線是沒有布局和繪制環節的,只需要做渲染層的合并即可:

          之前也參看:《關于css3之transform一些坑的總結-transform對普通元素的N多渲染》

          對用戶輸入事件的處理去抖動

          • 避免使用運行時間過長的輸入事件處理函數,它們會阻塞頁面的滾動
          • 避免在輸入事件處理函數中修改樣式屬性
          • 對輸入事件處理函數去抖動,存儲事件對象的值,然后在requestAnimationFrame 回調函數中修改樣式屬性

          具體參看《Debounce 和 Throttle 的原理及實現》


          參考文章:

          從瀏覽器多進程到JS單線程,JS運行機制最全面的一次梳理 https://www.cnblogs.com/cangqinglang/p/8963557.html

          Chrome源碼剖析、上--多線程模型、進程通信、進程模型https://www.cnblogs.com/v-July-v/archive/2011/04/02/2036008.html

          Chrome源代碼分析之進程和線程模型(三) https://blog.csdn.net/namelcx/article/details/6582730

          http://dev.chromium.org/developers/design-documents/multi-process-architecture

          chrome渲染機制淺析 https://www.jianshu.com/p/99e450fc04a5

          淺析瀏覽器渲染原理 https://segmentfault.com/a/1190000012960187

          javascript宏任務和微任務 https://www.cnblogs.com/fangdongdemao/p/10262209.html

          瀏覽器與Node的事件循環(Event Loop)有何區別? https://blog.csdn.net/Fundebug/article/details/86487117





          轉載本站文章《瀏覽器層面優化前端性能(2):Reader引擎線程與模塊分析優化點》,
          請注明出處:https://www.zhoulujun.cn/html/webfront/browser/webkit/2020_0615_8464.html

          在面試的時候,經常會遇到一道經典的面試題:

          如何優化網頁加載速度?

          常規的回答中總會有一條:

          把 css 文件放在頁面頂部,把 js 文件放在頁面底部。

          那么,為什么要把 js 文件放在頁面的最底部呢?

          我們先來看下這段代碼:

          <!DOCTYPE html>
          <html lang="zh">
            <head>
              <title>Hi</title>
              <script>
                  console.log("Howdy ~");
              </script>
              <script src="https://unpkg.com/vue@3.2.41/dist/vue.global.js"></script>
              <script src="https://unpkg.com/vue-router@4.1.5/dist/vue-router.global.js"></script>
            </head>
            <body>
              Hello  ~
            </body>
          </html>

          他的執行順序是:

          • 在控制臺打印:Howdy ~
          • 請求并執行 vue.global.js
          • 請求并執行 vue-router.global.js
          • 在頁面中展示:Hello ~
          • 觸發 DOMContentLoaded 事件

          script 加載邏輯

          瀏覽器的解析規則是:如果遇到 script 標簽,則暫停構建 DOM,轉而開始執行 script 標簽,如果是外部 script,那么瀏覽器還需要一直等待其「下載」并「執行」后,再繼續解析后面的 HTML。

          如果請求并執行「vue.global.js」需要 3 秒,「vue-router.global.js」需要 2 秒,那么頁面中的 Hello ~,則至少需要 5 秒以上才會展示出來。

          可以看到,script 標簽會阻塞瀏覽器解析 HTML,如果把 script 都放在 head 中,在網絡不佳的情況下,就會導致頁面長期處于白屏狀態。

          在很久以前,一般都是將這些外聯腳本,放在 body 標簽的最后面,確保先解析展示 body 中的內容,然后再一個個請求執行這些外聯腳本。

          那有沒有其他更優雅的解決方案呢?

          答案是肯定的,現在 script 標簽新增了 2 個屬性:deferasync,就是為了解決此類問題,提升頁面性能的。

          <script defer>

          先看一下 MDN 上的解釋:

          這個布爾屬性被設定用來通知瀏覽器該腳本將在文檔完成解析后,觸發 DOMContentLoaded 事件前執行。

          有 defer 屬性的腳本會阻止 DOMContentLoaded 事件,直到腳本被加載并且解析完成。

          文檔是直接總結了他的特性,我們先看看下面的代碼,展開說說細節,加深一下理解。

          <!DOCTYPE html>
          <html lang="zh">
            <head>
              <title>Hi</title>
              <script>
                console.log("Howdy ~");
              </script>
              <script defer src="https://unpkg.com/vue@3.2.41/dist/vue.global.js"></script>
              <script defer src="https://unpkg.com/vue-router@4.1.5/dist/vue-router.global.js"></script>
            </head>
            <body>
              Hello  ~
            </body>
          </html>

          他的執行順序是:

          • 在控制臺打印:Howdy ~
          • 在頁面中展示:Hello ~
          • 請求并執行 vue.global.js
          • 請求并執行 vue-router.global.js
          • 觸發 DOMContentLoaded 事件

          script defer 加載邏輯

          如果在 script 標簽上設置了 defer 屬性,那么在瀏覽器解析到這里時,會默默的在后臺開始下載此腳本,并繼續解析后面的 HTML,并不會阻塞解析操作。

          等到 HTML 解析完成之后,瀏覽器會立即執行后臺下載的腳本,腳本執行完成之后,才會觸發 DOMContentLoaded 事件。

          看起來還是蠻好理解的吧?咱們再來討論 2 個小細節:

          Q1: 如果 HTML 解析完成之后,設置了 defer 屬性的腳本還沒下載完成,會怎樣?

          A1: 瀏覽器會等腳本下載完成之后,再執行此腳本,執行完成之后,再觸發 DOMContentLoaded 事件。

          Q2: 如果有多個設置了 defer 屬性的腳本,那瀏覽器會如何處理?

          A2: 瀏覽器會并行的在后臺下載這些腳本,等 HTML 解析完成,并且所有腳本下載完成之后,再按照他們在 HTML 中出現的相對順序執行,等所有腳本執行完成之后,再觸發 DOMContentLoaded 事件。

          最佳實踐:

          建議所有的外聯腳本都默認設置此屬性,因為他不會阻塞 HTML 解析,可以并行下載 JavaScript 資源,還可以按照他們在 HTML 中的相對順序執行,確保有依賴關系的腳本運行時,不會缺少依賴。

          在 SPA 的應用中,可以考慮把所有的 script 標簽加上 defer 屬性,并且放到 body 的最后面。在現代瀏覽器中,可以并行下載提升速度,也可以確保在老瀏覽器中,不阻塞瀏覽器解析 HTML,起到降級的作用。

          注意:

          • defer 屬性僅適用于外部腳本,如果 script 腳本沒有 src,則會忽略 defer 特性。
          • defer 屬性對模塊腳本(script type='module')無效,因為模塊腳本就是以 defer 的形式加載的。

          <script async>

          按照慣例,先看一下 MDN 上的解釋:

          對于普通腳本,如果存在 async 屬性,那么普通腳本會被并行請求,并盡快解析和執行。

          對于模塊腳本,如果存在 async 屬性,那么腳本及其所有依賴都會在延緩隊列中執行,因此它們會被并行請求,并盡快解析和執行。


          該屬性能夠消除解析阻塞的 Javascript。

          解析阻塞的 Javascript 會導致瀏覽器必須加載并且執行腳本,之后才能繼續解析。

          感覺這段描述的已經蠻清晰了,不過咱們還是先看看下面的代碼,展開說說細節,加深一下理解。

          <!DOCTYPE html>
          <html lang="zh">
            <head>
              <title>Hi</title>
              <script>
                console.log("Howdy ~");
              </script>
              <script async src="https://google-analytics.com/analytics.js"></script>
              <script async src="https://ads.google.cn/ad.js"></script>
            </head>
            <body>
              Hello  ~
            </body>
          </html>

          他的執行順序是:

          • 在控制臺打印:Howdy ~
          • 并行請求 analytics.jsad.js
          • 在頁面中展示:Hello ~
          • 根據網絡的實際情況,以下幾項會無序執行 執行 analytics.js(下載完后,立即執行)執行 ad.js(下載完后,立即執行)觸發 DOMContentLoaded 事件(可能在在上面 2 個腳本之前,之間,之后觸發)

          script async 加載邏輯

          瀏覽器在解析到帶有 async 屬性的 script 標簽時,也不會阻塞頁面,同樣是在后臺默默下載此腳本。當他下載完后,瀏覽器會暫停解析 HTML,立馬執行此腳本。

          看起來還是蠻好理解的吧?咱們再來討論 2 個小細節:

          Q1:如果設置了 async 屬性的 script 下載完之后,瀏覽器還沒解析完 HTML,會怎樣?

          A1:瀏覽器會暫停解析 HTML,立馬執行此腳本,等執行完之后,再繼續解析 HTML。

          Q2:如果有多個 async 屬性的 script 標簽,那等他們下載完成之后,會按照代碼順序執行嗎?

          A2:不會。執行順序是:誰先下載完成,誰先執行。async 的特點是「完全獨立」,不依賴其他內容。

          最佳實踐:

          當我們的項目,需要集成其他獨立的第三方庫時,可以使用此屬性,他們不依賴我們,我們也不依賴于他們。 通過設置此屬性,讓瀏覽器異步下載并執行他,是個不錯的優化方案。

          注意:

          • async 特性僅適用于外部腳本,如果 script 腳本沒有 src,則會忽略 async 特性。

          總結

          defer

          • 不阻塞瀏覽器解析 HTML,等解析完 HTML 之后,才會執行 script
          • 會并行下載 JavaScript 資源。
          • 會按照 HTML 中的相對順序執行腳本。
          • 會在腳本下載并執行完成之后,才會觸發 DOMContentLoaded 事件。
          • 在腳本執行過程中,一定可以獲取到 HTML 中已有的元素。
          • defer 屬性對模塊腳本無效。
          • 適用于:所有外部腳本(通過 src 引用的 script)。

          async

          • 不阻塞瀏覽器解析 HTML,但是 script 下載完成后,會立即中斷瀏覽器解析 HTML,并執行此 script
          • 會并行下載 JavaScript 資源。
          • 互相獨立,誰先下載完,誰先執行,沒有固定的先后順序,不可控。
          • 由于沒有確定的執行時機,所以在腳本里面可能會獲取不到 HTML 中已有的元素。
          • DOMContentLoaded 事件和 script 腳本無相關性,無法確定他們的先后順序。
          • 適用于:獨立的第三方腳本。

          另外:asyncdefer 之間最大的區別在于它們的執行時機。

          One More Thing

          你有沒有想過,如果一個 script 標簽同時設置 deferasync,瀏覽器會如何處理?

          先說結論:從表現形式上來說,async 的優先級比 defer 高,也就是如果同時存在這 2 個屬性,那么瀏覽器將會以 async 的特性去加載此腳本。

          這主要分 2 種情況: 如果是「普通腳本」,瀏覽器會優先判斷async屬性是否存在,如果存在,則以async特性去加載此腳本,如果不存在,再去判斷是否存在defer屬性。

          如果是「模塊腳本」,瀏覽器會判斷async屬性是否存在:

          • 如果存在,瀏覽器會并行下載此模塊和他的所有依賴模塊,等全部下載完成之后,會立刻執行此腳本。
          • 如果不存在,瀏覽器也會并行下載此模塊和他的所有依賴模塊,然后等瀏覽器解析完 HTML 之后,再執行此腳本。
          • 另外需要注意的是:在模塊腳本上設置 defer 屬性是無效的。

          一圖勝千言

          最后,用一張圖概括一下這兩個屬性的加載模式吧:

          defer 和 async 的加載模式

          思考題

          • 為什么瀏覽器在解析到普通的 script 標簽時,必須先執行他?
          • 普通的 script 標簽會阻塞瀏覽器解析 HTML,這會導致什么問題?

          本文首發于:https://github.com/mrlmx/blogs/issues/4 ,如果喜歡,記得去點個贊哦~ ??

          參考

          • https://javascript.info/script-async-defer
          • https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
          • https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script
          • https://html.spec.whatwg.org/multipage/scripting.html

          站的加載速度是跳失率的關鍵因素,大多數買家對于網頁加載速度緩慢的網站會感到不耐煩。要了解網站的速度并提高網頁加載速度,你可以使用Google Page Speed Insights工具。

          本文將為你介紹該工具,了解它如何能夠幫助你優化網站。

          Google PageSpeed Insights是什么?

          Google Page Speed Insight(PSI)是一款旨在優化所有設備上的網頁、提高網頁加載速度的工具。

          它可以為以下各項創建單獨的診斷:

          1、桌面設備

          2、移動設備

          該工具會對網頁進行診斷,并提供頁面總體速度的分數,然后該工具會告訴你哪些地方需要優化。

          此外,該工具會對你的網頁在0到100之間評定一個分數,使你確切地知道網頁的運行狀況。

          以下是使用該工具提高網頁加載速度的方法。

          如何解決問題?

          將網站的URL粘貼到Page Speed Insights并獲得分析結果后,你需要查看紅色和黃色警報,以及導致網站運行緩慢的原因。

          下面是一些使你的網站運行緩慢的常見問題,以及如何修復這些問題的方法。

          常見的問題及其解決方法

          1、圖像尺寸

          每個網站都含有一定數量的圖像,以使網站更加人性化、更具吸引力或更加生動有趣。但是,圖像通常可能是導致網站運行以及加載時間緩慢的原因。

          如果Page Speed Insight提醒你有關圖像尺寸的信息,你則需要執行以下操作:

          · 查看上傳到網站上的圖像;

          · 使用壓縮工具或插件調整圖像大小;

          · 壓縮要上傳的圖像,以避免再次獲得低分。

          圖像經過壓縮后,你會注意到得分和加載速度有了顯著改善。

          此外,考慮使用延遲加載圖像,在實際需要顯示圖像的時候再進行加載,這也可以幫助你提高網頁速度。

          2、瀏覽器緩存

          每次瀏覽器加載網頁時,下載網頁文件的過程都會在后臺進行。瀏覽器需要下載正確顯示網頁所需的所有文件:

          · HTML;

          · 圖片;

          · CSS;

          · JavaScript。

          此過程會使整個過程變慢,并拉低分數。

          但是,瀏覽器緩存可以幫助你減少或消除此問題:

          · 它將文件存儲在用戶的瀏覽器中;

          · 用戶重新進入網站時就無需再次下載此類文件;

          · 網站加載速度更快。

          你可以使用緩存插件以優化網站、提高加載速度。

          3、停止加載CSS和JavaScript資源

          JavaScript文件也可能會拖慢網頁加載速度,這是一個不容忽視的常見問題。

          要阻止這種情況的發生,你需要先停止加載CSS和JavaScript資源。

          方法如下:

          · 內聯腳本;

          · 延遲加載不重要的腳本

          這樣,你可以確保提高加載速度,并顯著降低跳失率。

          4、精簡代碼

          Page Speed Insight工具可能會警告你的另一個問題是源代碼占用的空間。

          編碼會占用一定的空間,如果能對其進行精簡,則可以加快網頁加載時間。

          你可以通過刪除或修復重復數據來進行精簡,例如:

          · 空白空間;

          · 未使用的代碼;

          · 重復格式化;

          · 評論;

          · 等等。

          需要精簡的三個資源是:

          · JS;

          · CSS;

          · HTML。

          每個資源都有一個工具或插件,可以幫助你進行精簡。確保使用它們,并盡快解決此問題。

          5、重定向

          此外,重定向過程也會對加載速度造成影響。頁面加載時間要是過長,很可能是重定向導致其無法正常運轉的原因。

          當頁面重定向到針對某些設備優化過的不同頁面時,就會發生這種情況。

          那么,如何解決這個問題?

          有一種方法:確保構建適合所有設備的響應式設計。這樣,你就無需重定向,并且能夠提高網頁的加載速度。

          【限時免費】如何使用谷歌官方工具,解決營銷路上遇到的道道難關?

          (編譯/雨果網 陳杰)

          【特別聲明】未經許可同意,任何個人或組織不得復制、轉載、或以其他方式使用本網站內容。轉載請聯系:editor@cifnews.com

          上雨果網搜索“跨境資料庫”,領取歐美/東南亞各國市場商機、各大平臺熱銷品報告、跨境電商營銷白皮書!


          主站蜘蛛池模板: 日韩精品无码久久一区二区三| 国产精品高清一区二区人妖| 国产精品一区电影| 久久久无码一区二区三区| 亚洲国产成人久久一区久久| 亚洲天堂一区二区三区| 国产精品无码一区二区三区毛片| 综合无码一区二区三区| 精品国产一区AV天美传媒| 精品一区二区久久久久久久网站| 国产成人av一区二区三区在线| 亚洲av乱码一区二区三区香蕉| 上原亚衣一区二区在线观看| 精品一区二区高清在线观看| 日本一区二区三区日本免费| 无码一区18禁3D| 一区二区三区无码被窝影院| 亚洲综合无码一区二区三区| 亚洲国产综合精品中文第一区| 国产午夜精品一区二区| 国产精品女同一区二区久久| 合区精品久久久中文字幕一区| 日本一区二区三区在线网| 一区在线免费观看| 伊人精品视频一区二区三区| 亚洲熟女乱综合一区二区| 成人精品一区二区三区不卡免费看 | 果冻传媒董小宛一区二区| 国产在线不卡一区二区三区 | 亚洲无线码一区二区三区| 国产在线视频一区二区三区98| 精品国产亚洲一区二区三区| 国产精品视频一区二区三区四| 人妻激情偷乱视频一区二区三区 | 成人影片一区免费观看| 日韩精品无码一区二区三区AV| 亚洲国产精品乱码一区二区| 中字幕一区二区三区乱码| 国产在线一区二区视频| 国产精品一区二区久久沈樵| 制服中文字幕一区二区|