# 各種瀏覽器問題效能 集中區 目前包含: 像素通道/ Reflow&Repaint/ <link>/<script> ## Explain the difference between layout, painting and compositing ![](https://i.imgur.com/SC61B3F.jpg) ### 1. Style 解析選擇器,從匹配選擇器中獲取樣式變化,並計算出最終樣式 **Notice** * 降低選擇器的複雜性 * 減少必須計算其樣式的元素數量 ### 2. Layout 瀏覽器開始計算元素要占用多少空間以及在螢幕上的位置 **Notice** * 盡量避免布局操作 ### 3. Paint 牽涉到描繪出文字,顏色、影像、邊框、陰影基本上是元素每個視覺化的部分 **Notice** * 除transform或opacity屬性之外,更改任何屬性始終都會觸發paint * paint通常是像素管道中開銷最大的部分 * 通過z-index的提升和動畫的編排來減少繪製區域 ### 4. Composite 網頁可能會被描繪成多個層,因此需要按正確的順序描繪至螢幕 **Notice** * z-index層數過多會占用更多的內存,需合理分配 * 使用transform和opacity屬性更改來實現動畫,這並不觸發重排和重繪 ## Reflow & Repaint ### Reflow 計算Render Tree上各元素的物理屬性,位置、大小、是否看的見、是否被其他元素遮擋住,需要大量的運算資源,也因為是要計算出這些屬性,只要是有可能牽扯到這些屬性的操作都會觸發Reflow e.x. 1. 設定CSS屬性 * 大小: width、height * 浮動: float * 定位: position 2. 使用者互動 * 調整瀏覽器視窗大小 * 輸入框的內容變更 3. JavaScript * DOM操作 * 動態載入CSS樣式表 * 取得元素的大小 ### Repaint Repaint是相對單純的,把Reflow計算的結果轉換成螢幕上的實際像素顯示,這部分是難以避免的開銷 ## <link>標籤在<head>中 如果link標籤放在</body>之前的話,如果用戶網路速度較慢可能會造成看到沒有樣式的HTML結構,看到沒樣式的HTML結構也代表已經做了一次渲染,需要再做一次帶有樣式的渲染,會造成效能的多於消耗。 所以如果<link>在<head>中會先載css之後建構CSSOMTree同時建構DOMTree, 建構完畢後開始建構RenderTree, 計算布局渲染 ## <script>標籤在</body>之前 瀏覽器在解析HTML 是一行一行向下在讀取的, 當瀏覽器讀到<script>標籤時會暫停解析HTML, 且立刻執行<script>所以當<script>放在<head>中有可能造成DOM tree 建構不完全時就執行JavaScript或使用<script>標籤的屬性 * defer 當瀏覽器遇到帶有defer屬性的<script>標籤時,會再 開一個執行緒去下載JavaScript,當HTML執行完畢DOM載入完 成時,才執行JS * async 與defer功能類似但會再下載完成JS後立刻執行,但不像 defer那樣保證按照順序執行, 哪個JS檔先載完先執行 **參考文章** [Reflow&Repaint](https://medium.com/schaoss-blog/%E5%89%8D%E7%AB%AF%E4%B8%89%E5%8D%81-03-css-reflow-%E5%8F%8A-repaint-%E6%98%AF%E4%BB%80%E9%BA%BC-36293ebcffe7) [How Rendering Works](https://ithelp.ithome.com.tw/articles/10248720) [性能優化之關於像素管道](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/735242/#outline__3_2) [轉譯效能](https://developers.google.com/web/fundamentals/performance/rendering?hl=zh-tw) [css為什麼要放在head標籤中](https://segmentfault.com/a/1190000023325101)