如何做單網(wǎng)頁網(wǎng)站抖音seo優(yōu)化公司
瀏覽器架構(gòu)
線程:操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。
進(jìn)程:操作系統(tǒng)最核心的就是進(jìn)程,他是操作系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位。
一個(gè)進(jìn)程就是一個(gè)程序的運(yùn)行實(shí)例。啟動(dòng)一個(gè)程序的時(shí)候,操作系統(tǒng)會(huì)為該程序創(chuàng)建一塊內(nèi)存,用來存放代碼、運(yùn)行中的數(shù)據(jù)和一個(gè)執(zhí)行任務(wù)的主線程,把這樣的一個(gè)運(yùn)行環(huán)境叫進(jìn)程。
線程是依附于進(jìn)程的,而進(jìn)程中使用多線程并行處理能提升運(yùn)算效率。
進(jìn)程和線程之間的關(guān)系4個(gè)特點(diǎn)。
- 進(jìn)程中任意線程執(zhí)行出錯(cuò),都會(huì)導(dǎo)致整個(gè)進(jìn)程崩潰
- 線程之間共享進(jìn)程中的數(shù)據(jù)
- 當(dāng)一個(gè)進(jìn)程關(guān)閉后,操作系統(tǒng)會(huì)回收進(jìn)程占用的內(nèi)存
- 進(jìn)程之間內(nèi)容相互隔離(通過IPC機(jī)制進(jìn)行通信)
現(xiàn)代瀏覽器為多進(jìn)程架構(gòu),打開一個(gè)頁面,瀏覽器至少會(huì)打開四個(gè)進(jìn)程 -- 瀏覽器主進(jìn)程、渲染進(jìn)程、GPU進(jìn)程、網(wǎng)絡(luò)進(jìn)程。
- 瀏覽器進(jìn)程:主要負(fù)責(zé)界面顯示、用戶交互、子進(jìn)程管理,同時(shí)提供存儲等功能。
- 渲染進(jìn)程:核心任務(wù)是將 HTML、CSS 和 JavaScript 轉(zhuǎn)換為用戶可以與之交互的網(wǎng)頁,排版引擎Blink和JavaScript引擎V8都是運(yùn)行在該進(jìn)程中,默認(rèn)情況下,Chrome會(huì)為每個(gè)Tab標(biāo)簽創(chuàng)建一個(gè)渲染進(jìn)程。出于安全考慮,渲染進(jìn)程都是運(yùn)行在沙箱模式下。
- GPU進(jìn)程:實(shí)現(xiàn)3D CSS效果,UI界面繪制。
- 網(wǎng)絡(luò)進(jìn)程。主要負(fù)責(zé)頁面的網(wǎng)絡(luò)資源加載。
- 插件進(jìn)程。主要是負(fù)責(zé)插件的運(yùn)行,因插件易崩潰,所以需要通過插件進(jìn)程來隔離,以保證插件進(jìn)程崩潰不會(huì)對瀏覽器和頁面造成影響。
地址欄鍵入U(xiǎn)RL后會(huì)發(fā)生什么?
- 構(gòu)建請求:瀏覽器準(zhǔn)備發(fā)起網(wǎng)絡(luò)請求,構(gòu)建請求行等
- 查找緩存:若命中強(qiáng)緩存,直接攔截請求,從本地獲取資源
#URL解析
先進(jìn)行url解析,提取出協(xié)議,端口,域名,路徑等信息
判斷你輸入的是一個(gè)合法的URL
?還是一個(gè)待搜索的關(guān)鍵詞,并且根據(jù)你輸入的內(nèi)容進(jìn)行對應(yīng)操作
#DNS查詢
獲取到了域名對應(yīng)的目標(biāo)服務(wù)器IP
地址
DNS(Domain Name System)是互聯(lián)網(wǎng)中用于將域名轉(zhuǎn)換為對應(yīng) IP 地址的分布式數(shù)據(jù)庫系統(tǒng)。當(dāng)客戶端需要解析域名時(shí),它會(huì)發(fā)送 DNS 查詢請求到 DNS 服務(wù)器,并獲取對應(yīng)的 IP 地址。DNS 查詢過程可以分為遞歸查詢和迭代查詢兩種方式。### 遞歸查詢1. **客戶端發(fā)起請求**:當(dāng)客戶端需要解析域名時(shí),它會(huì)發(fā)送一個(gè) DNS 查詢請求到本地 DNS 服務(wù)器。2. **本地 DNS 服務(wù)器查詢**:本地 DNS 服務(wù)器首先檢查自己的緩存中是否有該域名對應(yīng)的 IP 地址。如果有,它會(huì)直接返回給客戶端。3. **迭代查詢**:如果本地 DNS 服務(wù)器的緩存中沒有該域名對應(yīng)的 IP 地址,它會(huì)向根域名服務(wù)器發(fā)送一個(gè) DNS 查詢請求。根域名服務(wù)器會(huì)告訴本地 DNS 服務(wù)器負(fù)責(zé)該頂級域的權(quán)威 DNS 服務(wù)器的地址。4. **查詢頂級域 DNS 服務(wù)器**:本地 DNS 服務(wù)器再向負(fù)責(zé)該頂級域的權(quán)威 DNS 服務(wù)器發(fā)送一個(gè) DNS 查詢請求。頂級域 DNS 服務(wù)器會(huì)告訴本地 DNS 服務(wù)器負(fù)責(zé)該二級域的權(quán)威 DNS 服務(wù)器的地址。5. **查詢權(quán)威 DNS 服務(wù)器**:本地 DNS 服務(wù)器繼續(xù)向負(fù)責(zé)該二級域的權(quán)威 DNS 服務(wù)器發(fā)送 DNS 查詢請求,直到最終獲取到域名對應(yīng)的 IP 地址。本地 DNS 服務(wù)器將 IP 地址返回給客戶端,并將 IP 地址緩存起來,以便下次查詢時(shí)使用。### 迭代查詢1. **客戶端發(fā)起請求**:客戶端發(fā)送一個(gè) DNS 查詢請求到 DNS 服務(wù)器。2. **DNS 服務(wù)器查詢**:DNS 服務(wù)器首先檢查自己的緩存中是否有該域名對應(yīng)的 IP 地址。如果有,它會(huì)直接返回給客戶端。3. **迭代查詢**:如果 DNS 服務(wù)器的緩存中沒有該域名對應(yīng)的 IP 地址,它會(huì)向根域名服務(wù)器發(fā)送一個(gè) DNS 查詢請求。根域名服務(wù)器會(huì)告訴 DNS 服務(wù)器負(fù)責(zé)該頂級域的權(quán)威 DNS 服務(wù)器的地址。4. **查詢頂級域 DNS 服務(wù)器**:DNS 服務(wù)器再向負(fù)責(zé)該頂級域的權(quán)威 DNS 服務(wù)器發(fā)送一個(gè) DNS 查詢請求。頂級域 DNS 服務(wù)器會(huì)告訴 DNS 服務(wù)器負(fù)責(zé)該二級域的權(quán)威 DNS 服務(wù)器的地址。5. **查詢權(quán)威 DNS 服務(wù)器**:DNS 服務(wù)器繼續(xù)向負(fù)責(zé)該二級域的權(quán)威 DNS 服務(wù)器發(fā)送 DNS 查詢請求,直到最終獲取到域名對應(yīng)的 IP 地址。然后,DNS 服務(wù)器將 IP 地址返回給客戶端。=======遞歸查詢和迭代查詢的主要區(qū)別在于,遞歸查詢是由 DNS 服務(wù)器代為向其他 DNS 服務(wù)器查詢,直到找到域名對應(yīng)的 IP 地址并返回給客戶端;而迭代查詢是由 DNS 服務(wù)器一步步地指導(dǎo)客戶端自行向其他 DNS 服務(wù)器查詢,直到最終找到域名對應(yīng)的 IP 地址。
實(shí)際上,DNS 解析過程中既有遞歸查詢,也有迭代查詢,這兩種查詢方式是相輔相成的。1. **遞歸查詢**:在 DNS 解析過程中,客戶端向本地 DNS 服務(wù)器發(fā)起遞歸查詢請求。本地 DNS 服務(wù)器會(huì)負(fù)責(zé)向其他 DNS 服務(wù)器發(fā)送遞歸查詢請求,直到找到域名對應(yīng)的 IP 地址,并將結(jié)果返回給客戶端。遞歸查詢的特點(diǎn)是 DNS 服務(wù)器會(huì)負(fù)責(zé)完成整個(gè)查詢過程,直到找到結(jié)果并返回給客戶端。2. **迭代查詢**:在 DNS 解析過程中,當(dāng)本地 DNS 服務(wù)器無法直接返回結(jié)果時(shí),它會(huì)向其他 DNS 服務(wù)器發(fā)送迭代查詢請求,獲取更多的信息。這些迭代查詢請求會(huì)依次向根域名服務(wù)器、頂級域 DNS 服務(wù)器和權(quán)威 DNS 服務(wù)器發(fā)送,直到最終找到結(jié)果。迭代查詢的特點(diǎn)是 DNS 服務(wù)器向客戶端提供其他 DNS 服務(wù)器的地址,然后客戶端會(huì)繼續(xù)向這些 DNS 服務(wù)器發(fā)送查詢請求,直到找到結(jié)果。因此,DNS 解析過程中通常會(huì)同時(shí)使用遞歸查詢和迭代查詢,以確??蛻舳四軌蚩焖贉?zhǔn)確地獲取到域名對應(yīng)的 IP 地址。
#TCP連接
在確定目標(biāo)服務(wù)器服務(wù)器的IP
地址后,則經(jīng)歷三次握手建立TCP
連接
#發(fā)送 http 請求
當(dāng)建立tcp
連接之后,就可以在這基礎(chǔ)上進(jìn)行通信,瀏覽器發(fā)送?http
?請求到目標(biāo)服務(wù)器
請求的內(nèi)容包括:
- 請求行
- 請求頭
- 請求主體
#響應(yīng)請求
當(dāng)服務(wù)器接收到瀏覽器的請求之后,就會(huì)進(jìn)行邏輯操作,處理完成之后返回一個(gè)HTTP
響應(yīng)消息,包括:
- 狀態(tài)行
- 響應(yīng)頭
- 響應(yīng)正文
在服務(wù)器響應(yīng)之后,由于現(xiàn)在http
默認(rèn)開始長連接keep-alive
,當(dāng)頁面關(guān)閉之后,tcp
鏈接則會(huì)經(jīng)過四次揮手完成斷開
#頁面渲染
當(dāng)瀏覽器接收到服務(wù)器響應(yīng)的資源后,首先會(huì)對資源進(jìn)行解析:
- 查看響應(yīng)頭的信息,根據(jù)不同的指示做對應(yīng)處理,比如重定向(301,302),存儲cookie(如果響應(yīng)頭中包含 Set-Cookie 字段,表示服務(wù)器希望瀏覽器存儲 cookie,瀏覽器會(huì)根據(jù)這些字段存儲 cookie 信息。),解壓gzip(Content-Encoding :gzip),緩存資源等等
- 查看響應(yīng)頭的 Content-Type的值,根據(jù)不同的資源類型采用不同的解析方式
(Content-Type 是響應(yīng)頭中的一個(gè)字段,它指示了響應(yīng)內(nèi)容的類型。瀏覽器會(huì)根據(jù) Content-Type 的值來確定響應(yīng)的內(nèi)容類型,然后采用不同的解析方式對響應(yīng)內(nèi)容進(jìn)行處理。例如:
- 如果 Content-Type 表示響應(yīng)內(nèi)容是 HTML 文檔(如
text/html
),瀏覽器會(huì)將其解析為 DOM 結(jié)構(gòu),并進(jìn)行頁面渲染。 - 如果 Content-Type 表示響應(yīng)內(nèi)容是 JavaScript 腳本(如
application/javascript
),瀏覽器會(huì)執(zhí)行這段 JavaScript 代碼。 - 如果 Content-Type 表示響應(yīng)內(nèi)容是 CSS 樣式表(如
text/css
),瀏覽器會(huì)解析這段 CSS 代碼,并應(yīng)用于頁面渲染。 - 如果 Content-Type 表示響應(yīng)內(nèi)容是圖片、音頻或視頻等媒體資源(如
image/jpeg
、audio/mp3
、video/mp4
等),瀏覽器會(huì)直接將其展示給用戶或者交給相應(yīng)的插件進(jìn)行處理。)
渲染流程:HTML、CSS和JavaScript,是如何變成頁面的?
關(guān)于頁面的渲染過程如下:dom css render 布局繪制顯示
- 解析HTML,構(gòu)建 DOM 樹
- 解析 CSS ,生成 CSS 規(guī)則樹 樣式計(jì)算
- 合并 DOM 樹和 CSS 規(guī)則,生成 render 樹,(在這個(gè)階段,瀏覽器會(huì)根據(jù) DOM 樹中的每個(gè)可見節(jié)點(diǎn)和樣式計(jì)算得到的具體樣式來構(gòu)建渲染樹,忽略掉不可見的元素或不影響渲染的節(jié)點(diǎn)(比如
<script>
、<meta>
等)。這個(gè)渲染樹將用于后續(xù)的布局和繪制。) - 布局 render 樹( Layout / reflow ),負(fù)責(zé)各元素尺寸、位置的計(jì)算
- 繪制 render 樹( paint ),繪制頁面像素信息
- 瀏覽器會(huì)將各層的信息發(fā)送給 GPU,GPU 會(huì)將各層合成,顯示在屏幕上
-
構(gòu)建DOM樹:瀏覽器無法直接理解和使用HTML,所以需要將HTML轉(zhuǎn)換為瀏覽器能夠理解的結(jié)構(gòu)——DOM樹
-
樣式計(jì)算:
- 把CSS轉(zhuǎn)換為瀏覽器能夠理解的結(jié)構(gòu) -- styleSheets
- 轉(zhuǎn)換樣式表中的屬性值,使其標(biāo)準(zhǔn)化,比如將顏色‘red’轉(zhuǎn)化成渲染引擎可以理解的rgb值
- 瀏覽器會(huì)將DOM樹和CSS規(guī)則樹合并,計(jì)算每個(gè)元素的具體樣式信息,即進(jìn)行樣式計(jì)算。這個(gè)過程中,瀏覽器會(huì)計(jì)算出每個(gè)DOM節(jié)點(diǎn)的最終樣式信息,包括繼承的樣式和自身的樣式。
-
布局階段:有了DOM樹和樣式,還不足以顯示頁面,接下來就需要計(jì)算出DOM樹中可見元素的幾何位置,這個(gè)計(jì)算過程叫做布局。
- 創(chuàng)建布局樹:構(gòu)建一顆元素布局樹,比如去掉head等沒有實(shí)際元素的標(biāo)簽,去掉display為none的元素等
-
分層:頁面中有很多復(fù)雜的效果,如一些復(fù)雜的3D變換、頁面滾動(dòng),或者使用z-indexing做z軸排序等,為了更加方便地實(shí)現(xiàn)這些效果,渲染引擎還需要為特定的節(jié)點(diǎn)生成專用的圖層,并生成一棵對應(yīng)的圖層樹。所以瀏覽器的頁面實(shí)際上被分成了很多圖層,這些圖層疊加后合成了最終的頁面
-
圖層繪制:將布局樹中的元素轉(zhuǎn)換成屏幕上的像素信息。
-
柵格化操作:通常一個(gè)頁面可能很大,但是用戶只能看到其中的一部分,這個(gè)部分叫做視口。在有些情況下,有的圖層可以很大,比如有的頁面要滾動(dòng)好久才能滾動(dòng)到底部,但是通過視口,用戶只能看到頁面的很小一部分,所以在這種情況下,要繪制出所有圖層內(nèi)容的話,就會(huì)產(chǎn)生太大的開銷,而且也沒有必要?;谶@個(gè)原因,合成線程會(huì)將圖層劃分為圖塊,這些圖塊的大小通常是256x256或者512x512。然后合成線程會(huì)按照視口附近的圖塊來優(yōu)先生成位圖,實(shí)際生成位圖的操作是由柵格化來執(zhí)行的。所謂柵格化,是指將圖塊轉(zhuǎn)換為位圖。而圖塊是柵格化執(zhí)行的最小單位。
-
合成和顯示:所有圖塊都柵格化完成后,合成線程將指令提交給瀏覽器進(jìn)程,瀏覽器進(jìn)程根據(jù)指令將頁面內(nèi)容繪制到內(nèi)存中,最后從內(nèi)存中取出圖像顯示到屏幕上。
從發(fā)起URL請求開始,到首次顯示頁面的內(nèi)容,在視覺上經(jīng)歷三個(gè)階段??赡軙?huì)有阻塞的地方,怎么解決
頁面渲染過程中可能出現(xiàn)阻塞的主要環(huán)節(jié)包括:
- 等請求發(fā)出去之后,到提交數(shù)據(jù)階段,這時(shí)頁面展示出來的還是之前頁面的內(nèi)容。
- 提交數(shù)據(jù)之后渲染進(jìn)程會(huì)創(chuàng)建一個(gè)空白頁面,這段時(shí)間稱為解析白屏,并等待CSS文件和JavaScript文件的加載完成,生成CSS規(guī)則樹和dom樹,然后合成布局樹,最后還要經(jīng)過一系列的步驟準(zhǔn)備首次渲染。
- 第三個(gè)階段,等首次渲染完成之后,就開始進(jìn)入完整頁面的生成階段了,然后頁面會(huì)一點(diǎn)點(diǎn)被繪制出來。
影響第一個(gè)階段的因素主要是網(wǎng)絡(luò)或者是服務(wù)器處理。
第二個(gè)階段主要問題是白屏?xí)r間,如果白屏?xí)r間過久,就會(huì)影響到用戶體驗(yàn)。為了縮短白屏?xí)r間,需要挨個(gè)分析這個(gè)階段的主要任務(wù),包括了解析HTML、下載CSS、下載Js、生成CSSOM、執(zhí)行JavaScript、生成布局樹、繪制頁面一系列操作。通常情況下的瓶頸主要體現(xiàn)在下載CSS文件、下載JavaScript文件和執(zhí)行JavaScript。
1. HTML解析:瀏覽器解析HTML文檔構(gòu)建DOM樹時(shí),如果遇到`<script>`標(biāo)簽,會(huì)立即暫停解析,等待腳本執(zhí)行完畢。這是因?yàn)槟_本可能會(huì)修改DOM,所以瀏覽器需要等待腳本執(zhí)行完成后再繼續(xù)解析。
2. CSS解析:CSSOM(CSS對象模型)的構(gòu)建也可能阻塞渲染,因?yàn)闉g覽器需要確保頁面的樣式在腳本執(zhí)行之前就已經(jīng)確定。
3. JavaScript執(zhí)行:JavaScript的執(zhí)行會(huì)阻塞DOM的構(gòu)建,因?yàn)槟_本可能會(huì)操作DOM元素。
所以要想縮短白屏?xí)r長,可以有以下策略:
- 將關(guān)鍵CSS直接內(nèi)聯(lián)到HTML中(style標(biāo)簽),可以加快首次渲染的速度(行內(nèi)>內(nèi)部>外部)。對于非關(guān)鍵CSS,可以通過媒體查詢或JavaScript異步加載。這樣只有在特定的場景下才會(huì)加載特定的CSS文件。
-
<!-- 異步加載非關(guān)鍵CSS --><script>var link = document.createElement('link');link.rel = 'stylesheet';link.href = 'non-critical.css';document.head.appendChild(link);</script> </head>
- 異步加載腳本:使用
async
或defer
屬性將JavaScript腳本異步加載,可以使得腳本不會(huì)阻塞頁面的渲染,從而減少白屏?xí)r間。? ? ? ? ? ? ? ? ? ? ? ? ? ?async:異步加載腳本,腳本加載完成后,會(huì)立即執(zhí)行,與在頁面中出現(xiàn)的順序無關(guān);? ? ? ? ? ??defer:瀏覽器立即加載,但是延遲執(zhí)行,需要在DOMContentLoaded事件之前執(zhí)行,與出現(xiàn)順序有關(guān),dom加載完畢后按出現(xiàn)順序依次執(zhí)行。 -
使用CDN加速:將頁面資源分發(fā)到全球各地的CDN(內(nèi)容分發(fā)網(wǎng)絡(luò)),可以加速資源的加載速度,減少白屏?xí)r間。CDN可以使用戶從距離較近的服務(wù)器獲取資源,從而提高訪問速度。
- 使用預(yù)加載和預(yù)渲染技術(shù):可以使用預(yù)加載(preload)和預(yù)渲染(prerender)等技術(shù),提前加載頁面所需的資源或者預(yù)渲染頁面內(nèi)容,以減少白屏?xí)r間。預(yù)加載可以在頁面加載過程中提前加載關(guān)鍵資源,而預(yù)渲染可以在后臺加載整個(gè)頁面內(nèi)容,使得用戶訪問頁面時(shí)可以立即展示完整內(nèi)容。
- HTTP/2通過引入多路復(fù)用、頭部壓縮、服務(wù)器推送等技術(shù),優(yōu)化了網(wǎng)絡(luò)資源的利用效率,減少了網(wǎng)絡(luò)連接的延遲,提高了頁面加載速度
- 代碼分割和懶加載:可以使用代碼分割將代碼分成多個(gè)小塊,然后按需加載。對于不影響首屏渲染的組件或功能,可以使用懶加載技術(shù)延遲加載。Webpack提供了一種稱為“動(dòng)態(tài)導(dǎo)入”的語法,可以實(shí)現(xiàn)代碼分割。
// 使用動(dòng)態(tài)導(dǎo)入語法,將代碼按需分割成多個(gè)小塊
import('./module').then(module => {// 在需要的時(shí)候加載模塊module.doSomething();
});
Webpack會(huì)將動(dòng)態(tài)導(dǎo)入的代碼塊分割成單獨(dú)的文件,并在需要的時(shí)候按需加載。
在React中,可以使用React.lazy和Suspense組件來實(shí)現(xiàn)懶加載。
import React, { Suspense } from 'react';const LazyComponent = React.lazy(() => import('./LazyComponent'));function MyComponent() {return (<div><Suspense fallback={<div>Loading...</div>}><LazyComponent /></Suspense></div>);
}
當(dāng) MyComponent 被渲染時(shí),它會(huì)先顯示 fallback 屬性指定的加載中提示,
然后在 LazyComponent 加載完成后顯示真正的內(nèi)容。
- 客戶端緩存:瀏覽器可以通過緩存響應(yīng)內(nèi)容來減少對服務(wù)器的請求。通過設(shè)置合適的緩存控制頭(如
Cache-Control
和Expires
),可以告訴瀏覽器何時(shí)可以使用緩存以及緩存的有效期。對于那些不經(jīng)常變化的靜態(tài)資源,可以使用強(qiáng)緩存來盡快地加載頁面內(nèi)容,減少白屏?xí)r間;而對于那些可能會(huì)頻繁更新的動(dòng)態(tài)內(nèi)容,可以使用協(xié)商緩存來確保客戶端可以獲取到最新的資源。在Express中,你可以在路由處理函數(shù)中設(shè)置緩存控制頭,通過res.setHeader
方法實(shí)現(xiàn)。
代碼優(yōu)化
比如下面的代碼,實(shí)現(xiàn)了一個(gè)斐波那契數(shù)列,也就是說,在實(shí)現(xiàn)的這個(gè)數(shù)列中,每一個(gè)數(shù)的值是前面兩個(gè)數(shù)的值之和??梢允褂煤唵蔚倪f歸算法實(shí)現(xiàn)斐波那契數(shù)列后,在頁面顯示計(jì)算結(jié)果。
function fib(n){ if(n<=1) return 1 return fib(n-1)+fib(n-2) } let count = ref(fib(38))
使用performance:
打開調(diào)試窗口中的 Performance 面板,使用錄制功能后,便可得到下面的火焰圖。通過這個(gè)火焰圖,可以清晰地定位出這個(gè)項(xiàng)目中,整體而言耗時(shí)最長的 fib 函數(shù),并且能看到這個(gè)函數(shù)被遞歸執(zhí)行了無數(shù)次。到這里,不難意識到這段代碼有性能問題。不過,定位到問題出現(xiàn)的地方之后,代碼性能的優(yōu)化就變得方向明確了。
用戶體驗(yàn)優(yōu)化
1.比如用戶加載大量圖片的同時(shí),如果本身圖片清晰度較高,那直接加載的話,頁面會(huì)有很多圖一直是白框。所以可以預(yù)先解析出圖片的一個(gè)模糊版本,加載圖片的時(shí)候,先加載這個(gè)模糊的圖作為占位符,然后再去加載清晰的版本。雖然額外加載了圖片文件,但是用戶在體驗(yàn)上得到了提升。
2.類似的場景還有很多,比如用戶上傳文件的時(shí)候,如果文件過大,那么上傳可能就會(huì)很耗時(shí)。而且一旦上傳的過程中發(fā)生了網(wǎng)絡(luò)中斷,那上傳就前功盡棄了。為了提高用戶的體驗(yàn),可以選擇斷點(diǎn)續(xù)傳,也就是把文件切分成小塊后,挨個(gè)上傳。這樣即使中間上傳中斷,但下次再上傳時(shí),只上傳缺失的那些部分就可以了??梢钥吹?#xff0c;斷點(diǎn)上傳雖然在性能上,會(huì)造成網(wǎng)絡(luò)請求變多的問題,但也極大地提高了用戶上傳的體驗(yàn)。
3.還有很多組件庫也會(huì)提供骨架圖的組件,能夠在頁面還沒有解析完成之前,先渲染一個(gè)頁面的骨架和 loading 的狀態(tài),這樣用戶在頁面加載的等待期就不至于一直白屏
性能監(jiān)測報(bào)告
解釋一下 FCP、TTI 和 LCP 這幾個(gè)關(guān)鍵指標(biāo)的含義。
首先是 First Contentful Paint,通常簡寫為 FCP,它表示的是頁面上呈現(xiàn)第一個(gè) DOM 元素的時(shí)間。在此之前,頁面都是白屏的狀態(tài);
然后是 Time to interactive,通常簡寫為 TTI,也就是頁面可以開始交互的時(shí)間;
還有和用戶體驗(yàn)相關(guān)的 Largest Contentful Paint,通常簡寫為 LCP,這是頁面視口上最大的圖片或者文本塊渲染的時(shí)間,在這個(gè)時(shí)間,用戶能看到渲染基本完成后的首頁,這也是用戶體驗(yàn)里非常重要的一個(gè)指標(biāo)。
可以通過代碼中的 performance 對象去動(dòng)態(tài)獲取性能指標(biāo)數(shù)據(jù),并且統(tǒng)一發(fā)送給后端,實(shí)現(xiàn)網(wǎng)頁性能的監(jiān)控。性能監(jiān)控也是大型項(xiàng)目必備的監(jiān)控系統(tǒng)之一,可以獲取到用戶電腦上項(xiàng)目運(yùn)行的狀態(tài)。下圖展示了 performance 中所有的性能指標(biāo),可以通過這些指標(biāo)計(jì)算出需要統(tǒng)計(jì)的性能結(jié)果。
const timing = window.performance && window.performance.timing
const navigation = window.performance && window.performance.navigation// DNS 解析:
const dns = timing.domainLookupEnd - timing.domainLookupStart// 總體網(wǎng)絡(luò)交互耗時(shí):
const network = timing.responseEnd - timing.navigationStart// 渲染處理:
const processing = (timing.domComplete || timing.domLoading) - timing.domLoading// 可交互:
const active = timing.domInteractive - timing.navigationStart
在上面的代碼中,通過 Performance API 獲取了 DNS 解析、網(wǎng)絡(luò)、渲染和可交互的時(shí)間消耗。有了這些指標(biāo)后,就可以隨時(shí)對用戶端的性能進(jìn)行檢測,做到提前發(fā)現(xiàn)問題,提高項(xiàng)目的穩(wěn)定性。