渲染機制
什麼是DOCTYPE? 及作用
HTML5
<!DOCTYPE HTML>
HTML4.01版本 有兩個模式 嚴格模式 傳統模式
嚴格模式(DTD包含所有HTML元素和屬性. 但不包括棄用的元素(eg:font),如果使用,可能解析時會出錯)
傳統模式(DTD包含所有,包括棄用的)
瀏覽器渲染過程
html -> 經過html Parser -> DOM Tree
樣式 -> 經過 css parser -> style rules
Dom Tree + Style rules -> 經過attachment生成 Render Tree
Render Tree 通過 layout 繪製成頁面
重排 Reflow
定義: 瀏覽器在DOM各元素(盒子)的位置發生改變並且重新計算繪製的過程,叫reflow, 它影響它所有的children、ancestors及siblings.
觸發reflow:
- 對Dom節點增刪改的時候, 會觸發reflow或者repaint
- 移動dom的時候(比如動畫)
- 修改樣式的時候
- 改變窗口大小的時候(pc) , 或滾動的時候
- 修改默認字體(影響大)
重繪 Repaint
在改變 DOM 元素的視覺效果時觸發,即不涉及任何排版佈局的問題時觸發。
如果只是改變某個元素的背景色、文 字顏色、邊框顏色等等不影響它周圍或內部佈局的屬性,將只會引起瀏覽器 repaint(重繪)。repaint 的速度明顯快於 reflow
觸發: Dom改動,css改動
如何減少最小程度的repaint: 節點改動,修改的結果儘量集合在一起(取最後的結果), repaint一次
// (不要改動一點,就repaint)
// 類似節流
如何儘可能的避免觸發reflow和repaint,提高性能?
儘可能的減少DOM元素相互影響
-
避免設置內聯樣式
-
儘量簡寫CSS樣式
-
刪除複雜動畫,儘量給動畫元素設置position:fixed/absolute,使動畫元素從DOM流中獨立出來,從而減少對其他元素的影響。同時,儘量犧牲平滑度去滿足性能,因爲動畫精度太強,會造成更多次的repaint/reflow
-
避免使用table進行佈局:
-
table的每個元素的大小以及內容的改動,都會導致整個table進行重新計算,造成大幅度的repaint或者reflow。改用div則可以進行針對性的repaint和避免不必要的reflow
-
避免在CSS中使用運算式:
-
學習CSS的時候就知道,這個應該避免,不應該加深到這一層再去了解,因爲這個的後果確實非常嚴重,一旦存在動畫性的repaint/reflow,那麼每一幀動畫都會進行計算,性能消耗不容小覷。
-
減少DOM的層級,減少DOM的數量,DOM數量越少越好
-
慎改class!!去改子元素少的DOM的class
-
儘量採取批量更新元素樣式的方式,比如可以將需要修改的樣式集合放在一個class裏,將這個class附給元素
佈局 Layout (瀏覽器的佈局)
html -> CSS -> render -> layout -> paint
JS運行機制
如何理解js的單線程
一個時間內只幹一件事
什麼是任務隊列
事件隊列(消息的隊列,所謂任務是WebAPIs返回的一個個通知), 執行棧爲空後會到任務隊列中去取任務,依次執行任務隊列中對應的回調函數, 其中分同步任務, 異步任務, 同步總是在異步之前執行.
異步任務:
- DOM事件
- ajax.(promise)
- setTimeout
Event loop
瀏覽器的事件循環, 主線程運行棧中。只要棧中的代碼(api,同步)執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。 執行棧空了, 再去讀取, 再循環.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>js運行機制</title>
</head>
<body>
<script type="text/javascript">
// console.log(1);
// setTimeout(function () {
// console.log(2);
// }, 0);
// console.log(3);
// console.log(4);
//
// console.log('A');
// setTimeout(function () {
// console.log('B');
// }, 0);
// while (1) {
//
// }
//
for (var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
</script>
</body>
</html>
頁面性能
提升頁面性能的方法有哪些?
- 資源壓縮合並, 減少http請求
- 非核心代碼異步加載 ----> 異步加載的方式 ----> 異步加載的區別
- 利用瀏覽器的緩存 ----> 緩存的分類 ----> 緩存的原理
- 使用CDN
- DNS預解析
DNS預解析
// <meta>信息告訴瀏覽器,當前頁面要做DNS預解析;https瀏覽器是默認不開啓的(a標籤)
<meta http-equiv="x-dns-prefetch-control" content="on" />
// 使用<link>標籤來強制對DNS預解析;
<!--如果不確定是http還是https連接的話建議如下寫法 -->
<link rel="dns-prefetch" href="//renpengpeng.com" />
異步加載的方式
- 動態腳本加載(script)
- async
- defer
異步加載的區別
defer是在html解析完之後才加載, 多個的話, 是按順序的.
async是在會在下載完成後立刻執行, 多個的話, 是亂序的, 那個先回來, 那個先執行.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>性能優化</title>
<!-- <script src="./defer1.js" charset="utf-8" defer></script>
<script src="./defer2.js" charset="utf-8" defer></script> -->
<script src="./async1.js" charset="utf-8" async></script>
<script src="./async2.js" charset="utf-8" async></script>
</head>
<body>
<div class="">
test
<script type="text/javascript">
console.log('write');
document.write('<span>write</span>');
</script>
<script type="text/javascript">
for (var i = 0; i < 200000; i++) {
if (i % 20000 === 0) {
console.log(i);
}
}
</script>
</div>
</body>
</html>
瀏覽器的緩存
緩存的分類
- 強緩存 // 直接讀取瀏覽器存儲在磁盤緩存(本地) 在相對時間內
Expires:Wed, 10 Jul 2019 09:53:41 GMT
Cache-Control:max-age=86400
- 協商緩存 // 詢問服務器先 內容是否有改變
<!-- 下發的時間 -->
Last-Modified:Tue, 16 Feb 2016 04:22:55 GMT
<!--- 再次請求的攜帶的 下發的時間 -->
If-Modified-Since:Tue, 16 Feb 2016 04:22:55 GMT
<!-- 判斷內容是否變化 hash值 (判不同) -->
Etag:"Fqbu34Q4nhvJ91e8LRlTj4yNHK6d.gz"
錯誤監控
問法:
- 如何保證代碼(產品)質量?
- 如何檢測js錯誤
前端錯誤的分類 1. 運行錯誤(代碼錯誤) 2. 資源加載錯誤
- 即時運行錯誤(代碼錯誤)
- 資源加載錯誤 (圖片,js,css)
錯誤的捕獲方式
performance.getEntries() 跟 document.getElementByTagName(’’) 比對. 缺失的資源爲加載失敗.
跨域的js也可以捕獲.
處理:
- 後端處理跨域. 響應頭Access-Control-Allow-Origin: *
- script標籤添加crossorigin屬性
上報錯誤的基本原理
- ajax通信的方式上報
- 利用Image對象上報
<script type="text/javascript">
// 地址 可帶參數
(new Image()).src = 'http://baidu.com/tesjk?r=tksjk';
</script>