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
首先是網頁內容,加載完輸入到HTML解釋器,解釋后構成DOM樹,這期間如果遇到JavaScript代碼就交給JavaScript引擎去處理,如果網頁中包含CSS,就交給CSS解釋器;DOM樹簡歷的時候,渲染引擎接收來自CSS解釋器的樣式信息,構建一個新的你日不會吐模型,該模型由布局模塊計算模型內部各個元素的位置和大小信息
渲染流程有四個主要步驟:
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 優先:引入順序上,CSS 資源先于 JavaScript 資源。JavaScript 應盡量少影響 DOM 的構建。
defer 屬性表示延遲執行引入 JavaScript,即 JavaScript 加載時 HTML 并未停止解析,這兩個過程是并行的。整個 document 解析完畢且 defer-script 也加載完成之后(這兩件事情的順序無關),會執行所有由 defer-script 加載的 JavaScript 代碼,再觸發DOMContentLoaded(初始的 HTML 文檔被完全加載和解析完成之后觸發,無需等待樣式表圖像和子框架的完成加載) 事件。
defer 不會改變 script 中代碼的執行順序,示例代碼會按照 1、2、3 的順序執行。所以,defer 與相比普通 script,有兩點區別:載入 JavaScript 文件時不阻塞 HTML 的解析,執行階段被放到 HTML 標簽解析完成之后。
async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在于,如果已經加載好,就會開始執行,無論此刻是 HTML 解析階段還是 DOMContentLoaded 觸發(HTML解析完成事件)之后。需要注意的是,這種方式加載的 JavaScript 依然會阻塞 load 事件。換句話說,async-script 可能在 DOMContentLoaded 觸發之前或之后執行,但一定在 load 觸發之前執行。
從上一段也能推出,多個 async-script 的執行順序是不確定的,誰先加載完誰執行。值得注意的是,向 document 動態添加 script 標簽時,async 屬性默認是 true。
使用 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
setTimeout(callback)和setInterval(callback)無法保證callback函數的執行時機,很可能在幀結束的時候執行,從而導致丟幀。
requestAnimationFrame(callback)可以保證callback函數在每幀動畫開始的時候執行。拓展閱讀《頻率史—從電源頻率到音頻采樣頻率與視頻幀率:29.97/44.1》、《弄懂javascript的執行機制:事件輪詢|微任務和宏任務》
JS代碼運行在瀏覽器的主線程上,與此同時,瀏覽器的主線程還負責樣式計算、布局、繪制的工作,如果JavaScript代碼運行時間過長,就會阻塞其他渲染工作,很可能會導致丟幀。
前面提到每幀的渲染應該在16ms內完成,但在動畫過程中,由于已經被占用了不少時間,所以JavaScript代碼運行耗時應該控制在3-4毫秒。
如果真的有特別耗時且不操作DOM元素的純計算工作,可以考慮放到Web Workers中執行。
添加或移除一個DOM元素、修改元素屬性和樣式類、應用動畫效果等操作,都會引起DOM結構的改變,從而導致瀏覽器要repaint或者reflow。
布局,就是瀏覽器計算DOM元素的幾何信息的過程:元素大小和在頁面中的位置。每個元素都有一個顯式或隱式的大小信息,決定于其CSS屬性的設置、或是元素本身內容的大小、抑或是其父元素的大小。在Blink/WebKit內核的瀏覽器和IE中,這個過程稱為布局。在基于Gecko的瀏覽器(比如Firefox)中,這個過程稱為Reflow。
布局的時間消耗主要在于:
一份詳細的能觸發布局、繪制或渲染層合并的CSS屬性清單:CSS Triggers
新的Flexbox比舊的Flexbox和基于浮動的布局模型更高效。
在任何情況下,不管是是否使用Flexbox,你都應該努力避免同時觸發所有布局,特別在頁面對性能敏感的時候(比如執行動畫效果或頁面滾動時)。
將一幀畫面渲染到屏幕上的處理順序如下所示:
大多數情況下,都不需要先修改然后再讀取元素的樣式屬性值,使用上一幀的值就足夠了。過早地同步執行樣式計算和布局是潛在的頁面性能的瓶頸之一
比強制同步布局更糟:連續快速的多次執行它。如:
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)是一致的,它們都是可以在圖像中的某個單個圖層上做操作,最后合并所有圖層得到最終的圖像。
有時候盡管把元素提升到了一個單獨的渲染層,渲染工作依然是必須的。渲染過程中一個比較有挑戰的問題是,瀏覽器會把兩個相鄰區域的渲染任務合并在一起進行,這將導致整個屏幕區域都會被繪制。比如,你的頁面頂部有一個固定位置的header,而此時屏幕底部有某個區域正在發生繪制的話,整個屏幕都將會被繪制。
注意:在DPI較高的屏幕上,固定定位的元素會自動地被提升到一個它自有的渲染層中。但在DPI較低的設備上卻并非如此,因為這個渲染層的提升會使得字體渲染方式由子像素變為灰階(詳細內容請參考:Text Rendering),我們需要手動實現渲染層的提升。
減少繪制區域通常需要對動畫效果進行精密設計,以保證各自的繪制區域之間不會有太多重疊,或者想辦法避免對頁面中某些區域執行動畫效果。
比如js 獲取元素的offsetTop ffsetTop 比如getBoundingClientRect 消耗更少。
在css里面,重繪 backgroun 比如 box-shadow 消耗更好。
那些能性能更加耗資源,我也不知道,道友若知,請留言賜教,多謝。手工就 paint profiler 分析對比咯
從性能方面考慮,最理想的渲染流水線是沒有布局和繪制環節的,只需要做渲染層的合并即可:
之前也參看:《關于css3之transform一些坑的總結-transform對普通元素的N多渲染》
具體參看《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>
他的執行順序是:
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 個屬性:defer 和 async,就是為了解決此類問題,提升頁面性能的。
先看一下 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>
他的執行順序是:
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,起到降級的作用。
注意:
按照慣例,先看一下 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>
他的執行順序是:
script async 加載邏輯
瀏覽器在解析到帶有 async 屬性的 script 標簽時,也不會阻塞頁面,同樣是在后臺默默下載此腳本。當他下載完后,瀏覽器會暫停解析 HTML,立馬執行此腳本。
看起來還是蠻好理解的吧?咱們再來討論 2 個小細節:
Q1:如果設置了 async 屬性的 script 下載完之后,瀏覽器還沒解析完 HTML,會怎樣?
A1:瀏覽器會暫停解析 HTML,立馬執行此腳本,等執行完之后,再繼續解析 HTML。
Q2:如果有多個 async 屬性的 script 標簽,那等他們下載完成之后,會按照代碼順序執行嗎?
A2:不會。執行順序是:誰先下載完成,誰先執行。async 的特點是「完全獨立」,不依賴其他內容。
最佳實踐:
當我們的項目,需要集成其他獨立的第三方庫時,可以使用此屬性,他們不依賴我們,我們也不依賴于他們。 通過設置此屬性,讓瀏覽器異步下載并執行他,是個不錯的優化方案。
注意:
另外:async 和 defer 之間最大的區別在于它們的執行時機。
你有沒有想過,如果一個 script 標簽同時設置 defer 和 async,瀏覽器會如何處理?
先說結論:從表現形式上來說,async 的優先級比 defer 高,也就是如果同時存在這 2 個屬性,那么瀏覽器將會以 async 的特性去加載此腳本。
這主要分 2 種情況: 如果是「普通腳本」,瀏覽器會優先判斷async屬性是否存在,如果存在,則以async特性去加載此腳本,如果不存在,再去判斷是否存在defer屬性。
如果是「模塊腳本」,瀏覽器會判斷async屬性是否存在:
最后,用一張圖概括一下這兩個屬性的加載模式吧:
defer 和 async 的加載模式
本文首發于:https://github.com/mrlmx/blogs/issues/4 ,如果喜歡,記得去點個贊哦~ ??
站的加載速度是跳失率的關鍵因素,大多數買家對于網頁加載速度緩慢的網站會感到不耐煩。要了解網站的速度并提高網頁加載速度,你可以使用Google Page Speed Insights工具。
本文將為你介紹該工具,了解它如何能夠幫助你優化網站。
Google Page Speed Insight(PSI)是一款旨在優化所有設備上的網頁、提高網頁加載速度的工具。
它可以為以下各項創建單獨的診斷:
1、桌面設備
2、移動設備
該工具會對網頁進行診斷,并提供頁面總體速度的分數,然后該工具會告訴你哪些地方需要優化。
此外,該工具會對你的網頁在0到100之間評定一個分數,使你確切地知道網頁的運行狀況。
以下是使用該工具提高網頁加載速度的方法。
將網站的URL粘貼到Page Speed Insights并獲得分析結果后,你需要查看紅色和黃色警報,以及導致網站運行緩慢的原因。
下面是一些使你的網站運行緩慢的常見問題,以及如何修復這些問題的方法。
每個網站都含有一定數量的圖像,以使網站更加人性化、更具吸引力或更加生動有趣。但是,圖像通常可能是導致網站運行以及加載時間緩慢的原因。
如果Page Speed Insight提醒你有關圖像尺寸的信息,你則需要執行以下操作:
· 查看上傳到網站上的圖像;
· 使用壓縮工具或插件調整圖像大小;
· 壓縮要上傳的圖像,以避免再次獲得低分。
圖像經過壓縮后,你會注意到得分和加載速度有了顯著改善。
此外,考慮使用延遲加載圖像,在實際需要顯示圖像的時候再進行加載,這也可以幫助你提高網頁速度。
每次瀏覽器加載網頁時,下載網頁文件的過程都會在后臺進行。瀏覽器需要下載正確顯示網頁所需的所有文件:
· HTML;
· 圖片;
· CSS;
· JavaScript。
此過程會使整個過程變慢,并拉低分數。
但是,瀏覽器緩存可以幫助你減少或消除此問題:
· 它將文件存儲在用戶的瀏覽器中;
· 用戶重新進入網站時就無需再次下載此類文件;
· 網站加載速度更快。
你可以使用緩存插件以優化網站、提高加載速度。
JavaScript文件也可能會拖慢網頁加載速度,這是一個不容忽視的常見問題。
要阻止這種情況的發生,你需要先停止加載CSS和JavaScript資源。
方法如下:
· 內聯腳本;
· 延遲加載不重要的腳本
這樣,你可以確保提高加載速度,并顯著降低跳失率。
Page Speed Insight工具可能會警告你的另一個問題是源代碼占用的空間。
編碼會占用一定的空間,如果能對其進行精簡,則可以加快網頁加載時間。
你可以通過刪除或修復重復數據來進行精簡,例如:
· 空白空間;
· 未使用的代碼;
· 重復格式化;
· 評論;
· 等等。
需要精簡的三個資源是:
· JS;
· CSS;
· HTML。
每個資源都有一個工具或插件,可以幫助你進行精簡。確保使用它們,并盡快解決此問題。
此外,重定向過程也會對加載速度造成影響。頁面加載時間要是過長,很可能是重定向導致其無法正常運轉的原因。
當頁面重定向到針對某些設備優化過的不同頁面時,就會發生這種情況。
那么,如何解決這個問題?
有一種方法:確保構建適合所有設備的響應式設計。這樣,你就無需重定向,并且能夠提高網頁的加載速度。
【限時免費】如何使用谷歌官方工具,解決營銷路上遇到的道道難關?
(編譯/雨果網 陳杰)
【特別聲明】未經許可同意,任何個人或組織不得復制、轉載、或以其他方式使用本網站內容。轉載請聯系:editor@cifnews.com
上雨果網搜索“跨境資料庫”,領取歐美/東南亞各國市場商機、各大平臺熱銷品報告、跨境電商營銷白皮書!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。