學習網頁的概念和分類,了解靜態網頁和動態網頁的不同;了解網頁瀏覽器的工作原理。了解HTML,XHTML,HTML5的概念,制作簡單的HTML頁面的開發。
可以在internet上通過網頁瀏覽信息,如新聞,圖片等,還可發布信息,如招聘信息等,網頁是在某個地方某一臺計算機上的一個文件。
網頁主要由3部分組成:結構,表現,行為。
靜態網頁的特點是不論在何時何地瀏覽這個網頁,看到的形式和內容都相同,且只能瀏覽,用戶無法與網站進行互動。靜態頁面由HTML編寫,擴展名一般為.htm, .html, .shtml, .xml等。與動態頁面相比,動態網頁是以.asp, .jsp, .php, .perl, .cgi等形式為后綴。
動態網頁指網頁的內容可以根據某種條件而自動改變。
采用B/S結構,即瀏覽器/服務器結構,用戶工作界面是通過www瀏覽器來實現的:
瀏覽器的工作原理:
www的基礎是HTTP協議,web瀏覽器就是用于通過url來獲取并顯示web網頁的一種軟件工具,url用于指定要取得的Internet上資源的位置與方式。
HTML是一種用來制作超文本文檔的簡單標記語言,用其編寫的超文本文檔稱為HTML文檔,它能獨立于各種操作系統平臺。
可擴展超文本標記語言XHTML:
XHTML是不需要編譯,可以直接由瀏覽器執行,是一種增強了的HTML。它的可擴展性和靈活性將適應未來網絡應用的更多需求,是基于XML的應用。開發者在HTML4.0的基礎上,用XML的規則對其進行一些擴展,由此得到了XHTML,所以,建立XHTML的目的是為了實現HTML向xml的過渡。
HTML5簡化了:<!DOCTYPE html>,簡化了DOCTYPE,簡化了字符集聲明,以瀏覽器的原生能力替代腳本代碼的實現,簡單而強大的HTML5API。
文件擴展名是操作系統用來標志文件格式的一種機制。擴展名如同文件的身份說明,區別了文件的類別和作用。
HTML網頁的文件后綴名是.html或者.htm.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"xxx">
聲明的作用,告訴瀏覽器所書寫的HTML代碼的版本。
復制代碼
<meta>標簽,是HTML文檔<head>標簽內的一個輔助性標簽,meta標簽分為2個重要的屬性:name和http-equiv,通常用于能夠優化頁面被搜索的可能性。
meta標簽下name屬性的使用:
<head>
<meta name="keywords" content="nine, twenty-three">
<meta name="description" content="...">
<meta name="generator" content="Dreamweaver">
<meta name="author" content="depp">
<meta name="robots" content="all">
</head>
復制代碼
meta標簽下的另一個屬性http-equiv,其作用是反饋給瀏覽器一些明確的信息,幫助瀏覽器更精確地展示頁面。
<head>
<meta http-equiv="content-type" content="text/html; charset=gb2312"/>
</head>
復制代碼
link標簽,定義了一個外部文件的鏈接,經常被用于鏈接外部css樣式。
base標簽為整個頁面定義了所有鏈接的基礎定位,其主要的作用是確保文檔中所有的相對url都可以被分解成確定的文檔地址。
style標簽用于定義css的樣式。表明了在頁面中引入一個.style的樣式表。
script標簽用于定義頁面內的腳本。
titl標題標簽,body體標簽.
一個好的HTML文檔應具備以下3個方面:
<br>..</br>
<p>...</p>
復制代碼
<p align=left>...</p>
<p align=center>...</p>
<p align=right>...</p>
復制代碼
給文本加標注:<acronym title="">...</acronym>注釋的內容放在title屬性后的引號中,被注釋的內容放在標簽內。
無序列表:ul,li,有序列表:ol li
定義列表:
<dl>
<dt>...</dt>
<dd>...</dd>
<dt>...</dt>
<dd>...</dd>
</dl>
復制代碼
所以總的來說:jepg可以壓縮圖像的容量,png的質量較好,gif可以做動畫。
矢量圖
說說矢量圖和位圖最大的區別:
無論是否對圖像進行縮放,都不會影響矢量圖的效果,但會影響圖的質量。
設計者一般只愿意將logo,ui圖標,標識符號等簡單圖像存為矢量圖。
圖像的分辨率
分辨率的單位是dpi即每英寸顯示的線數。通常所指的分辨率有兩種,屏幕分辨率和圖片分辨率,屏幕分辨率即計算機顯示器默認的分辨率。
一般目前大部分顯示器的分辨率是1024px x 768px,圖片分辨率定義是用于量度位圖圖像內數據量多少的一個參數。
分辨率越高的圖像,包含的數據越多,圖像的容量就越大,會消耗更多的計算機資源,需要更大的存儲空間。
分辨率指的是每英寸的像素值,通過像素和分辨率的換算可以測算圖片的長度。
頁面中的圖像
<img src=... alt=.../>
復制代碼
<img style="vertial-align:text-top"/>
復制代碼
<img style="vertical-align:middle"/>
復制代碼
<img style="vertical-align:text-bottom"/>
復制代碼
<img style="vertical-alignbaseline"/>
復制代碼
hspace=30px表示圖像左,右兩邊與頁面其他內容隔30px的距離。vspace=30px表示圖像上,下兩邊與頁面的其他內容的間隔距離是30px。
<img src="" widht="" height="">
<img src="..." border=>
<hr align=".." width="..." size="...">
<a href="鏈接對象的路徑">鏈接錨點對象</a>
復制代碼
把郵箱留給需要聯系你的人
<a href="mailto:郵箱地址">鏈接錨點對象</a>
復制代碼
dashed 虛線
double 雙線
groove 槽線
inset 內陷
outset 外陷
復制代碼
熱點圖像區域的鏈接
map標簽:
<map id=...>
<area shape="..." coords="..." href="...">
</map>
復制代碼
shape屬性,用于確定選區的形狀,rect矩形,circle圓形,poly多邊形。href屬性,就是超鏈接。coords屬性,用于控制形狀的位置,通過坐標來找到這個位置。
計算矩形的面積
<html>
<head>
<title>計算矩形的面積</title>
<style type="text/css">
.result {font-weight:bold;}
</style>
<script language="JavaScript">
function calculate() {
var length=document.data.length.value;
var width=document.data.width.value;
var height=document.data.height.value;
var area=document.getElementById('area');
area.innerHTML=length*widht;
volume.innerHTML=length*widht*height;
}
</script>
復制代碼
<form action="my.php"></form>
復制代碼
它表明了這是一個表單,其作用是提交my.php頁面中的數據。
<form name="data">
復制代碼
原理:在客戶端接收用戶的信息,然后將數據遞交給后臺的程序來操控這些數據。
<script language="JavaScript">
復制代碼
如果通過引用外部javascript程序,就像鏈接外聯樣式:
<script type="text/javascript" src="dada.js"></script>
復制代碼
<form action="da.php"></form>
復制代碼
提交方式用get,表單域中輸入的內容會添加在action指定的url中,當表單提交之后,用戶會獲取一個明確的url。get在安全性上較差,所有表單域的值直接呈現。post除了有可見的處理腳本程序,別的東西都可以隱藏。
<form name="dada">
復制代碼
<form action="mailto:da@qq.com" method="post" name="dada"
enctype="text/plain" target="_blank"></form>
復制代碼
是指用戶輸入數據的地方,表單域可分為3個對象,input, textarea, select。
input對象下的多種表單的表現形式。
<input name="" type="" value="" size="" maxlength="">
復制代碼
<form action="" method="post">
<input name="name" type="text" size="20" maxlength="12">
</form>
<input name="secret" type="password" size="20" maxlength="20">
<input name="one" type="radio" value="one" checked="checked">
<input name="one" type="radio" value="two">
<input type="submit" value="確定">
<input type="reset" value="恢復">
復制代碼
創建submit按鈕或reset按鈕時,name屬性不是必需的。
使用hidden來記錄頁面的數據并將它隱藏起來,用戶對這些數據通常并不關心,但是必須提交數據。
<form action=da.asp>
<input type=hidden name=somehidden value=dada>
<input type=submit value=下一頁>
</form>
復制代碼
image樣式的表單
<input type="image" src="圖片/小圖標.jpg" alt="確定">
復制代碼
file上傳文件的樣式表單
file樣式表單允許用戶上傳自己的文件
<html>
<head>
<title>file樣式的表單</title>
<style type="text/css">
body {font:120% 微軟雅黑;}
input {font:100% 微軟雅黑;}
</style>
</head>
上傳我的文件:
<form action="..." method="post" enctype="multipart/form-data">
<input type="file" name="uploadfile" id="uploadfile"/>
</form>
</body>
</html>
復制代碼
textarea對象的表單
textarea對象的表單
<html>
<head>
<title>file樣式的表單</title>
<style type="text/css">
body{font:120% 微軟雅黑;}
textarea{font:80% 微軟雅黑;color:navy;}
</style>
</head>
<body>
留言板
<form action="..." method="post" enctype="multipart/form-data">
<textarea name="dada" rows="10" cols="50" value="dada">請說:</textarea>
</form>
</body>
</html>
復制代碼
select對象的表單
select對象的表單
<form action="">
地址:
<select name="da1">
<option>1</option>
</select>
</form>
復制代碼
使用optgroup標簽配合label屬性來給選項分類:
<select name="上海">
<optgroup label="da1">
<option>1</option>
</optgroup>
<optgroup label="da2">
<option>2</option>
</optgroup>
</select>
復制代碼
在select標簽中加入size屬性即可,如size=6表示是一個能容納6行文字的文本框,超出設置的行數時,將出現滾動條。
<select name="上海" size="6">
復制代碼
表單域集合:表單域的代碼由fieldset標簽和legend標簽組合而成。
<form action="..." method="post">
<fieldset>
<legend>注冊信息:</legend>
輸入用戶名:<input name="name" type="text" size="20" maxlength="12">
</fieldset>
</form>
復制代碼
表單輸入類型
<input type="url" name="webUrl" id="webUrl" value="http://wwwxxx"/>
復制代碼
<input type="email" name="dada" id="dada" value="23@qq.com"/>
復制代碼
<input type="range" name="volume" id="volume" min="0" max="1" step="0.2"/>
復制代碼
<input type="number" name="score" id="score" min="0" max="10" step="0.5"/>
復制代碼
增加表單的特性以及元素
<input name="name" type="text" form="form1" required/>
<form id="form1">
<input type="submit" value="提交"/>
</form>
復制代碼
<form id="form1" method="post">
<input name="name" type="text" form="form1"/>
<input type="submit" value="提交到page1" formaction="?page=1”/>
<input type="submit" value="提交到page2" formaction="?page=2"/>
<input type="submit" value="提交"/>
</form>
復制代碼
placeholder特性
<input name="name" type="text" placeholder="請輸入關鍵詞"/>
復制代碼
autofocus特性:用于當頁面加載完成時,可自動獲取焦點,每個頁面只允許出現一個有autofocus特性的input元素。
<input name="key" type="text" autofocus/>
復制代碼
autocomplete特性用于form元素和輸入型的Input元素,用于表單的自動完成。
input name="key" type="text" autocommplete="on"/>
復制代碼
autocomplete特性有三個值,可以指定"on","off"和""不指定,不指定就將使用瀏覽器的默認設置。
<input name="email" type="email" list="emaillist"/>
<datalist id="emaillist">
<option value="23#qq.com">xxxx</option>
</datalist>
復制代碼
keygen元素提供一個安全的方式來驗證用戶。
<form action="">
<input type="text" name="name"/><br>
<keygen name="security"/>
<br><input type="submit"/>
</form>
復制代碼
<form oninput="x.value=dada.value">
<input type="range" name="volume" value="50"/>
<output name="x"></output>
</form>
復制代碼
為某個表單內部的元素設置了required特性,那么這項的值不能為空,否則無法提交表單。
<input name="name" type="text" placeholder="dada" required/>
復制代碼
<input name="code" type="text" value="" pattern="[0-9]{6}" placeholder="da"/>
復制代碼
<input type="range" name="dada" id="dada" min="0" max="1" step="0.2"/>
復制代碼
<form action="dada.asp" novalidate="novalidate">
<input type="email" name="user_email"/>
<input type="submit"/>
</form>
復制代碼
var validityState=document.getElementById("username").validity;
復制代碼
var willValidate=document.getElementById("username").willValidate;
復制代碼
var validationMessage=document.getElementById("username").validationMessage;
復制代碼
好了各位,以上就是這篇文章的全部內容,能看到這里的人都是人才。我后面會不斷更新技術相關的文章,如果覺得文章對你有用,歡迎給個“贊”,也歡迎分享,感謝大家 ??!
前后端分離已成為互聯網項目開發的業界標準使用方式,通過nginx+tomcat的方式(也可以中間加一個nodejs)有效的進行解耦,并且前后端分離會為以后的大型分布式架構、彈性計算架構、微服務架構、多端化服務(多種客戶端,例如:瀏覽器,車載終端,安卓,IOS等等)打下堅實的基礎。這個步驟是系統架構從猿進化成人的必經之路。
核心思想:前端html頁面通過ajax調用后端的restuful api接口并使用json數據進行交互。
在互聯網架構中,
web服務器:一般指像nginx,apache這類的服務器,他們一般只能解析靜態資源。
應用服務器:一般指像tomcat,jetty,resin這類的服務器可以解析動態資源也可以解析靜態資源,但解析靜態資源的能力沒有web服務器好。
一般都是只有web服務器才能被外網訪問,應用服務器只能內網訪問。
以前的JavaWeb項目大多數都是java程序員又當爹又當媽,又搞前端(ajax/jquery/js/html/css等等),又搞后端(java/mysql/oracle等等)。
隨著時代的發展,漸漸的許多大中小公司開始把前后端的界限分的越來越明確,前端工程師只管前端的事情,后端工程師只管后端的事情。正所謂術業有專攻。
對于后端java工程師:
把精力放在java基礎,設計模式,jvm原理,spring+springmvc原理及源碼,linux,mysql事務隔離與鎖機制,mongodb,http/tcp,多線程,分布式架構(dubbo,dubbox,spring cloud),彈性計算架構,微服務架構(springboot+zookeeper+docker+jenkins),java性能優化,以及相關的項目管理等等。
后端追求的是:三高(高并發,高可用,高性能),安全,存儲,業務等等。
對于前端工程師:
把精力放在html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多線程,模塊化,面向切面編程,設計模式,瀏覽器兼容性,性能優化等等。
前端追求的是:頁面表現,速度流暢,兼容性,用戶體驗等等。
通常我們的JavaWeb項目都是使用了若干后臺框架,springmvc/struts + spring + spring jdbc/hibernate/mybatis 等等。大多數項目在java后端都是分了三層,控制層(controller/action),業務層(service/manage),持久層(dao)??刂茖迂撠熃邮諈?,調用相關業務層,封裝數據,以及路由&渲染到jsp頁面。然后jsp頁面上使用各種標簽(jstl/el/struts標簽等)或者手寫java表達式(<%=%>)將后臺的數據展現出來,玩的是MVC那套思路。緊接著系統發布,你需要用maven或者eclipse等工具把你的代碼打成一個war包,然后把這個war包發布到你的生產環境下的web容器(tomcat/jboss/weblogic/websphere/jetty/resin)里,對吧?發布完了之后,你要啟動你的web容器,開始提供服務,這時候你通過配置域名,dns等等相關,你的網站就可以訪問了。這樣一來,你的前后端代碼全都在那個war包里了,包括你的js,css,圖片,各種第三方的庫。
在瀏覽器中輸入你的網站域名(www.xxx.com),之后發生了什么?瀏覽器通過域名,再通過dns服務器找到你的服務器外網ip,將http請求發送到你的服務器,在tcp3次握手之后(http下面是tcp/ip),通過tcp協議開始傳輸數據,你的服務器得到請求后,開始提供服務,接收參數,之后返回你的應答給瀏覽器,瀏覽器再通過content-type來解析你返回的內容,呈現給用戶。
我們先假設你的首頁中有100張圖片,此時,用戶的看似一次http請求,其實并不是一次,用戶在第一次訪問的時候,瀏覽器中不會有緩存,你的100張圖片,瀏覽器要連著請求100次http請求(有人會跟我說http長連短連的問題,不在這里討論),你的服務器接收這些請求,都需要耗費內存去創建socket來玩tcp傳輸(消耗你服務器上的計算資源)。這樣的話,你的服務器的壓力會非常大,因為頁面中的所有請求都是只請求到你這臺服務器上,如果1個人還好,如果10000個人并發訪問呢(先不聊服務器集群,這里就說是單實例服務器),那你的服務器能扛住多少個tcp連接?你的帶寬有多大?你的服務器的內存有多大?你的硬盤是高性能的嗎?你能抗住多少IO?你給web服務器分的內存有多大?會不會宕機?
這就是為什么,越是大中型的web應用,他們越是要解耦。
理論上你可以把你的數據庫+應用服務+消息隊列+緩存+用戶上傳的文件+日志+等等都扔在一臺服務器上,你也不用玩什么服務治理,也不用做什么性能監控,什么報警機制等等。但是這樣把雞蛋都放在一個籃子里,隱患非常大。如果因為一個子應用的內存不穩定導致整個服務器內存溢出而hung住,那你的整個網站就掛掉了。
JSP的痛點:
以前的javaWeb項目大多數使用jsp作為頁面層展示數據給用戶,因為流量不高,因此也沒有那么苛刻的性能要求,但現在是大數據時代,對于互聯網項目的性能要求是越來越高。
1.動態資源和靜態資源全部耦合在一起,服務器壓力大,因為服務器會收到各種http請求,例如css的http請求,js的,圖片的等等。一旦服務器出現狀況,前后臺一起玩完,用戶體驗極差。
2.UI出好設計圖后,前端工程師只負責將設計圖切成html,需要由java工程師來將html套成jsp頁面,出錯率較高,修改問題時需要雙方協同開發,效率低下。
3.jsp必須要在支持java的web服務器里運行(例如tomcat,jetty,resin等),無法使用nginx等(nginx據說單實例http并發高達5w,這個優勢要用上),性能提不上來。
4.第一次請求jsp,必須要在web服務器中編譯成servlet,第一次運行會較慢。
5.每次請求jsp都是訪問servlet再用輸出流輸出的html頁面,效率沒有直接使用html高。
6.jsp內有較多標簽和表達式,前端工程師在修改頁面時會遇到很多痛點。
7.如果jsp中的內容很多,頁面響應會很慢,因為是同步加載。
8.需要前端工程師使用java的ide(例如eclipse),以及需要配置各種后端的開發環境,你們有考慮過前端工程師的感受嗎。
基于上述的一些痛點,我們應該把整個項目實現前后端真正的解耦!
前后分離的優勢:
1.可以實現真正的前后端解耦,前端服務器使用nginx。
前端/WEB服務器放的是css,js,圖片等等一系列靜態資源(甚至你還可以css,js,圖片等資源放到特定的文件服務器,例如阿里云的oss,并使用cdn加速),前端服務器負責控制頁面引用&跳轉&路由,前端頁面異步調用后端的接口,后端/應用服務器使用tomcat(把tomcat想象成一個數據提供者),加快整體響應速度。
(這里需要使用一些前端工程化的框架比如nodejs,react,router,react,redux,webpack)
2.發現bug,可以快速定位是誰的問題,不會出現互相踢皮球的現象。
頁面邏輯,跳轉錯誤,瀏覽器兼容性問題,腳本錯誤,頁面樣式等問題,全部由前端工程師來負責。
接口數據出錯,數據沒有提交成功,應答超時等問題,全部由后端工程師來解決。
雙方互不干擾,前端與后端是相親相愛的一家人。
3.在大并發情況下,可以同時水平擴展前后端服務器,比如淘寶的一個首頁就需要2000+臺前端服務器做集群來抗住日均多少億+的日均pv。
4.減少后端服務器的并發/負載壓力
除了接口以外的其他所有http請求全部轉移到前端nginx上,接口的請求調用tomcat,參考nginx反向代理tomcat。
且除了第一次頁面請求外,瀏覽器會大量調用本地緩存。
5.即使后端服務暫時超時或者宕機了,前端頁面也會正常訪問,只不過數據刷不出來而已。
6.也許你也需要有微信相關的輕應用,那樣你的接口完全可以共用,如果也有app相關的服務,
那么只要通過一些代碼重構,也可以大量復用接口,提升效率。(多端應用)
7.頁面顯示的東西再多也不怕,因為是異步加載。
8.nginx支持頁面熱部署,不用重啟服務器,前端升級更無縫。
9.增加代碼的維護性&易讀性(前后端耦在一起的代碼讀起來相當費勁)。
10.提升開發效率,因為可以前后端并行開發,而不是像以前的強依賴。
11.在nginx中部署證書,外網使用https訪問,并且只開放443和80端口,其他端口一律關閉(防止黑客端口掃描),內網使用http,性能和安全都有保障。
12.前端大量的組件代碼得以復用,組件化,提升開發效率,抽出來!
總結一下新的方式的請求步驟:
大量并發瀏覽器請求--->web服務器集群(nginx)--->應用服務器集群(tomcat)--->文件/數據庫/緩存/消息隊列服務器集群
同時又可以玩分模塊,還可以按業務拆成一個個的小集群,為后面的架構升級做準備。
擊上方 關注訂閱黑碼教主獲取更多精彩內容
在多重嵌套循環的程序上,如果能分出出多個獨立循環也比嵌套在一個循環體內來的更有益。
優化循環的3種方式:減少每次迭代的開銷、減少迭代的次數或者重新設計應用程序。
在測試的時候僅可能模擬真實環境:如低端機器和低速網絡。
?
對于連續頁面之間的差別很小的應用而言,使用Ajax技術能帶來顯著的改善。
?
在HTML頁面完成展現之后,動態改變頁面元素或調整CSS樣式都會引起瀏覽器重繪,性能的損耗直接取決于動態改變的范圍:如果只是改變一個元素的顏色之類的信息則只會重繪該元素;而如果是增刪節點或調整節點位置則會引起其兄弟節點也一并重繪。
減少重繪并不是說不要重繪,而是要注意重繪范圍:
以改變一個<a>標簽的背景色、寬度和顏色為例。
<a href="javascript:void(0);" id="example">傳統的代碼</a> <script> var example=document.getElementById("example"); example.ondblclick=function() { example.style.backgroundColor="red"; example.style.width="200px"; example.style.color="white"; } </script>
以上會執行3次重繪,而通過CSS代替javascript多次執行則只進行一次重繪。
<style> .dblClick { width: 200px; background: red; color: white; } </style> <a href="javascript:;" id="example">CSS優化的代碼</a> <script> var example=document.getElementById("example"); example.ondblclick=function() { example.className="dblClick"; } </script>
當瀏覽器在解析常規的script標簽時,它需要等待script下載完畢,再解析執行,而后續的HTML代碼只能等待。CSS文件引入要放在頭部,因為這是HTML渲染必備元素。
?
為了避免阻塞加載,應把腳本放到文檔的末尾,而CSS是需要放在頭部的!
<head> <link rel="stylesheet" href="common.css"> ...... <script src="example.js"></script> </body>
深層級嵌套的節點在初始化構建時往往需要更多的內存占用,并且在遍歷節點時也會更慢些,這與瀏覽器構建DOM文檔的機制有關。瀏覽器會把整個HTML文檔的結構存儲為DOM“樹”結構。當文檔節點的嵌套層次越深,構建的DOM樹層次也會越深。
如下代碼,完全能夠去掉
或其中一個標簽。<div> <span> <label>嵌套</label> </span> </div>
頁面緩存
通常不設置緩存的情況下,每次刷新頁面都會重新讀取服務器的文件,而如果設置緩存之后,所有文件都可以從本地取得,這樣明顯極大提高了頁面效率。
我們可以通過設置頁面頭的expires來定義頁面過期時間,將過期時間定久一點就達到了“永久”緩存。
<meta http-equiv="expires" content="Sunday 26 October 2099 01:00 GMT" />
當然,如果你的項目代碼有變更,因為客戶端緩存了文件就得不到最新的文件,勢必造成顯示錯誤?;谶@個問題的解決方案就是給鏈接文件加一個時間戳,如果時間戳有變化,瀏覽器會認為是新文件,就會向服務器請求最新文件。
<script src="example2014-6-17.js"></script> //如果是JSP,可以用EL表達式來取時間戳信息,這樣管理更加方便 <script src="example${your time param}.js"></script> //或者這樣的寫法更優秀: <script src="example.js?time=2014-6-7"></script> <script src="example.js?time=${your time param}"></script>
所有涉及到請求數據的文件盡量做壓縮,比如Javascript文件、css文件及圖片文件,特別是圖片文件,如果沒有高清晰要求,完全可以壓縮后再使用。
數量少體積大的文件要比數量多體積小的文件加載速度快,所以有時候可以考慮將多個js文件、多個css文件合并在一起。
除此之外減少HTML文檔大小還可以采取下面幾種方法:
圖像合并其實就是把網頁中一些背景圖片整合到一張圖片文件中,再利用CSS 的“background-image”,“background- repeat”,“background-position”的組合進行背景定位,background-position可以用數字能精確的定位出背景圖片的位置。
一個頁面要用到多個圖標,完全可以將多個圖標合并成一個圖,然后只需要發一次圖片請求,通過css定位分割圖標即可。
使用iframe并不會增加同域名下的并行下載數,瀏覽器對同域名的連接總是共享瀏覽器級別的連接池,在頁面加載過程中iframe元素還會阻塞父文檔onload事件的觸發。并且iframe是html標簽中最消耗資源的標簽,它的開銷比DIV、SCRIPT、STYLE等DOM高1~2個數量級。
避免onload事件被阻塞,可使用JavaScript動態的加載iframe元素或動態設置iframe的src屬性(但其僅在高級瀏覽器IE9及以上有效)。
<iframe id="if"></iframe> document.getElementById("if").setAttribute("src","url");
一般來說,瀏覽器對于相同域名的圖片,最多用2-4個線程并行下載(不同瀏覽器的并發下載數是不同的)。而相同域名的其他圖片,則要等到其他圖片下載完后才會開始下載。
有時候,圖片數據太多,一些公司的解決方法是將圖片數據分到多個域名的服務器上,這在一方面是將服務器的請求壓力分到多個硬件服務器上,另一方面,是利用了瀏覽器的特性。(大家可以去新浪、騰訊門戶網站查看,這些大型站點同一頁面加載的圖片可能由多個站點提供)
注:一個HTML請求的域名也不要太多(2~3個差不多),多了可能造成不同服務器連接時間差異,反而影響速度。
如<img src=""><a href="">這樣的設置方式是非常不可取的,即使鏈接為空,在舊的瀏覽器也會以固定步驟發送請求信息。
另外<a href="#"></a>也不可取,最好的方式是在鏈接中加一個空的js代碼<a href="javascript:void();"></a>
base64是一串字符串,他可以代表一個圖片的所有信息,也就是可以通過
(S表示一串base64碼)來顯示圖片,這種方式不需要再向服務器發送請求,完全由瀏覽器解析成圖片。
目前高級瀏覽器都支持此功能,但要注意兩點:
如果HTML里的圖片沒有指定尺寸(寬和高),或者代碼描述的尺寸與實際圖片的尺寸不符時,瀏覽器則要在圖片下載完成后再“回溯”該圖片并重新顯示,這會消耗額外時間。
<iframe id="if"></iframe> document.getElementById("if").setAttribute("src","url");
如果瀏覽器不能獲知頁面的編碼字符集,一般都會在執行腳本和渲染頁面前,把字節流緩存,然后再搜索可進行解析的字符集,或以默認的字符集來解析頁面代碼,這會導致消耗不必要的時間。
<iframe id="if"></iframe> document.getElementById("if").setAttribute("src","url");
漸進式增強設計的通俗解釋就是:首先寫一段滿足所有瀏覽器的基本樣式,再在后面針對不同高級瀏覽器編寫更漂亮的樣式
如下代碼,所有瀏覽器都支持background-color: #2067f5;滿足了瀏覽器基本現實需求,而后面的background-image: -webkit-gradient等則為不同高級瀏覽器使用,只要瀏覽器識別就能執行這段代碼(不識別,CSS也不會報錯只會直接忽略)。
<div class="someClass"></div> .someClass { width: 100px; height: 100px; background-color: #2067f5; background-image: -webkit-gradient(linear, left top, left bottom, from(#2067f5), to(#154096)); background-image: -webkit-linear-gradient(top, #2067f5, #154096); background-image: -moz-linear-gradient(top, #2067f5, #154096); background-image: -ms-linear-gradient(top, #2067f5, #154096); background-image: -o-linear-gradient(top, #2067f5, #154096); background-image: linear-gradient(to bottom, #2067f5, #154096); }
預加載和懶加載,是一種改善用戶體驗的策略,它實際上并不能提高程序性能,但是卻可以明顯改善用戶體驗或減輕服務器壓力。
預加載表示當前用戶在請求到需要的數據之后,頁面自動預加載下一次用戶可能要看的數據,這樣用戶下一次操作的時候就立刻呈現,依次類推。
懶加載表示用戶請求什么再顯示什么,如果一個請求要響應的時間非常長,就不推薦懶加載。
當一個頁面非常大,內容非常多,可以采用flush的形式分部分返回給頁面,這樣能告訴用戶我正在工作,顯示一部分內容比白屏等很長時間要好得多。在Java Web技術中,實現Flush非常簡單,只要調用 HttpServletResponse.getWriter輸出流的flush方法,就可以將已經完成加載的內容寫回給客戶端。
這種方式只適用于返回數據特別多、請求時間特別長的情況,常規數據還是用正常的實時全部返回最佳。這種實現方式實際會增加瀏覽器渲染時間和用戶整體等待時間,但從用戶體驗上會更加優秀。
所謂的CDN,就是一種內容分發網絡,它采用智能路由和流量管理技術,及時發現能夠給訪問者提供最快響應的加速節點,并將訪問者的請求導向到該加速節點,由該加速節點提供內容服務。
通俗點說,你在成都(瀏覽器)購買了北京賣家(服務器)的產品,北京賣家通過快遞(CDN服務)寄送包裹,從北京到成都可以走路、坐汽車、火車或飛機,而采用CND的快遞會選擇飛機直達,因為這種寄送方式最快。
當然使用CDN有兩個注意事項:
瀏覽器緩存帶來的性能提升已經眾人皆知了,而很多人卻并不知道瀏覽器的緩存過期時間、緩存刪除、什么頁面可以緩存等,都可以由我們程序員來控制,只要您熟悉HTTP協議,就可以輕松的控制瀏覽器。
所謂的動靜分離,就是將Web應用程序中靜態和動態的內容分別放在不同的Web服務器上,有針對性的處理動態和靜態內容,從而達到性能的提升。我們知道如果一個HTML有多個域名請求數據文件會提高
Tomcat服務器在處理靜態和并發問題上比較弱,所以事先動靜分離的方式一般會用Apache+Tomcat、Nginx+Tomcat等。
以Apache+Tomcat為例,其運行機理是:頁面請求首先給Apache,然后Apache分析請求信息是靜態還是動態,靜態則本機處理,動態則交給Tomcat做處理。
這其實是負載均衡的雛形,這樣的實現不用讓開發人員做任何特殊開發,一個
交給服務器即可,至于這個文件是從Apache還是從Tomcat取得,開發人員完全無需關注。
持久連接(Keep-Alive)也叫做長連接,它是一種TCP的連接方式,連接會被瀏覽器和服務器所緩存,在下次連接同一服務器時,緩存的連接被重新使用。HTTP無狀態性表示了它不屬于長連接,但HTTP/1.1提供了對長連接的支持(不過這必須依賴瀏覽器和服務器雙方均支持長連接功能才行),最常見的HTTP長連接例子是“斷點下載”。
瀏覽器在請求的頭部添加 Connection:Keep-Alive,以此告訴服務器“我支持長連接,你支持的話就和我建立長連接吧”,而倘若服務器的確支持長連接,那么就在響應頭部添加“Connection:Keep-Alive”,從而告訴瀏覽器“我的確也支持,那我們建立長連接吧”。服務器還可以通過Keep-Alive:timeout=..., max=...的頭部告訴瀏覽器長連接失效時間。
配置長連接通常是要服務器支持設置,有測試數據顯示,使用長連接和不使用長連接的性能對比,對于Tomcat配置的maxKeepAliveRequests為50來說,效率竟然提升了將近5倍。
HTTP協議支持GZIP的壓縮格式,當服務器返回的HTML信息報頭中包含Content-Encoding:gzip,它就告訴瀏覽器,這個響應的返回數據已經壓縮成GZIP格式,瀏覽器獲得數據后要進行解壓縮操作,一定程度上減輕了服務器傳輸數據的壓力。
很多服務器已經支持通過配置來自動將HTML信息壓縮成GZIP,比如tomcat、又比如很火的Nginx。如果無法配置服務器級別的GZIP壓縮機制,可以改為程序壓縮。
// 監視對 gzipCategory 文件夾的請求 @WebFilter(urlPatterns={ "/gzipCategory/*" }) public class GZIPFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String parameter=request.getParameter("gzip"); // 判斷是否包含了 Accept-Encoding 請求頭部 HttpServletRequest s=(HttpServletRequest)request; String header=s.getHeader("Accept-Encoding"); //"1".equals(parameter) 只是為了控制,如果傳入 gzip=1,才執行壓縮,目的是測試用 if ("1".equals(parameter) && header !=null && header.toLowerCase().contains("gzip")) { HttpServletResponse resp=(HttpServletResponse) response; final ByteArrayOutputStream buffer=new ByteArrayOutputStream(); HttpServletResponseWrapper hsrw=new HttpServletResponseWrapper( resp) { @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(new OutputStreamWriter(buffer, getCharacterEncoding())); } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public void write(int b) throws IOException { buffer.write(b); } }; } }; chain.doFilter(request, hsrw); byte[] gzipData=gzip(buffer.toByteArray()); resp.addHeader("Content-Encoding", "gzip"); resp.setContentLength(gzipData.length); ServletOutputStream output=response.getOutputStream(); output.write(gzipData); output.flush(); } else { chain.doFilter(request, response); } } // 用 GZIP 壓縮字節數組 private byte[] gzip(byte[] data) { ByteArrayOutputStream byteOutput=new ByteArrayOutputStream(10240); GZIPOutputStream output=null; try { output=new GZIPOutputStream(byteOutput); output.write(data); } catch (IOException e) { } finally { try { output.close(); } catch (IOException e) { } } return byteOutput.toByteArray(); } …… }
如果你覺得本篇還不錯,請點贊關注!
文字由黑碼教主創作,配圖源于網絡,版權歸原作者所有,如有侵權聯系刪除!
你有更好的網站性能優化方案嗎?
歡迎留言分享。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。