摘要:由一道面試題引發(fā)的思考從用戶輸入瀏覽器輸入到頁(yè)面最后呈現(xiàn)有哪些過(guò)程一道很常規(guī)的題目,考的是基本網(wǎng)絡(luò)原理,和瀏覽器加載,過(guò)程。所以抽出時(shí)間研究下瀏覽器渲染頁(yè)面的過(guò)程。
由一道面試題引發(fā)的思考:
從用戶輸入瀏覽器輸入url到頁(yè)面最后呈現(xiàn) 有哪些過(guò)程?
一道很常規(guī)的題目,考的是基本網(wǎng)絡(luò)原理,和瀏覽器加載css,js過(guò)程。
答案大致如下:
用戶輸入U(xiǎn)RL地址
瀏覽器解析URL解析出主機(jī)名
瀏覽器將主機(jī)名轉(zhuǎn)換成服務(wù)器ip地址(瀏覽器先查找本地DNS緩存列表 沒(méi)有的話 再向?yàn)g覽器默認(rèn)的DNS服務(wù)器發(fā)送查詢請(qǐng)求 同時(shí)緩存)
瀏覽器將端口號(hào)從URL中解析出來(lái)
瀏覽器建立一條與目標(biāo)Web服務(wù)器的TCP連接(三次握手)
瀏覽器向服務(wù)器發(fā)送一條HTTP請(qǐng)求報(bào)文
服務(wù)器向?yàn)g覽器返回一條HTTP響應(yīng)報(bào)文
關(guān)閉連接 瀏覽器解析文檔
如果文檔中有資源 重復(fù)6 7 8 動(dòng)作 直至資源全部加載完畢
以上答案基本簡(jiǎn)述了一個(gè)網(wǎng)頁(yè)基本的響應(yīng)過(guò)程背后的原理。
但這也只是一部分,瀏覽器獲取數(shù)據(jù)的部分,至于瀏覽器拿到數(shù)據(jù)之后,怎么渲染頁(yè)面的,一直沒(méi)太關(guān)注。
所以抽出時(shí)間研究下瀏覽器渲染頁(yè)面的過(guò)程。
通過(guò)研究,了解一些基本常識(shí)的原理:
為什么要將js放到頁(yè)腳部分
引入樣式的幾種方式的權(quán)重
css屬性書(shū)寫(xiě)順序建議
何種類型的DOM操作是耗費(fèi)性能的
瀏覽器渲染主要流程不同的瀏覽器內(nèi)核不同,所以渲染過(guò)程不太一樣。
WebKit 主流程
Mozilla 的 Gecko 呈現(xiàn)引擎主流程
由上面兩張圖可以看出,雖然主流瀏覽器渲染過(guò)程叫法有區(qū)別,但是主要流程還是相同的。
Gecko 將視覺(jué)格式化元素組成的樹(shù)稱為“框架樹(shù)”。每個(gè)元素都是一個(gè)框架。WebKit 使用的術(shù)語(yǔ)是“呈現(xiàn)樹(shù)”,它由“呈現(xiàn)對(duì)象”組成。對(duì)于元素的放置,WebKit 使用的術(shù)語(yǔ)是“布局”,而 Gecko 稱之為“重排”。對(duì)于連接 DOM 節(jié)點(diǎn)和可視化信息從而創(chuàng)建呈現(xiàn)樹(shù)的過(guò)程,WebKit 使用的術(shù)語(yǔ)是“附加”。
所以可以分析出基本過(guò)程:
HTML解析出DOM Tree
CSS解析出Style Rules
將二者關(guān)聯(lián)生成Render Tree
Layout 根據(jù)Render Tree計(jì)算每個(gè)節(jié)點(diǎn)的信息
Painting 根據(jù)計(jì)算好的信息繪制整個(gè)頁(yè)面
HTML解析HTML Parser的任務(wù)是將HTML標(biāo)記解析成DOM Tree
這個(gè)解析可以參考React解析DOM的過(guò)程,
但是這里面有很多別的規(guī)則和操作,比如容錯(cuò)機(jī)制,識(shí)別和
等等。
感興趣的可以參考 《How Browser Work》,中文翻譯
舉個(gè)例子:一段HTML
Web page parsing Web page parsing
This is an example Web page.
經(jīng)過(guò)解析之后的DOM Tree差不多就是
將文本的HTML文檔,提煉出關(guān)鍵信息,嵌套層級(jí)的樹(shù)形結(jié)構(gòu),便于計(jì)算拓展。這就是HTML Parser的作用。
CSS解析CSS Parser將CSS解析成Style Rules,Style Rules也叫CSSOM(CSS Object Model)。
StyleRules也是一個(gè)樹(shù)形結(jié)構(gòu),根據(jù)CSS文件整理出來(lái)的類似DOM Tree的樹(shù)形結(jié)構(gòu):
于HTML Parser相似,CSS Parser作用就是將很多個(gè)CSS文件中的樣式合并解析出具有樹(shù)形結(jié)構(gòu)Style Rules。
腳本處理瀏覽器解析文檔,當(dāng)遇到
樣式計(jì)算樣式計(jì)算是個(gè)很復(fù)雜的問(wèn)題。DOM中的一個(gè)元素可以對(duì)應(yīng)樣式表中的多個(gè)元素。樣式表包括了所有樣式:瀏覽器默認(rèn)樣式表,自定義樣式表,inline樣式元素,HTML可視化屬性如:width=100。后者將轉(zhuǎn)化以匹配CSS樣式。
WebKit 節(jié)點(diǎn)會(huì)引用樣式對(duì)象 (RenderStyle)。這些對(duì)象在某些情況下可以由不同節(jié)點(diǎn)共享。這些節(jié)點(diǎn)是同級(jí)關(guān)系,并且:
這些元素必須處于相同的鼠標(biāo)狀態(tài)(例如,不允許其中一個(gè)是“:hover”狀態(tài),而另一個(gè)不是)
任何元素都沒(méi)有 ID
標(biāo)記名稱應(yīng)匹配
類屬性應(yīng)匹配
映射屬性的集合必須是完全相同的
鏈接狀態(tài)必須匹配
焦點(diǎn)狀態(tài)必須匹配
任何元素都不應(yīng)受屬性選擇器的影響,這里所說(shuō)的“影響”是指在選擇器中的任何位置有任何使用了屬性選擇器的選擇器匹配
元素中不能有任何 inline 樣式屬性
不能使用任何同級(jí)選擇器。WebCore 在遇到任何同級(jí)選擇器時(shí),只會(huì)引發(fā)一個(gè)全局開(kāi)關(guān),并停用整個(gè)文檔的樣式共享(如果存在)。這包括 + 選擇器以及 :first-child 和 :last-child 等選擇器。
為了簡(jiǎn)化樣式計(jì)算,F(xiàn)irefox 還采用了另外兩種樹(shù):規(guī)則樹(shù)和樣式上下文樹(shù)。WebKit 也有樣式對(duì)象,但它們不是保存在類似樣式上下文樹(shù)這樣的樹(shù)結(jié)構(gòu)中,只是由 DOM 節(jié)點(diǎn)指向此類對(duì)象的相關(guān)樣式。
樣式上下文包含端值。要計(jì)算出這些值,應(yīng)按照正確順序應(yīng)用所有的匹配規(guī)則,并將其從邏輯值轉(zhuǎn)化為具體的值。
例如,如果邏輯值是屏幕大小的百分比,則需要換算成絕對(duì)的單位。規(guī)則樹(shù)的點(diǎn)子真的很巧妙,它使得節(jié)點(diǎn)之間可以共享這些值,以避免重復(fù)計(jì)算,還可以節(jié)約空間。
所有匹配的規(guī)則都存儲(chǔ)在樹(shù)中。路徑中的底層節(jié)點(diǎn)擁有較高的優(yōu)先級(jí)。規(guī)則樹(shù)包含了所有已知規(guī)則匹配的路徑。規(guī)則的存儲(chǔ)是延遲進(jìn)行的。規(guī)則樹(shù)不會(huì)在開(kāi)始的時(shí)候就為所有的節(jié)點(diǎn)進(jìn)行計(jì)算,而是只有當(dāng)某個(gè)節(jié)點(diǎn)樣式需要進(jìn)行計(jì)算時(shí),才會(huì)向規(guī)則樹(shù)添加計(jì)算的路徑。
舉個(gè)例子 我們有段HTML代碼:
this is a big error this is also a very big error error
another error
對(duì)應(yīng)CSS規(guī)則如下:
1. .div {margin:5px;color:black} 2. .err {color:red} 3. .big {margin-top:3px} 4. div span {margin-bottom:4px} 5. #div1 {color:blue} 6. #div2 {color:green}
則CSS形成的規(guī)則樹(shù)如下圖所示(節(jié)點(diǎn)的標(biāo)記方式為“節(jié)點(diǎn)名 : 指向的規(guī)則序號(hào)”)
假設(shè)我們解析 HTML 時(shí)遇到了第二個(gè)
現(xiàn)在我們需要填充樣式結(jié)構(gòu)。首先要填充的是 margin 結(jié)構(gòu)。由于最后的規(guī)則節(jié)點(diǎn) (F) 并沒(méi)有添加到 margin 結(jié)構(gòu),我們需要上溯規(guī)則樹(shù),直至找到在先前節(jié)點(diǎn)插入中計(jì)算過(guò)的緩存結(jié)構(gòu),然后使用該結(jié)構(gòu)。我們會(huì)在指定 margin 規(guī)則的最上層節(jié)點(diǎn)(即 B 節(jié)點(diǎn))上找到該結(jié)構(gòu)。
我們已經(jīng)有了 color 結(jié)構(gòu)的定義,因此不能使用緩存的結(jié)構(gòu)。由于 color 有一個(gè)屬性,我們無(wú)需上溯規(guī)則樹(shù)以填充其他屬性。我們將計(jì)算端值(將字符串轉(zhuǎn)化為 RGB 等)并在此節(jié)點(diǎn)上緩存經(jīng)過(guò)計(jì)算的結(jié)構(gòu)。
第二個(gè) 元素處理起來(lái)更加簡(jiǎn)單。我們將匹配規(guī)則,最終發(fā)現(xiàn)它和之前的 span 一樣指向規(guī)則 G。由于我們找到了指向同一節(jié)點(diǎn)的同級(jí),就可以共享整個(gè)樣式上下文了,只需指向之前 span 的上下文即可。
對(duì)于包含了繼承自父代的規(guī)則的結(jié)構(gòu),緩存是在上下文樹(shù)中進(jìn)行的(事實(shí)上 color 屬性是繼承的,但是 Firefox 將其視為 reset 屬性,并緩存到規(guī)則樹(shù)上)
所以生成的上下文樹(shù)如下:
樣式對(duì)象具有與每個(gè)可視化屬性一一對(duì)應(yīng)的屬性(均為 CSS 屬性但更為通用)。如果某個(gè)屬性未由任何匹配規(guī)則所定義,那么部分屬性就可由父代元素樣式對(duì)象繼承。其他屬性具有默認(rèn)值。
如果定義不止一個(gè),就會(huì)出現(xiàn)問(wèn)題,需要通過(guò)層疊順序來(lái)解決。
一些例子:
* {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */ li {} /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */ li:first-line {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul li {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul ol+li {} /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */ h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */ ul ol li.red {} /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */ li.red.level {} /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */ #x34y {} /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */ style="" /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */
利用上面的方法,基本可以快速確定不同選擇器的優(yōu)先級(jí)。
布局Layout創(chuàng)建渲染樹(shù)后,下一步就是布局(Layout),或者叫回流(reflow,relayout),這個(gè)過(guò)程就是通過(guò)渲染樹(shù)中渲染對(duì)象的信息,計(jì)算出每一個(gè)渲染對(duì)象的位置和尺寸,將其安置在瀏覽器窗口的正確位置,而有些時(shí)候我們會(huì)在文檔布局完成后對(duì)DOM進(jìn)行修改,這時(shí)候可能需要重新進(jìn)行布局,也可稱其為回流,本質(zhì)上還是一個(gè)布局的過(guò)程,每一個(gè)渲染對(duì)象都有一個(gè)布局或者回流方法,實(shí)現(xiàn)其布局或回流。
對(duì)渲染樹(shù)的布局可以分為全局和局部的,全局即對(duì)整個(gè)渲染樹(shù)進(jìn)行重新布局,如當(dāng)我們改變了窗口尺寸或方向或者是修改了根元素的尺寸或者字體大小等;而局部布局可以是對(duì)渲染樹(shù)的某部分或某一個(gè)渲染對(duì)象進(jìn)行重新布局。
大多數(shù)web應(yīng)用對(duì)DOM的操作都是比較頻繁,這意味著經(jīng)常需要對(duì)DOM進(jìn)行布局和回流,而如果僅僅是一些小改變,就觸發(fā)整個(gè)渲染樹(shù)的回流,這顯然是不好的,為了避免這種情況,瀏覽器使用了臟位系統(tǒng),只有一個(gè)渲染對(duì)象改變了或者某渲染對(duì)象及其子渲染對(duì)象臟位值為”dirty”時(shí),說(shuō)明需要回流。
表示需要布局的臟位值有兩種:
“dirty”–自身改變,需要回流
“children are dirty”–子節(jié)點(diǎn)改變,需要回流
布局是一個(gè)從上到下,從外到內(nèi)進(jìn)行的遞歸過(guò)程,從根渲染對(duì)象,即對(duì)應(yīng)著HTML文檔根元素,然后下一級(jí)渲染對(duì)象,如對(duì)應(yīng)著元素,如此層層遞歸,依次計(jì)算每一個(gè)渲染對(duì)象的幾何信息(位置和尺寸)。
每一個(gè)渲染對(duì)象的布局流程基本如:
1.計(jì)算此渲染對(duì)象的寬度(width);
2.遍歷此渲染對(duì)象的所有子級(jí),依次:
2.1設(shè)置子級(jí)渲染對(duì)象的坐標(biāo)
2.2判斷是否需要觸發(fā)子渲染對(duì)象的布局或回流方法,計(jì)算子渲染對(duì)象的高度(height)
3.設(shè)置此渲染對(duì)象的高度:根據(jù)子渲染對(duì)象的累積高,margin和padding的高度設(shè)置其高度;
4.設(shè)置此渲染對(duì)象臟位值為false。
繪制(Painting)在繪制階段,系統(tǒng)會(huì)遍歷呈現(xiàn)樹(shù),并調(diào)用呈現(xiàn)器的“paint”方法,將呈現(xiàn)器的內(nèi)容顯示在屏幕上。繪制工作是使用用戶界面基礎(chǔ)組件完成的。
CSS2 規(guī)范定義了繪制流程的順序。繪制的順序其實(shí)就是元素進(jìn)入堆棧樣式上下文的順序。這些堆棧會(huì)從后往前繪制,因此這樣的順序會(huì)影響繪制。塊呈現(xiàn)器的堆棧順序如下:
背景顏色
背景圖片
邊框
子代
輪廓
這里還要說(shuō)兩個(gè)概念,一個(gè)是Reflow,另一個(gè)是Repaint。這兩個(gè)不是一回事。
Repaint ——屏幕的一部分要重畫(huà),比如某個(gè)CSS的背景色變了。但是元素的幾何尺寸沒(méi)有變。
Reflow 元件的幾何尺寸變了,我們需要重新驗(yàn)證并計(jì)算Render Tree。是Render Tree的一部分或全部發(fā)生了變化。這就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的幾何尺寸發(fā)生了變化,需要重新布局,也就叫reflow)reflow 會(huì)從這個(gè)root frame開(kāi)始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置,在reflow過(guò)程中,可能會(huì)增加一些frame,比如一個(gè)文本字符串必需被包裝起來(lái)。
Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每個(gè)結(jié)點(diǎn)都會(huì)有reflow方法,一個(gè)結(jié)點(diǎn)的reflow很有可能導(dǎo)致子結(jié)點(diǎn),甚至父點(diǎn)以及同級(jí)結(jié)點(diǎn)的reflow。在一些高性能的電腦上也許還沒(méi)什么,但是如果reflow發(fā)生在手機(jī)上,那么這個(gè)過(guò)程是非常痛苦和耗電的。 所以,下面這些動(dòng)作有很大可能會(huì)是成本比較高的。
當(dāng)你增加、刪除、修改DOM結(jié)點(diǎn)時(shí),會(huì)導(dǎo)致Reflow或Repaint
當(dāng)你移動(dòng)DOM的位置,或是搞個(gè)動(dòng)畫(huà)的時(shí)候。
當(dāng)你修改CSS樣式的時(shí)候。
當(dāng)你Resize窗口的時(shí)候(移動(dòng)端沒(méi)有這個(gè)問(wèn)題),或是滾動(dòng)的時(shí)候。
當(dāng)你修改網(wǎng)頁(yè)的默認(rèn)字體時(shí)。
注:display:none會(huì)觸發(fā)reflow,而visibility:hidden只會(huì)觸發(fā)repaint,因?yàn)闆](méi)有發(fā)現(xiàn)位置變化。
基本上來(lái)說(shuō),reflow有如下的幾個(gè)原因:
Initial。網(wǎng)頁(yè)初始化的時(shí)候。
Incremental。一些Javascript在操作DOM Tree時(shí)。
Resize。其些元件的尺寸變了。
StyleChange。如果CSS的屬性發(fā)生變化了。
Dirty。幾個(gè)Incremental的reflow發(fā)生在同一個(gè)frame的子樹(shù)上。
看幾個(gè)例子:
$("body").css("color", "red"); // repaint $("body").css("margin", "2px"); // reflow, repaint var bstyle = document.body.style; // cache bstyle.padding = "20px"; // reflow, repaint bstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint bstyle.color = "blue"; // repaint bstyle.backgroundColor = "#fad"; // repaint bstyle.fontSize = "2em"; // reflow, repaint // new DOM element - reflow, repaint document.body.appendChild(document.createTextNode("dude!"));
當(dāng)然,我們的瀏覽器是聰明的,它不會(huì)像上面那樣,你每改一次樣式,它就reflow或repaint一次。一般來(lái)說(shuō),瀏覽器會(huì)把這樣的操作積攢一批,然后做一次reflow,這又叫異步reflow或增量異步reflow。但是有些情況瀏覽器是不會(huì)這么做的,比如:resize窗口,改變了頁(yè)面默認(rèn)的字體,等。對(duì)于這些操作,瀏覽器會(huì)馬上進(jìn)行reflow。
但是有些時(shí)候,我們的腳本會(huì)阻止瀏覽器這么干,比如:如果我們請(qǐng)求下面的一些DOM值:
offsetTop, offsetLeft, offsetWidth, offsetHeight scrollTop/Left/Width/Height clientTop/Left/Width/Height IE中的 getComputedStyle(), 或 currentStyle
因?yàn)?,如果我們的程序需要這些值,那么瀏覽器需要返回最新的值,而這樣一樣會(huì)flush出去一些樣式的改變,從而造成頻繁的reflow/repaint。
Chrome調(diào)試工具查看頁(yè)面渲染順序頁(yè)面的渲染詳細(xì)過(guò)程可以通過(guò)chrome開(kāi)發(fā)者工具中的timeline查看
發(fā)起請(qǐng)求;
解析HTML;
解析樣式;
執(zhí)行JavaScript;
布局;
繪制
頁(yè)面渲染優(yōu)化瀏覽器對(duì)上文介紹的關(guān)鍵渲染路徑進(jìn)行了很多優(yōu)化,針對(duì)每一次變化產(chǎn)生盡量少的操作,還有優(yōu)化判斷重新繪制或布局的方式等等。
在改變文檔根元素的字體顏色等視覺(jué)性信息時(shí),會(huì)觸發(fā)整個(gè)文檔的重繪,而改變某元素的字體顏色則只觸發(fā)特定元素的重繪;改變?cè)氐奈恢眯畔?huì)同時(shí)觸發(fā)此元素(可能還包括其兄弟元素或子級(jí)元素)的布局和重繪。某些重大改變,如更改文檔根元素的字體尺寸,則會(huì)觸發(fā)整個(gè)文檔的重新布局和重繪,據(jù)此及上文所述,推薦以下優(yōu)化和實(shí)踐:
HTML文檔結(jié)構(gòu)層次盡量少,最好不深于六層;
腳本盡量后放,放在前即可;
少量首屏樣式內(nèi)聯(lián)放在標(biāo)簽內(nèi);
樣式結(jié)構(gòu)層次盡量簡(jiǎn)單;
在腳本中盡量減少DOM操作,盡量緩存訪問(wèn)DOM的樣式信息,避免過(guò)度觸發(fā)回流;
減少通過(guò)JavaScript代碼修改元素樣式,盡量使用修改class名方式操作樣式或動(dòng)畫(huà);
動(dòng)畫(huà)盡量使用在絕對(duì)定位或固定定位的元素上;
隱藏在屏幕外,或在頁(yè)面滾動(dòng)時(shí),盡量停止動(dòng)畫(huà);
盡量緩存DOM查找,查找器盡量簡(jiǎn)潔;
涉及多域名的網(wǎng)站,可以開(kāi)啟域名預(yù)解析
總結(jié)瀏覽器渲染是個(gè)很繁瑣的過(guò)程,其中每一步都有對(duì)應(yīng)的算法。
了解渲染過(guò)程原理可以有針對(duì)的性能優(yōu)化,而且也可以懂得一些基本的要求和規(guī)范的原理。
最后文章中間很多語(yǔ)句都是直接復(fù)制的原文,自己的語(yǔ)言概況還是不及原文精彩。
《How Browser Work》
瀏覽器的工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘
瀏覽器渲染原理
淺析前端頁(yè)面渲染機(jī)制
瀏覽器 渲染,繪制流程及性能優(yōu)化
優(yōu)化CSS重排重繪與瀏覽器性能
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/112271.html
摘要:性能優(yōu)化網(wǎng)站的性能細(xì)線在幾個(gè)方面網(wǎng)站首頁(yè)加載速度動(dòng)畫(huà)的流暢度通過(guò)分析瀏覽器的渲染原理資源對(duì)渲染的影響,得出優(yōu)化網(wǎng)站性能的辦法。查看性能的工具的面板錄制網(wǎng)頁(yè)加載的過(guò)程,分析記錄瀏覽器渲染過(guò)程中每個(gè)過(guò)程的耗時(shí)。通過(guò)引入,可以避免阻塞。 1 Web性能優(yōu)化 Web網(wǎng)站的性能細(xì)線在幾個(gè)方面: 網(wǎng)站首頁(yè)加載速度 動(dòng)畫(huà)的流暢度 通過(guò)分析瀏覽器的渲染原理、資源對(duì)渲染的影響,得出優(yōu)化網(wǎng)站性能的辦法...
摘要:端優(yōu)談?wù)勱P(guān)于前端的緩存的問(wèn)題我們都知道對(duì)頁(yè)面進(jìn)行緩存能夠有利于減少請(qǐng)求發(fā)送,從而達(dá)到對(duì)頁(yè)面的優(yōu)化。而作為一名有追求的前端,勢(shì)必要力所能及地優(yōu)化我們前端頁(yè)面的性能。這種方式主要解決了淺談前端中的過(guò)早優(yōu)化問(wèn)題過(guò)早優(yōu)化是萬(wàn)惡之源。 優(yōu)化向:?jiǎn)雾?yè)應(yīng)用多路由預(yù)渲染指南 Ajax 技術(shù)的出現(xiàn),讓我們的 Web 應(yīng)用能夠在不刷新的狀態(tài)下顯示不同頁(yè)面的內(nèi)容,這就是單頁(yè)應(yīng)用。在一個(gè)單頁(yè)應(yīng)用中,往往只有一...
摘要:不推薦移動(dòng)端瀏覽器前端優(yōu)化策略相對(duì)于桌面端瀏覽器,移動(dòng)端瀏覽器上有一些較為明顯的特點(diǎn)設(shè)備屏幕較小新特性兼容性較好支持一些較新的和特性需要與應(yīng)用交互等。 GitHub鏈接:https://github.com/zwwill/blo... 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動(dòng)端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展開(kāi),遇到不會(huì)不懂的點(diǎn)還請(qǐng)站外擴(kuò)展 開(kāi)車...
摘要:不推薦移動(dòng)端瀏覽器前端優(yōu)化策略相對(duì)于桌面端瀏覽器,移動(dòng)端瀏覽器上有一些較為明顯的特點(diǎn)設(shè)備屏幕較小新特性兼容性較好支持一些較新的和特性需要與應(yīng)用交互等。 GitHub鏈接:https://github.com/zwwill/blo... 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動(dòng)端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展開(kāi),遇到不會(huì)不懂的點(diǎn)還請(qǐng)站外擴(kuò)展 開(kāi)車...
摘要:不推薦移動(dòng)端瀏覽器前端優(yōu)化策略相對(duì)于桌面端瀏覽器,移動(dòng)端瀏覽器上有一些較為明顯的特點(diǎn)設(shè)備屏幕較小新特性兼容性較好支持一些較新的和特性需要與應(yīng)用交互等。 GitHub鏈接:https://github.com/zwwill/blo... 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動(dòng)端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展開(kāi),遇到不會(huì)不懂的點(diǎn)還請(qǐng)站外擴(kuò)展 開(kāi)車...
閱讀 3789·2021-10-14 09:43
閱讀 3383·2021-08-25 09:38
閱讀 676·2019-08-30 15:55
閱讀 1469·2019-08-30 13:05
閱讀 2300·2019-08-29 16:05
閱讀 572·2019-08-29 12:58
閱讀 2869·2019-08-29 12:34
閱讀 3300·2019-08-26 12:15