瀏覽器渲染機(jī)制,css文檔和js文檔在渲染時(shí)的動(dòng)態(tài)展示

前幾天剛剛學(xué)完css,這兩天開始進(jìn)軍js部分,看了一些老師們的操作視頻,有理論的,有展示的現(xiàn)象得到的一些結(jié)論的東西,第一遍看起來,其實(shí)很沒有感的,因?yàn)闈M腦子都在引入概念,跟著老師走,自己其實(shí)在被動(dòng)接受,也不敢自己跟著操作,怕跟不上節(jié)奏了,都怪自己是計(jì)算機(jī)界的一種小白了。所以心里發(fā)誓,有必要把c和Java好好下來研究研究了。廢話不多說,我第二遍看視頻,一遍看,一遍看代碼,思考,才有了感的。

瀏覽器的渲染機(jī)制

其實(shí)這個(gè)就是理論上的東西,最具有邏輯性了,所有很容易明白,理解,就算是拿來主義,也不可恥,因?yàn)楸緛砭褪侨绱?,除非是作為一個(gè)瀏覽器開發(fā)者才會(huì)以此為恥的吧。
記得學(xué)HTML時(shí),也有一個(gè)機(jī)制攻略的,那個(gè)就是從URL輸入到瀏覽器展示頁面的一個(gè)總體的思路過程了,資料可回顧參考《初學(xué)從url到展示網(wǎng)頁的感官》,這個(gè)過程里的其中一部分就是現(xiàn)在要講的瀏覽器渲染機(jī)制了。當(dāng)時(shí)只是總攬全局,并且在邏輯上明白了一個(gè)思路,現(xiàn)在學(xué)到這里,我們需要細(xì)細(xì)拿出這 其中一部分,好好地品味下內(nèi)在的想法如何實(shí)現(xiàn)的。
具體思路:瀏覽器發(fā)出請(qǐng)求,服務(wù)器收到后,回復(fù)給html文件,瀏覽器接收并解析:解析到css文件,發(fā)請(qǐng)求要css文件;解析到j(luò)s文件,發(fā)請(qǐng)求要js文件。
html文件在第一時(shí)間解析完成,在瀏覽器的邏輯下,生成DOM樹。
同時(shí),接收到css文件后,解析,生成cssOM樹,也就是樣式樹。
然后兩棵樹互相聯(lián)系作用,一個(gè)是角色,一個(gè)是角色的各種屬性,搭配起來,形成了一顆渲染樹,這棵樹也是存在于瀏覽器機(jī)制的邏輯里的,只是為了讓人更明白,所有,我覺得把這個(gè)理念概念化語義化了哦。
然后瀏覽器通過渲染樹,對(duì)各個(gè)節(jié)點(diǎn)標(biāo)簽進(jìn)行布局計(jì)算,計(jì)算完了,就開始畫畫,畫好了就顯示成頁面了。
流程圖如下:


其實(shí)在這里,我就感到奇怪了,比如js文件呢?還有實(shí)際操作的話,這個(gè)理論的應(yīng)用層面在瀏覽器上會(huì)有什么樣的現(xiàn)象和問題?這就是我下面想要說的,不過我才疏學(xué)淺,時(shí)間很緊,只能把一些現(xiàn)象說出來,具體的一些結(jié)論,我能查出根據(jù)的會(huì)覺得會(huì)好,模凌兩可的只能作為自己的猜想了。說真的,瀏覽器其實(shí)原理一樣,但是耐不住開發(fā)人員的牛脾氣,所以,原理僅僅是在開發(fā)人員眼里的一條讓普通人更容易明白的小路而已,實(shí)際上,各種開發(fā)權(quán)限讓瀏覽器很搞怪,有時(shí)候讓你覺得,跟所學(xué)的知識(shí)相悖,根本沒有什么大一統(tǒng)的結(jié)論啊,比如,說js文件一加載就立刻執(zhí)行,然后出來了一個(gè)異步加載;谷歌瀏覽器是白屏的效果,可為啥火狐的是閃爍了?反正,明白一句話,實(shí)踐出真知,越認(rèn)識(shí)到錯(cuò)誤,越接近真實(shí),好比小學(xué)里0是最小的,那是對(duì)的,到初中你再說就錯(cuò)了。

css文檔流的分析

首先css文件,這個(gè)研究對(duì)象,起初啊,第一次跟著老師走的時(shí)候,是蒙的,沒有思路,只是跟著他走,模仿他的思路,分析方法,現(xiàn)象驗(yàn)證,總結(jié),這一套路吧,那時(shí)候憋屈啊,自己討厭自己沒思路,聽得云里霧里的,只是記錄了一些所謂的結(jié)論和感官,以及對(duì)研究對(duì)象的一種很深很厭惡的感官了。第二遍看視頻,對(duì)照著代碼,才能有自己的思路,而且有點(diǎn)成就感的是,對(duì)老師最后的幾個(gè)現(xiàn)象反而得不出大一統(tǒng)的結(jié)論想到了一些東西,心里還是比較滿足的。
我按我的猜想走吧。
這個(gè)研究對(duì)象啊,在html中css的位置有兩個(gè),一個(gè)在head中,一個(gè)在body里。在這里,我先對(duì)css的添加樣式做個(gè)說明,不管是外部鏈接還是內(nèi)部的,還是幾乎廢棄的在html標(biāo)簽里寫的,首先直接說最優(yōu)的就是內(nèi)部的,不用在發(fā)請(qǐng)求像外部的要文件了,加載快,省事。拋去這個(gè)因素,再從位置入手。
先說一下,大一統(tǒng)的結(jié)論,從老師的代碼實(shí)驗(yàn)中得到了,一個(gè)HTML文件,幾乎所有的css文件都是同時(shí)開始加載的,不論位置。當(dāng)然,除去幾乎要費(fèi)了的那種在html標(biāo)簽里寫的css,不是說它不適合或適合,只是說它沒法證明。
在head里的css,最明了,簡單。這里的css文件是全部加載完成后才開始執(zhí)行,而且伴隨著執(zhí)行,html的內(nèi)容開始出現(xiàn),符合渲染樹的步驟。
其實(shí),我比較喜歡放這里,覺得很區(qū)塊化,而且,確實(shí)效果上很好的。
在body里的css文件,加載時(shí)遵循順序,而無論上下方是何種html標(biāo)簽,都會(huì)在它們之后執(zhí)行,谷歌嘛。但是關(guān)于圖片的加載時(shí)機(jī)的影響,這是我看到代碼實(shí)驗(yàn)的一種猜想,僅僅限于谷歌瀏覽器上,尤其是當(dāng)css上面或者下面有圖片或其他加載數(shù)據(jù)大時(shí),影響會(huì)很明顯,圖片會(huì)顯得不受css文件影響一樣,該加載就加載。這里有一個(gè)因素是js文檔在head部時(shí)產(chǎn)生的阻礙作用,圖片會(huì)在所有css文件執(zhí)行后加載,而把阻礙的js移到body底部時(shí),圖片就好像不受css文件影響一樣,該加載就加載,也不等css文件了。

反正,對(duì)于研究加載的話,顯得很蒼白,特立獨(dú)行的是js文件,最具主動(dòng)性,它只會(huì)影響HTML和css,而自身不受它們影響。css加載幾乎是同時(shí)加載的,它影響html的一些元素如圖片的加載時(shí)機(jī)的。執(zhí)行的話,就比較簡單了,js文件加載后立即執(zhí)行,css文件一個(gè)一個(gè)地執(zhí)行,這里非要針對(duì)影響的話,我又查了下資料,貌似跟請(qǐng)求有關(guān)——
css文件的下載和渲染是同步的嗎? 還是先下載完, 再渲染?

不確定下載過程中是否同步做詞法分析parseCss,但是可能性很大,畢竟是種無損失的優(yōu)化方案,但是最終肯定需要下載完再layout生成渲染樹,進(jìn)而渲染。

css文件的下載&執(zhí)行 和 html文件的下載&執(zhí)行同步嗎?

并行的。但是需要注意一些限制,比如一個(gè)域名下最大并發(fā)6個(gè)請(qǐng)求,再多就得串行。

圖形的加載 和 html文件的下載/執(zhí)行同步嗎, 音視頻呢, 別的資源呢?
同上。

有沒有可能出現(xiàn)html文件/圖片/css文件/js文件同時(shí)下載的情況?

常態(tài)。

有沒有可能出現(xiàn)html/css文件/js文件同時(shí)執(zhí)行的情況?
html parse和css parse是并行的,兩者完成后才會(huì)layout、paint,新的css掛載會(huì)延遲layout、paint。js parse會(huì)阻塞html parse ,所以后面的layout、paint一定不會(huì)同時(shí)執(zhí)行。

作者:錢多多
鏈接:https://www.zhihu.com/question/59024365/answer/161615976
來源:知乎


然后,再說說無樣式加載,白屏,閃爍現(xiàn)象——這是瀏覽器加載與顯示頁面方式不同造成的。
谷歌呢是當(dāng)發(fā)現(xiàn)<link rel ="stylesheet"> 后立即停止渲染,在所有css加載完成之前頁面上不會(huì)有任何內(nèi)容,所有白屏了?;鸷赜幸馑剂耍?<head>標(biāo)簽中的<link rel ="stylesheet">與Chrome和Safari中完全一致,這些link標(biāo)簽全部加載完之前,頁面上不顯示任何內(nèi)容,而<body>中的內(nèi)容則不阻塞任何內(nèi)容顯示,也就是說,放<body>內(nèi),先渲染沒有樣式的,再渲染有樣式的。

repaint和reflow

  • 簡介
    repaint主要是針對(duì)某一個(gè)DOM元素進(jìn)行的重繪,reflow則是回流,針對(duì)整個(gè)頁面的重排。字面意思來說:repaint就是重繪,reflow就是回流。repaint和reflow的目的是:展示一個(gè)新的頁面樣貌。
  • 觸發(fā)
    reflow是只要涉及到頁面排版和布局變動(dòng)的,元素本身布局變動(dòng),style變化,就會(huì)觸發(fā),而且功耗很大。repaint是除了上述情況之外,還有就是標(biāo)簽本身的屬性渲染發(fā)生變化,顯示效果不一樣時(shí),也會(huì)觸發(fā),比如顏色變化,不過功耗小得多。
  • 避免功耗問題
    能不改就不改,盡量避免reflow,這就是想法了。
    比如說經(jīng)常有些刷新的對(duì)象啊標(biāo)簽啊,比如動(dòng)畫效果,對(duì)象一變化,整個(gè)頁面就相當(dāng)于刷新了,所以,變動(dòng)影響最小的就是把對(duì)象搞成絕對(duì)定位,或其他,反正脫離文檔流就行,并且如動(dòng)畫一類的可控變化,讓變化頻率變小。
    多用class選擇器,減少計(jì)算的量,精簡css的邏輯量,然后從這個(gè)角度入手,就是想辦法把css樹結(jié)構(gòu)變得小巧,所以DOM元素能不用css的就不用,所以減少外部鏈接引入css文件。

說了這么多,都是跟css有關(guān)的,心里有點(diǎn)意思的,莫名其妙哦,這可是在學(xué)js啊!只能說明,學(xué)css時(shí),自己太蠢,僅僅當(dāng)成了靜態(tài)頁面,給它們化妝打扮了,自以為可以為所欲為,可是站在更廣闊的大局觀,看到的風(fēng)景卻是很不一樣的。這里的css里的東西,我其實(shí)偷懶了,時(shí)間關(guān)系,根本沒有自己把實(shí)例一一展示,我僅僅是通過視頻里的代碼展示推出了一些猜想,并自覺地認(rèn)為,這僅僅是一個(gè)谷歌瀏覽器啊,那IE,火狐等等其他的呢?難道都要一一驗(yàn)證?我暫時(shí)沒有時(shí)間了,只能說這個(gè)是未完結(jié)版,待續(xù),,,

js文件的分析

終于到了新鮮貨了哦。不過js文件其實(shí)算是比較有原則的吧,畢竟它是為了實(shí)現(xiàn)功能和效果的,相比前兩者來說,卻是有些特立獨(dú)行。相比于如今的寬帶,研究白屏或者內(nèi)容閃爍,比較無聊在于,幾乎沒有這種顯示體驗(yàn)了,研究的意義在于,哦,讓我明白瀏覽器的渲染邏輯的更清晰化更具有邏輯,出來了一種現(xiàn)象,哦,我可以解釋,我懂得!所有我覺得我是前端工程師!包括js文件在整個(gè)運(yùn)行過程中的位置,我還是有必要說說滴。
js文件的研究,就不那么俗套了,直接說位置放在head和body中 的情況吧。
先說,一般情況下,大一統(tǒng)的結(jié)論就是,加載了js文件,立刻執(zhí)行,所以會(huì)阻礙后面的文件的執(zhí)行,也會(huì)阻礙后面的內(nèi)容的展示的。所以,一般情況下,都會(huì)把這個(gè)家伙放到body的最后,反正它就是個(gè)功能效果,對(duì)頁面的顯示體驗(yàn)影響不大,那就先讓頁面顯示出來,最后再加載頁面的功能效果。并且js文件有作用元素,如果元素還沒出來,js先執(zhí)行了,就會(huì)報(bào)錯(cuò)。
如果放head里,不用說了,按標(biāo)簽順序來,到了它這里,開始加載,加載的話不會(huì)影響其他哥們的加載,但是加載 完了,就立刻執(zhí)行,執(zhí)行時(shí),它下面的css不能執(zhí)行,html內(nèi)容不能展示的。
在body里的js文件嗯,一般來說,應(yīng)該也是跟head里的差不多的,但是偏偏有特例,嗯,在谷歌里,body里的js文件,有一個(gè)很有意思的現(xiàn)象,所以不是結(jié)論,視頻里老師稱之為谷歌的自己的優(yōu)化——body里的js文件的first child,嗯就是大兒子的意思,有特殊待遇,在比其他的js兄弟們更早地加載執(zhí)行,如何更早?幾乎相當(dāng)于html解析到它這里時(shí),做了個(gè)停頓,判斷處理,一秒左右,就開始加載了,這不算特殊。從除了它之外,其他的兄弟們受到隊(duì)伍前面的css文件執(zhí)行的阻礙,前面的執(zhí)行完了,它們才開始加載,所以大兒子是個(gè)異類。
然后,說到底,研究js如果太鉆牛角尖到具體的加載時(shí)機(jī)上,其實(shí)太復(fù)雜了,這僅僅是一個(gè)谷歌,還是那句話,不是瀏覽器開發(fā)者,就不懂得制定規(guī)則,只能按規(guī)則來,但是一個(gè)開發(fā)者一個(gè)規(guī)則,亂七八糟的,對(duì)初學(xué)者甚至于僅僅是個(gè)前端層次的大局來說,很無力,尤其是現(xiàn)在網(wǎng)速如此發(fā)達(dá)了,我們應(yīng)該更關(guān)注于一些最基本的運(yùn)行原理,比如js的阻礙效果,如何優(yōu)化?做到看到現(xiàn)象,能夠模擬,解析出來邏輯,就可以了,哪里有那么多大一統(tǒng)的總結(jié)?

異步加載

defer 和 async
避免js文件的加載和執(zhí)行擋路,于是有兩個(gè)屬性。
defer 和 async 在網(wǎng)絡(luò)讀?。ㄏ螺d)這塊兒是一樣的,都是異步的(相較于 HTML 解析)。
它倆的差別在于腳本下載完之后何時(shí)執(zhí)行,顯然 defer 是最接近我們對(duì)于應(yīng)用腳本加載和執(zhí)行的要求的。
關(guān)于 defer,它是按照加載順序執(zhí)行腳本的,這一點(diǎn)要善加利用。
async 則是一個(gè)亂序執(zhí)行的主,反正對(duì)它來說腳本的加載和執(zhí)行是緊緊挨著的,所以不管你聲明的順序如何,只要它加載完了就會(huì)立刻執(zhí)行。
仔細(xì)想想,async 對(duì)于應(yīng)用腳本的用處不大,因?yàn)樗耆豢紤]依賴(哪怕是最低級(jí)的順序執(zhí)行),不過它對(duì)于那些可以不依賴任何腳本或不被任何腳本依賴的腳本來說卻是非常合適的,最典型的例子:網(wǎng)頁的廣告。
此處拿來主義《defer和async的區(qū)別》。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容