文共4167字,預計學習時長11分鐘
圖源:turnkeyInternet
查詢谷歌會發現很多文章指出2到5秒鐘網頁就能加載完畢。但是,是什么使2-5秒成為預設范圍呢?直覺告訴你,答案必定比這更復雜。沒錯,真正的答案比任何試圖解答的時間范圍細微得多,問題出在提問本身。
并非所有網站和訪問者都一樣
這個問題有一個缺陷,即認為在不同情況下可采用同一標準。網站不同,用戶訪問網站的網絡情況也不盡相同。
靜態博客與圖形編輯器不同,4G比2G快得多。靜態博客可能根本用不到JavaScript,圖形編輯器卻會大量使用。4G網絡訪問者可能只會遇到50毫秒的延遲,而2G用戶每次往返可能會經歷整整一秒鐘的時間。
上表描述了理想條件下達到的數據速率。地下車庫不是理想環境,但每個人都有可能會遇到這樣的情況,這意味著用戶訪問網站所使用的網絡條件千變萬化。
網絡條件的可變性
調整網絡狀況會導致頁面加載時間截然不同。假設有兩個用戶要通過移動網絡訪問筆者的個人網站(davidea.st)。它只是一個靜態網站,不會阻斷JavaScript。index.html文件大小只有2.3kb,CSS的大小是1.8kb。
第一個用戶以400kib的帶寬(2G速度)但100ms的延遲(4G速度)訪問。第二位訪問者以400kib的帶寬,但有1000ms的延遲(均為2G速度)訪問。
使用同一網站,調整延遲(當人在停車場時延遲就會很容易調整)使index.html的加載速度慢了十倍。因此,如果僅考慮網絡延遲就可以徹底改變同一站點的頁面加載速度,只是提問“網站應該以多快速度加載”有意義嗎?
開發人員無法控制用戶進入的網絡。這意味著判定網絡性能并不僅僅是了解網站加載時間的固定數字。而是要知道頁面加載發生在不同條件下的不同時間段,知道這一點的唯一方法是測量。
RUM:測量現實世界性能
這正是RUM監控所能提供的。RUM或“真實用戶指標”,從頁面加載中收集重要的性能指標并將其信標到可以查看儀表盤數據的服務器。RUM供應商的形狀和大小各不相同,就本文而言,筆者將使用FirebasePerformance Monitoring。
Web性能是一種分布
想象一下,如果記錄了訪問網站的用戶的首次渲染時間。然后,將時間記錄在條形圖中,如下所示:
但是,如此呈現的視覺效果并不準確,并非所有用戶都將在完全相同的時間段內加載網站。一個人的網站加載時間為1.5秒,下一個人的網站加載時間為1.65秒。因此,可以使用面積圖代替條形圖。
該面積圖顯示了加載時間的分布,可以幫助了解加載時間的范圍以及最常見的情況,它代表所有加載時間的百分位。
Firebase Performance Monitoring為不同指標提供了一個完整的面積圖儀表板。
x軸代表更大的加載時間數組,y軸表示百分位數,這些百分位數最有趣的是它們的形狀。
尾部
圖表開始急劇向上彎曲,然后緩慢向下彎曲,形成尾巴形狀。這說明大多數用戶的加載時間在1.5到3.5秒之間。這很好,但是不要被這種變化所騙,尾部包含所有問題。
尾部表示遇到最長加載時間的用戶。尾部越長,波動性越大。這意味著網站性能變得難以理解。有些用戶加載很快,有些載入緩慢。因此,我們需要努力縮短尾部,也需要了解尾部代表什么。
網站何時可用?
當大多數人說“頁面加載”時,指的是該站點實際可用的時間。這有點誤導人,因為網站不必完全加載。
想想一個報導重大事件的實時流媒體博客。訪問它時發現,屏幕上神奇地出現了超時更新。該頁面什么時候“加載”?當第一次更新出現時嗎?當header加載時是嗎?并非人人都想細究這一話題,可以將頁面加載細分為更具體的指標。
“頁面加載”的指標
用戶啟動網站加載時會使用到導航,這可能是通過鍵入URL并單擊Enter或單擊鏈接生效。沒有渲染像素,瀏覽器通過網絡獲取資源。
初次渲染(FirstPaint, FP)是引用的最常見指標之一。它只會問:屏幕上何時出現普通的像素?了解像素何時開始出現很重要,因為可以了解用戶開始看到畫面的速度。在某些情況下,此反饋可以幫助用戶知道該網站正在加載,因而繼續等待。
如果要構建傳統的服務器端渲染網站(與服務器端呈現JavaScript應用程序不同),則First Paint可以準確地表示“頁面加載”。這是因為所有HTML和CSS都可以使用,無任何渲染阻止JavaScript。但這對于依賴JavaScript的網站可能有所不同。
在很多單頁應用(SPA)網站的情況下,First Paint用于靜態元素,例如頁眉和頁腳。該應用程序的其余部分仍在啟動,等待JavaScript加載和執行。用戶可能會看到一些東西,但該應用程序尚未可用。
首次有內容的渲染(FirstContentful Paint,FCP)關注的是設計內容何時出現在頁面上。這不僅僅是渲染到屏幕上的像素。如果網站加載速度很快,FCP和FP往往會同時啟動。但如果阻止了Web字體的文本呈現,或者當內容需要JavaScript來加載和執行時,FCP可能會落后于FP。
即使網站加載速度緩慢,FCP和FP的速度也可以相同。這是大型JavaScript應用程序的常見現象,這些應用程序無法渲染或渲染太多靜態HTML。在這種情況下,當JavaScript最終加載,執行并呈現FP和FCP時,往往會同時觸發它們。
domInteractve表示瀏覽器已經從靜態HTML構建了DOM樹。然后,瀏覽器開始加載其他資源,例如樣式表,圖像和JavaScript,這對于了解何時構造DOM樹以及何時瀏覽器將開始加載其他所有內容很有用。
何時知道重要的資源(如JavaScript和樣式表)已加載?這就是domContentLoadedEventEnd 的目的。當domContentLoadedEventEnd觸發時,不再有任何樣式表阻止任何JavaScript執行。這些度量標準非常有用,domInteractive 會說明何時開始加載樣式表,而domContentLoadedEventEnd 會說明何時結束加載。
“加載事件結束”(Load Event End)不一定總是最有用的指標,但有時它可以提供很多信息。文檔加載完成后,將觸發loadEventEnd事件。這意味著當DOM樹中的所有資源都已加載時將觸發該事件。所有鏈接的樣式表、腳本和圖像、圖片等資源可能會降低此指標的速度,如果不小心將100MB GIF上傳到網站,則會看到相當慢的loadEventEnd。
此指標可幫助大致了解文檔資源的加載時間。在觸發此指標之前,網站可以使用很長時間。
首次輸入延遲(FirstInput Delay,FID)用于測量首次用戶交互觸發所花費的時間。用戶可能停留在看起來可以使用但已凍結的頁面上,無論進行多少次滑動或點擊,該網站都無法正常工作,這時需要“首次輸入延遲”來測量此類問題。
如果有靜態博客,它就也許沒那么有用,因為FID可以測量用戶何時可以與網站進行交互,這通常是在事件監聽器觸發后觸發的。現在,對于重型JavaScript應用程序,該指標也很關鍵。JavaScript繁重的應用程序必須先加載、解析和執行,然后才能運行,這可能會推遲網站的最初交互時刻。
WebVitals
如果你是一個精通性能的開發人員(或者如果關注過大牛Addy Osmani),那么你可能聽說過Web Vitals計劃。Web Vitals是Google的一項舉措,旨在為質量信號提供統一指導,這對于在網絡上提供出色的用戶體驗至關重要。
其目的是提高加載性能、交互性和穩定性。構成Web Vitals的核心指標是:
· 最大內容渲染(LCP)(測量加載性能)
· 首次輸入延遲(測量交互性)
· 累積版式移位(CLS)(測量穩定性)
筆者不會詳細介紹每個指標(因為已經介紹了很多指標),但是可以在web.dev/vitals上查看說明。每個指標都是通過Google網絡小組提供的庫檢索的。
import { getCLS, getFID,getLCP } from 'web-vitals';getCLS(console.log);
getFID(console.log);
getLCP(console.log);
Firebase性能監控僅支持將“首次輸入延遲”作為一流指標。在自動收集其他項目之前,可以使用“自定義跟蹤”記錄最大的內容豐富的渲染和累積版式移位。
指標過載
借助Performance Monitoring,可以使用屬性來細分性能數據,并專注于應用程序在某些情況下的性能:firebase.google.com。
Web性能處處是指標,但并非所有指標都對網站和個人情況有用。筆者建議你去了解一下,看看它如何為你的網站類型服務。不用擔心追蹤所有指標,只要了解哪種方法最適合網站。
網站應該以多快速度加載?
如何處理這些指標?你可以使用它們來了解網站上發生的情況并提出更好的問題。有個問題必然要問:“使用3G訪問用戶何時首次看到內容?”追蹤這些指標可以查看受影響的用戶類型以及隨著時間推移的趨勢。
借助FirebasePerformance Monitoring,可以深入了解諸如First Contentful Paint的指標,查看哪些維度會影響指標。在這種情況下,可以按有效連接類型(網絡速度)將其拆分。
儀表板顯示大多數用戶至少使用4G或更快的連接網絡。但是,有5.88%的用戶使用3G速度并在2.24秒內加載網頁。這樣比問“網站應該以多快速度加載?”要好得多。
永遠記住,網頁加載的速度并非確定數值,Web性能本身就是一種分布。需幾行代碼,測量可以幫你提出更好的問題并獲得更好的答案。
留言點贊關注
我們一起分享AI學習與發展的干貨
如轉載,請后臺留言,遵守轉載規范
于做網站的需求越來越大,每個企業都想找一家可靠又有效率的的網站建設公司,對于這個要求,作為一個建站公司來說一定先要做到一點,這樣方可能確保建站時間的效速,那就是建站的時間。建站公司都希望建設網站的時間快,為什么這樣說呢?因為建站時間快那么會給建站公司省工時,同時也有提高工作效率。但是建站時間來說不單只有一個原因,還有多方面的因素,比如UI稿設計、網站代碼編寫、網站上線、網站驗收這都是要時間,對于時間方面建站公司給出一般都在于15到20個工作日來計,為什么要這么久呢?原因在會在哪呢?今天西安網站建設公司一度互聯小編來和大家分享一下在西安網站建設一般要多久:
一、UI設計時間
為什么談到UI設計,當然一個正常網站一定要有頁面設計的,一個網站好與壞都在UI方面體現的,對于UI方面設計時間要多久呢?在這方面當中要5到8個工作日,這也是UI設計常規的時間,要想做好網站這也是必然的第一步。
二、代碼程序編寫時間
網站的組成是CSS+DIY+HTML+JS寫這些代碼都要時間的,每一個網站的頁面都是一步一個代碼組成的,這也是一個重點原因之,在寫這些代碼都要花4到6個工作才能完成,所以一個網站組成的結構非常多,寫代碼時工程師都是一步一個腳印來寫的。
三、網站測試時間
網站完成后為什么還要測試呢?其實上網站測試是非常重要的一部份,所有問題都是在于網站測試才能體現出來的,那么測試時間要多久呢?相對來說要2個工作日成能完成的,這時間都是在尋找問題,找到問題后工程師還要一個一個來修復。
通過以上三點總結,我相信到大家都明白了,建站時間要多久了。其實上建站是急不來的都要有個過程的,不是一兩下就完事了,如果你明白后心里都有個數,這也幫你明白建站過程的時間,你可以更好的來規劃建站時間
如果您以前問我這個問題,我會說,肯定很難吧,我們用用開源項目就好。
何必重復造輪子?
應不應該重復造輪子呢?
我想每個人心中都有答案。但是我鼓勵大家,我們一起重復造輪子。
后續會出一篇文章,關于Chat的文章。是的,不是ChatGPT,是Chat,沒有機器學習,我們普通研發人員,也應該繼續前進,當然還是和正則表達式有關系。
現在,我們回到今天的話題,正則表達式實例與HTML語法樹。
前面的文章,我們知道了,怎么匹配HTML標簽,怎么匹配HTML標簽屬性,今天我們從零實現一個HTML語法樹。
看這篇文章之前,建議先看前面兩篇文章,如果您對正則非常熟悉,那么現在就開始吧。
在開始前,我們需要整理需求,我們需要知道,一個完整的HTML文檔,最基本的語法,標簽以及不同框架增加的特殊屬性等,我們因該如何去匹配實現。
為什么要加上其它框架屬性,因為當時想通過一套代碼生成VUE、React版本。[我想靜靜]
下面截圖文檔中,基本囊括了,一個HTML文檔的所有情況信息,您可以仔細看下。其中包括(注釋、文檔聲明、單標簽、雙標簽、樣式、腳本、有屬性值屬性、屬性名即屬性值屬性、第三方框架屬性等)。
需求文檔圖
<!-- 這是一段注釋。
寫好一個AST,讓組件一套代碼,
同時支持服務端渲染,前端渲染,是否可行? -->
const reg_comment=/<\!--.*?-->/s;
<!DOCTYPE html>
const reg_doctype=/<!doctype[^<>]*>/i;
<div><input />
const reg_element=/<[^\/\!]((["'])+.*?|[^>])+>/
</div>
const reg_elementEnd=/<\/.*?>/
<div></div>
var reg_tagName=/(?<=<[\/\s]*)\w+(?=(\s+(?![\s=])|>))/;
<input type='text' disabled value="" class="txt txt-md" v-on:click="save('button')" />
const reg_tagAttrs=/(?<=\s)[\w:\.\-@]+(=(["']).*?)*/g;
v-on:click="save('button')"
var reg_tagAttrDatas=/(^[^=]+|(?<=(['"])).*?(?=))/g;
查閱了相關資料、同時編寫Demo案例驗證、對于Javascript版本的正則表達式,發現對于嵌套匹配目前支持不完善,所以放棄這種方式。
當然,也有可能,我挖掘的還不夠深入。
怎么理解?
請看下面的例子。
<!-- 這是一段注釋。
寫好一個AST,組件一套代碼,
同時支持服務端渲染,前端渲染,似乎可行? -->
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<title>滄海一站</title>
<style type="text/css">
html,body {width: 100%;height: 100%;margin: 0;padding: 0;}
</style>
</head>
</html>
看到這個例子,你大概明白。就是一行一行的匹配,或者說每次只匹配一種類型。
1、遇到非input、img、link、hr、br這幾個單行標簽,或者</>結束標記,就向下遞歸。
2、遇到結束標記</>,就返回上一層。
3、遇到style、script標簽,他們內部的內容,直接按文本處理。
到這,我想部分朋友,都不需要看代碼實例,都知道怎么實現了。
測試代碼從PrvtCMS中,臨時拆分出來的,只要思路有了,實現起來還是很容易。
const reg_tagName=/(?<=<[\/\s]*)\w+(?=(\s+(?![\s=])|>))/;
const reg_tagAttrs=/(?<=\s)[\w:\.\-@]+(=(["']).*?\2)*/g;
const reg_tagAttrDatas=/(^[^=]+|(?<=(['"])).*?(?=\2))/g;
const regMap=new Map();
regMap.set("element", /^<[^\/\!]((["'])+.*?\2|[^>])+>/);
regMap.set("elementEnd", /<\/.*?>/);
regMap.set("note", /<\!--.*?-->/is);
regMap.set("declare", /<!doctype.*?>/i);
regMap.set("text", /^[^<>]+/);
/**
* 返回Json語法樹
* @param {父節點名稱} name
* @param {被解析的html} htmlContent
* @param {節點集合} nodes
*/
const toJson=(name, htmlContent, nodes)=> {
regMap.forEach((value, key)=> {
if (key !=="elementEnd") {
let res=regFirstResult(value, htmlContent);
if (res.length) {
htmlContent=toNext(name, res, key, htmlContent, nodes);
}
}
});
// 處理同級
let res=regFirstResult(regMap.get("element"), htmlContent);
if (res.length) return toJson(name, htmlContent, nodes);
return htmlContent;
};
/**
* 下一匹配
* @param {父節點名稱} name
* @param {匹配結果} parseRes
* @param {匹配類型} nodeType
* @param {被解析的html} htmlContent
* @param {節點集合} nodes
* @returns
*/
const toNext=(name, parseRes, nodeType, htmlContent, nodes)=> {
if (nodeType=="elementEnd")
return parseElementEnd(name, parseRes, nodeType, htmlContent, nodes);
if (nodeType=="element")
return parseElement(name, parseRes, nodeType, htmlContent, nodes);
return parseText(name, parseRes, nodeType, htmlContent, nodes);
};
const nodes=[];
toJson("", strHtml, nodes);
console.log(JSON.stringify(nodes));
結果圖
了解或者使用Svelte、Angular、Vue、React、Htmx、Qwik、Astro、Web Component等等技術,AST似乎無處不在。
所以一起重復造輪子吧。
PrvtCMS模板在線管理、支持實時預覽、跨模板、跨組件引用等。能實現這些功能的基礎就是寫了一個HTML語法樹。是的,重復造輪子。
功能截圖
……思考中……
人人為我,我為人人,歡迎您的瀏覽,我們一起加油吧。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。