這個信息爆炸的時代,使用移動終端獲取新鮮信息已經是大勢所趨,但是移動網頁瀏覽速度還有巨大的提升空間。據 Strangeloop Networks 統計,在同樣的網絡條件下,使用移動端訪問相同網頁平均會比 PC 端慢40%!然而另一方面,用戶對網速的要求卻步步緊逼。研究表明,網頁響應時間可容忍的閥值是2秒,一旦超過3秒,會有40%的用戶放棄瀏覽頁面。
所謂天下武功,唯快不破!想要設計更快的網頁優化速度,我們可以借鑒成功的優化經驗,全球最大的CDN服務商Akamai(阿卡邁)針對移動體驗的問題,提供了一套較為完整的解決方案,感興趣的讀者可以前往注冊下載;與此同時,我們也可以采用直接的技術手段,本文從PC端優化經驗、HTTP/2優化協議、優化蜂窩網絡、以及智能的加載方案設計四個維度,總結了一些提升移動網頁加載速度的方法和技巧。
一、PC 端網站優化方案
不論在 PC 還是在移動瀏覽器上,只有不到10%的時間是用來讀取頁面的 HTML 的。剩下的90%是用來加載額外的如樣式表、腳本文件、或者圖片這樣的資源和執行客戶端的程序。因此,許多在 PC 端的傳統網頁優化方案在移動端仍然可行。比如說:
1.1 減少每個頁面的 HTTP 請求數
I. 將共用的 JavaScript 和 CSS 代碼放在公共的文件夾中與多個頁面共享。
II. 確保在一個頁面中相同的腳本不會被加載多次。同時,將腳本中的 Click 事件改為 On Touch 事件來減少固有的300ms延遲。
III. 使用 CSS Sprites 來整合圖像,將多張圖片整合到一個線性的網狀的大圖片中。
IV. 使用 Cache-Control 或者 Expires 標記來實現瀏覽器緩存,從而減少不必要的服務器請求,盡可能地從本地緩存中獲取資源。
1.2 減少每個請求加載的大小
I. 使用 gzip 這樣的壓縮技術來壓縮圖像和文本,依靠增加服務端壓縮和瀏覽器解壓的步驟,來減少資源的負載。
II. 整合并壓縮 CSS 與 JavaScript,刪除不必要的字符與變量。
III. 動態地調整圖片大小或者將圖片替換為移動設備專用的更小的版本。
IV. 分段加載和隱藏加載等手段,可以將不可見區域的內容延遲加載或暫時不需要的腳本進行延時讀取
二、采用更優的 HTTP/2 協議
2.1 多路復用技術帶來的請求-響應加速
I. HTTP/2 采用多路復用的技術,允許同時通過單一的 HTTP/2 連接發起多重的請求響應消息,從而大大的加快了網頁加載時間。
2.2 更節省空間的二進制頭部數據嵌套
I. HTTP/2 采用二進制格式傳輸數據,并把他們分割為更小的幀,相比于 HTTP/1.x 的文本格式傳輸更為方便。
II. HTTP1.x 的 header 由于 cookie 和 user agent 很容易膨脹,而且每次都要重復發送。HTTP/2 對消息頭采用 HPACK 進行壓縮傳輸,能夠節省消息頭占用的網絡流量。
2.3 Server Push 帶來的更快的資源推送
I. 通過 Server Push 功能,服務端可以主動把 JS 和 CSS 等文件發送給終端,而省去了解析HTML 請求的過程。簡單的說,當你需要訪問某個文件的時候,它已經在乖乖的在后臺躺好了。
三、優化蜂窩網絡
I.具有實力的內容服務商可以把資源配置在離用戶地理位置更近的地方,縮短最后一公里。
II. 與移動網絡服務商合作共同開發算法,實現實時自動調整互聯網路由,避免網絡擁堵、丟包與離線問題。
III. 還可以采用優化TCP協議的方法,通過借助主流的Cubic、Bic以及Westwood算法,可以有效的避免網絡擁堵。
IV. 此外,還可以研究算法改善NAT嵌套導致的網絡延時,也可以直接通過IPV6的連接協議規避NAT的延遲問題。
四、設計更加智能的加載方案
4.1采用分段加載和隱藏加載
I.分段加載又稱懶加載,它能夠在用戶滾動頁面的時候自動獲取更多的數據,從而可以很大程度上減少服務器端的資源耗用。諸如Lazyload.js或Belazy.js都是非常成熟易用的開發包。
II. 隱藏加載是在頁面顯示后再加載用戶暫時看不到的信息,諸如圖片展示窗里除了第一張圖片,其他圖片都可以采用隱藏加載的技術。
4.2采用預加載技術
I.資源預加載目的是讓瀏覽器在空閑時間下載或預讀取一些文檔資源,用戶在將來將會訪問這些資源時瀏覽器能快速的從緩存里提取給用戶。
II. 預加載技術不僅支持PC,也已經支持Android系統,可惜的是目前尚不支持iOS Safari。
III. 事實上,Prefetch是網頁優化里Prebrowsing的一部分,開發者還可以通過DNS-Prefetch , Subresource,Preconnect,Prerender等技術來實現預先解析DNS與提前渲染等優化。
4.3通過機器學習的手段智能加載
I.通過機器學習的方法,網站可以自動收集并分析用戶的瀏覽習慣與訪問信息,然后通過預加載的手段將最有可能訪問的信息提前加載完成。
4.4智能調整圖片分辨率
I.圖片通常占用了Web頁面加載的大部分網絡資源,也占據了頁面緩存的主要空間。 根據統計,一個站點平均62%的內容都是由圖片組成。管理這些圖片除了需要考慮到圖片的大小、格式、旋轉、藝術處理、增加水印、存儲空間等,還要顧及海量的設備的屏幕尺寸,以及適應終端上運行的瀏覽器。
以上是我們給開發者總結的一些經驗分享,希望能夠對讀者有所幫助,大家也可以注冊下載阿卡邁的技術PPT詳細了解如何通過CDN 的方式為(移動)網頁提速。我們需要明確的是,專注移動網頁的性能優化無疑是開發者需要努力的方向,然而用戶并不等于機器。用戶不關心你的網站發出了多少請求,也不在乎你的屏幕渲染得有多快,他們只關心網站帶給他們體驗上的感覺。因此,開發者在進行技術優化時,不僅僅是在某一技術點上的優化,更需要從網站的整體性能規劃把控,讓整個網站給客戶呈現出更快的加載體驗!
HTTP車是由蒂姆·伯納斯-李( TimBerners—Lee )于1989年在歐洲核子研究組織( CERN )所發起
其中最著名的是 1999 年 6 月公布的 RFC 2616 ,定義了 HTTP 協議中現今廣泛使用的一個版本—— HTTP 1.1
全稱:超文本傳輸協議( HyperText Transfer Protocol )
概念: HTTP 是一種能夠獲取像 HTML 、圖片等網絡資源的通訊協議( protocol )。它是在 web 上進行數據交換的基礎,是一種 client-server 協議
HTTP ——因特網的多媒體信使 ——《HTTP權威指南》。 HTTP 在因特網的角色:充當一個信使的角色,干的就是一個跑腿的活,在客戶端和服務端之間傳遞信息,但我們又不能缺少它。 HTTP 協議是應用層的協議,是與前端開發最息息相關的協議。平時我們遇到的 HTTP 請求、 HTTP 緩存、 Cookies 、跨域等其實都跟 HTTP 息息相關
也就是說, HTTP 依賴于面向連接的 TCP 進行消息傳遞,但連接并不是必須的。只需要它是可靠的,或不丟失消息的(至少返回錯誤)。
HTTP/1.0 默認為每一對 HTTP 請求/響應都打開一個單獨的 TCP 連接。當需要連續發起多個請求時,這種模式比多個請求共享同一個 TCP 鏈接更低效。為此, HTTP 1.1 持久連接的概念,底層 TCP 連接可以通過 connection 頭部實現。但 HTTP 1.1 在連接上也是不完美的,后面我們會提到。
HTTP 的組件系統包括客戶端、 web 服務器和代理
瀏覽器,特殊比如是工程師使用的程序,以及 Web 開發人員調試應用程序
由 Web Server 來服務并提供客戶端所請求的文檔。每一個發送到服務器的請求,都會被服務器處理并返回一個消息,也就是 response
在瀏覽器和服務器之間,有很多計算機和其他設備轉發了 HTTP 消息。它們可能出現在傳輸層、網絡層和物理層上,對于 HTTP 應用層而言就是透明的
有如下的一些作用
HTTP 有兩種類型的消息:
HTTP 消息由采用 ASCII 編碼的多行文本構成的。在 HTTP/1.1 以及更早的版本中,這些消息通過連接公開的發送。在 HTTP2.0 中,消息被分到了多個 HTTP 幀中。通過配置文件(用于代理服務器或者服務器), API (用于瀏覽器)或者其他接口提供 HTTP 消息
HTTP 請求和響應都包括起始行( start line )、請求頭( HTTP Headers )、空行( empty line )以及 body 部分,如下圖所示:
下面詳細說下請求 Path ,請求路徑( Path )有以下幾種:
1)一個絕對路徑,末尾跟上一個 ' ? ' 和查詢字符串。這是最常見的形式,稱為 原始形式 ( origin form ),被 GET , POST , HEAD 和 OPTIONS 方法所使用
POST / HTTP/1.1
GET /background.png HTTP/1.0
HEAD /test.html?query=alibaba HTTP/1.1
OPTIONS /anypage.html HTTP/1.0
復制代碼
2)一個完整的 URL 。主要在使用 GET 方法連接到代理的時候使用
GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1
復制代碼
3)由域名和可選端口(以':'為前綴)組成的 URL 的 authority component ,稱為 authority form 。僅在使用 CONNECT 建立 HTTP 隧道時才使用
CONNECT developer.mozilla.org:80 HTTP/1.1
復制代碼
4)星號形式 ( asterisk form ),一個簡單的星號('*'),配合 OPTIONS 方法使用,代表整個服務器。
OPTIONS * HTTP/1.1
復制代碼
請求 Body 部分: 有些請求將數據發送到服務器以便更新數據:常見的的情況是 POST 請求(包含 HTML 表單數據)。請求報文的 Body 一般為兩類。一類是通過 Content-Type 和 Content-Length 定義的單文件 body 。另外一類是由多 Body 組成,通常是和 HTML Form 聯系在一起的。兩者的不同表現在于 Content-Type 的值。
1) Content-Type —— application/x-www-form-urlencoded 對于 application/x-www-form-urlencoded 格式的表單內容,有以下特點:
I.其中的數據會被編碼成以&分隔的鍵值對
II.字符以URL編碼方式編碼。
// 轉換過程: {a: 1, b: 2} -> a=1&b=2 -> 如下(最終形式)
"a%3D1%26b%3D2"
復制代碼
2) Content-Type —— multipart/form-data
請求頭中的 Content-Type 字段會包含 boundary ,且 boundary 的值有瀏覽器默認指定。例: Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe 。
數據會分為多個部分,每兩個部分之間通過分隔符來分隔,每部分表述均有 HTTP 頭部描述子包體,如 Content-Type ,在最后的分隔符會加上--表示結束。
Content-Disposition: form-data;name="data1";
Content-Type: text/plain
data1
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition: form-data;name="data2";
Content-Type: text/plain
data2
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--
復制代碼
響應 Body 部分:
1)由已知長度的單個文件組成。該類型 body 有兩個 header 定義: Content-Type 和 Content-Length
2)由未知長度的單個文件組成,通過將 Transfer-Encoding 設置為 chunked 來使用 chunks 編碼。
關于 Content-Length 在下面 HTTP 1.0 中會提到,這個是 HTTP 1.0 中新增的非常重要的頭部。
安全方法: HTTP 定義了一組被稱為安全方法的方法。 GET 方法和 HEAD 方法都被認為是安全的,這意味著 GET 方法和 HEAD 方法都不會產生什么動作 —— HTTP 請求不會再服務端產生什么結果,但這并不意味著什么動作都沒發生,其實這更多的是 web 開發者決定的
首先要了解下副作用和冪等的概念,副作用指的是對服務器端資源做修改。冪等指發送 M 和 N 次請求(兩者不相同且都大于 1),服務器上資源的狀態一致。應用場景上,get是無副作用的,冪等的。post 主要是有副作用的,不冪等的情況
技術上有以下的區分:
HTTP Headers
1.通用首部( General headers )同時適用于請求和響應消息,但與最終消息主體中傳輸的數據無關的消息頭。如 Date
2.請求首部( Request headers )包含更多有關要獲取的資源或客戶端本身信息的消息頭。如 User-Agent
3.響應首部( Response headers )包含有關響應的補充信息
4.實體首部( Entity headers )含有關實體主體的更多信息,比如主體長( Content-Length )度或其 MIME 類型。如 Accept-Ranges
詳細的 Header 見 HTTP Headers 集合
HTTP(HyperText Transfer Protocol) 是萬維網( World Wide Web )的基礎協議。 Tim Berners-Lee 博士和他的團隊在 1989-1991 年間創造出它。【HTTP、網絡瀏覽器、服務器】
在 1991 年發布了 HTTP 0.9 版,在 1996 年發布 1.0 版,1997 年是 1.1 版,1.1 版也是到今天為止傳輸最廣泛的版本。2015 年發布了 2.0 版,其極大的優化了 HTTP/1.1 的性能和安全性,而 2018 年發布的 3.0 版,繼續優化 HTTP/2 ,激進地使用 UDP 取代 TCP 協議,目前, HTTP/3 在 2019 年 9 月 26 日 被 Chrome , Firefox ,和 Cloudflare 支持
單行協議,請求由單行指令構成。以唯一可用的方法 GET 開頭。后面跟的是目標資源的路徑
GET /mypage.html
復制代碼
響應:只包括響應文檔本身
<HTML>
這是一個非常簡單的HTML頁面
</HTML>
復制代碼
HTML
RFC 1945 提出了 HTTP1.0 , 構建更好可拓展性
媒體類型是一種標準。用來表示文檔、文件或者字節流的性質和格式。瀏覽器通常使用 MIME ( Multipurpose Internet Mail Extensions )類型來確定如何處理 URL ,因此 Web 服務器在響應頭中配置正確的 MIME 類型會非常的重要。如果配置不正確,可能會導致網站無法正常的工作。 MIME 的組成結構非常簡單;由類型與子類型兩個字符串中間用'/'分隔而組成。
HTTP 從 MIME type 取了一部分來標記報文 body 部分的數據類型,這些類型體現在 Content-Type 這個字段,當然這是針對于發送端而言,接收端想要收到特定類型的數據,也可以用 Accept 字段。
這兩個字段的取值可以分為下面幾類:
- text: text/html, text/plain, text/css 等
- image: image/gif, image/jpeg, image/png 等
- audio/video: audio/mpeg, video/mp4 等
- application: application/json, application/javascript, application/pdf, application/octet-stream
復制代碼
同時為了約定請求的數據和響應數據的壓縮方式、支持語言、字符集等,還提出了以下的 Header
1.壓縮方式:發送端: Content-Encoding (服務端告知客戶端,服務器對實體的主體部分的編碼方式) 和 接收端: Accept-Encoding (用戶代理支持的編碼方式),值有 gzip: 當今最流行的壓縮格式;deflate: 另外一種著名的壓縮格式;br: 一種專門為 HTTP 發明的壓縮算法
2.支持語言: Content-Language 和 Accept-Language (用戶代理支持的自然語言集)
3.字符集:發送端: Content-Type 中,以 charset 屬性指定。接收端: Accept-Charset (用戶代理支持的字符集)。
// 發送端
Content-Encoding: gzip
Content-Language: zh-CN, zh, en
Content-Type: text/html; charset=utf-8
// 接收端
Accept-Encoding: gzip
Accept-Language: zh-CN, zh, en
Accept-Charset: charset=utf-8
復制代碼
雖然 HTTP1.0 在 HTTP 0.9 的基礎上改進了很多,但還是存在這不少的缺點
HTTP/1.0 版的主要缺點是,每個 TCP 連接只能發送一個請求。發送數據完畢,連接就關閉,如果還要請求其他資源,就必須再新建一個連接。 TCP 連接的新建成本很高,因為需要客戶端和服務器三次握手,并且開始時發送速率較慢( slow start )。
HTTP 最早期的模型,也是 HTTP/1.0 的默認模型,是短連接。每一個 HTTP 請求都由它自己獨立的連接完成;這意味著發起每一個 HTTP 請求之前都會有一次 TCP 握手,而且是連續不斷的。
HTTP/1.1 在1997年1月以 RFC 2068 文件發布。
HTTP 1.1 消除了大量歧義內容并引入了多項技術
虛擬主機( virtual hosting )即共享主機( shared web hosting ),可以利用虛擬技術把一臺完整的服務器分成若干個主機,因此可以在單一主機上運行多個網站或服務。
舉個例子,有一臺 ip 地址為 61.135.169.125 的服務器,在這臺服務器上部署著谷歌、百度、淘寶的網站。為什么我們訪問 https://www.google.com 時,看到的是 Google 的首頁而不是百度或者淘寶的首頁?原因就是 Host 請求頭決定著訪問哪個虛擬主機。
2015年, HTTP2.0 面世。 rfc7540
HTTP 2.0 中的幀將 HTTP/1.x 消息分成幀并嵌入到流 ( stream ) 中。數據幀和報頭幀分離,這將允許報頭壓縮。將多個流組合,這是一個被稱為多路復用 ( multiplexing ) 的過程,它允許更有效的底層 TCP 連接。
也就是說,流用來承載消息,消息又是有一個或多個幀組成。二進制傳輸的方式更加提升了傳輸性能。 每個數據流都以消息的形式發送,而消息又由一個或多個幀組成。 幀是流中的數據單位。
HTTP 幀現在對 Web 開發人員是透明的。在 HTTP/2 中,這是一個在 HTTP/1.1 和底層傳輸協議之間附加的步驟。 Web 開發人員不需要在其使用的 API 中做任何更改來利用 HTTP 幀;當瀏覽器和服務器都可用時, HTTP/2 將被打開并使用。
之前我們提到,雖然 HTTP 1.1 有了長連接和管道化的技術,但是還是會存在 隊頭阻塞。而 HTTP 2.0 就解決了這個問題 HTTP/2 中新的二進制分幀層突破了這些限制,實現了完整的請求和響應復用:客戶端和服務器可以將 HTTP 消息分解為互不依賴的幀,然后交錯發送,最后再在另一端把它們重新組裝起來。
如上圖所示,快照捕捉了同一個連接內并行的多個數據流。 客戶端正在向服務器傳輸一個 DATA 幀(數據流 5),與此同時,服務器正向客戶端交錯發送數據流 1 和數據流 3 的一系列幀。因此,一個連接上同時有三個并行數據流。
將 HTTP 消息分解為獨立的幀,交錯發送,然后在另一端重新組裝是 HTTP 2 最重要的一項增強。事實上,這個機制會在整個網絡技術棧中引發一系列連鎖反應,從而帶來巨大的性能提升,讓我們可以: 1.并行交錯地發送多個請求,請求之間互不影響。 2.并行交錯地發送多個響應,響應之間互不干擾。 3.使用一個連接并行發送多個請求和響應。 4.消除不必要的延遲和提高現有網絡容量的利用率,從而減少頁面加載時間。 5.不必再為繞過 HTTP/1.x 限制而做很多工作(比如精靈圖) ...
連接共享,即每一個 request 都是是用作連接共享機制的。一個 request 對應一個 id ,這樣一個連接上可以有多個 request ,每個連接的 request 可以隨機的混雜在一起,接收方可以根據 request 的 id 將 request 再歸屬到各自不同的服務端請求里面。
HTTP 1.1 和 HTTP 2.0 的對比,可以參考這個 網站 demo 演示
HTTP 1.1 演示如下:
HTTP2.0 演示如下:
使用 HTTP/1.1 和 HTTP/2 對于站點和應用來說是透明的。擁有一個最新的服務器和新點的瀏覽器進行交互就足夠了。只有一小部分群體需要做出改變,而且隨著陳舊的瀏覽器和服務器的更新,而不需 Web 開發者做什么,用的人自然就增加了
HTTPS 也是通過 HTTP 協議進行傳輸信息,但是采用了 TLS 協議進行了加密
對稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密。但是因為傳輸數據都是走的網絡,如果將秘鑰通過網絡的方式傳遞的話,一旦秘鑰被截獲就沒有加密的意義的
非對稱加密
公鑰大家都知道,可以用公鑰加密數據。但解密數據必須使用私鑰,私鑰掌握在頒發公鑰的一方。首先服務端將公鑰發布出去,那么客戶端是知道公鑰的。然后客戶端創建一個秘鑰,并使用公鑰加密,發送給服務端。服務端接收到密文以后通過私鑰解密出正確的秘鑰
TLS 握手的過程采用的是非對稱加密
強緩存主要是由 Cache-control 和 Expires 兩個 Header 決定的
Expires 的值和頭里面的 Date 屬性的值來判斷是否緩存還有效。 Expires 是 Web 服務器響應消息頭字段,在響應 http 請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器緩存取數據,而無需再次請求。 Expires 的一個缺點就是,返回的到期時間是服務器端的時間,這是一個絕對的時間,這樣存在一個問題,如果客戶端的時間與服務器的時間相差很大(比如時鐘不同步,或者跨時區),那么誤差就很大。
Cache-Control 指明當前資源的有效期,控制瀏覽器是否直接從瀏覽器緩存取數據還是重新發請求到服務器取數據。但是其設置的是一個相對時間。
指定過期時間: max-age 是距離請求發起的時間的秒數,比如下面指的是距離發起請求 31536000S 內都可以命中強緩存
Cache-Control: max-age=31536000
復制代碼
表示沒有緩存
Cache-Control: no-store
復制代碼
有緩存但要重新驗證
Cache-Control: no-cache
復制代碼
私有和公共緩存
public 表示響應可以被任何中間人(比如中間代理、 CDN 等緩存) 而 private 則表示該響應是專用于某單個用戶的,中間人不能緩存此響應,該響應只能應用于瀏覽器私有緩存中。
Cache-Control: private
Cache-Control: public
復制代碼
驗證方式:以下表示一旦資源過期(比如已經超過 max-age ),在成功向原始服務器驗證之前,緩存不能用該資源響應后續請求
Cache-Control: must-revalidate
復制代碼
Cache-control 優先級比 Expires 優先級高
以下是一個 Cache-Control 強緩存的過程:
Last-Modified 表示本地文件最后修改日期,瀏覽器會在 request header 加上 If-Modified-Since (上次返回的 Last-Modified 的值),詢問服務器在該日期后資源是否有更新,有更新的話就會將新的資源發送回來
但是如果在本地打開緩存文件,就會造成 Last-Modified 被修改,所以在 HTTP / 1.1 出現了 ETag
Etag 就像一個指紋,資源變化都會導致 ETag 變化,跟最后修改時間沒有關系, ETag 可以保證每一個資源是唯一的。 If-None-Match 的 header 會將上次返回的 Etag 發送給服務器,詢問該資源的 Etag 是否有更新,有變動就會發送新的資源回來
If-none-match 、 ETags 優先級高于 If-Modified-Since、Last-Modified
第一次請求:
第二次請求相同網頁:
協商緩存,假如沒有改動的話,返回 304 ,改動了返回 200 資源
現在的200 (from cache) 已經變成了 disk cache (磁盤緩存)和 memory cache (內存緩存)兩種
上面提到 HTTP 緩存相關,但是很多有時候,我們希望上線之后需要更新線上資源。
web 開發者發明了一種被 Steve Souders 稱之為 revving 的技術。不頻繁更新的文件會使用特定的命名方式:在 URL 后面(通常是文件名后面)會加上版本號。
弊端:更新了版本號,所有引用這些的資源的地方的版本號都要改變
web 開發者們通常會采用自動化構建工具在實際工作中完成這些瑣碎的工作。當低頻更新的資源( js/css )變動了,只用在高頻變動的資源文件( html )里做入口的改動。
HTTP Cookie (也叫 Web Cookie 或瀏覽器 Cookie )是服務器發送到用戶瀏覽器并保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶并發送到服務器上。
Set-Cookie 響應頭部和 Cookie 請求頭部
Set-Cookie: <cookie名>=<cookie值>
復制代碼
會話期Cookie是最簡單的 Cookie :瀏覽器關閉之后它會被自動刪除,也就是說它僅在會話期內有效。會話期 Cookie 不需要指定過期時間( Expires )或者有效期( Max-Age )。需要注意的是,有些瀏覽器提供了會話恢復功能,這種情況下即使關閉了瀏覽器,會話期 Cookie 也會被保留下來,就好像瀏覽器從來沒有關閉一樣
和關閉瀏覽器便失效的會話期 Cookie 不同,持久性 Cookie 可以指定一個特定的過期時間( Expires )或有效期( Max-Age )。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
復制代碼
標記為 Secure 的 Cookie 只應通過被 HTTPS 協議加密過的請求發送給服務端。
標記為 Secure 的 Cookie 只應通過被 HTTPS 協議加密過的請求發送給服務端。但即便設置了 Secure 標記,敏感信息也不應該通過 Cookie 傳輸,因為 Cookie 有其固有的不安全性, Secure 標記也無法提供確實的安全保障
通過 JavaScript 的 Document.cookie API 是無法訪問帶有 HttpOnly 標記的 cookie 。這么做是為了避免跨域腳本攻擊( XSS )
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
復制代碼
Domain 和 Path 標識定義了 Cookie 的作用域:即 Cookie 應該發送給哪些 URL 。
Domain 標識指定了哪些主機可以接受 Cookie 。如果不指定,默認為當前的主機(不包含子域名)。如果指定了 Domain ,則一般包含子域名。
例如,如果設置 Domain=mozilla.org ,則 Cookie 也包含在子域名中(如 developer.mozilla.org )。
Path 標識指定了主機下的哪些路徑可以接受 Cookie (該 URL 路徑必須存在于請求 URL 中)。以字符 %x2F ("/") 作為路徑分隔符,子路徑也會被匹配。
例如,設置 Path=/docs ,則以下地址都會匹配:
/docs
/docs/Web/
/docs/Web/HTTP
復制代碼
SameSite Cookie 允許服務器要求某個 cookie 在跨站請求時不會被發送,從而可以阻止跨站請求偽造攻擊
Set-Cookie: key=value; SameSite=Strict
復制代碼
None Strict Lax
在新版本的瀏覽器( Chrome 80 之后)中, SameSite 的默認屬性是 SameSite=Lax 。換句話說,當 Cookie 沒有設置 SameSite 屬性時,將會視作 SameSite 屬性被設置為 Lax —— 這意味著 Cookies 將不會在當前用戶使用時被自動發送。如果想要指定 Cookies 在同站、跨站請求都被發送,那么需要明確指定 SameSite 為 None 。因為這一點,我們需要好好排查舊系統是否明確指定 SameSite ,以及推薦新系統明確指定 SameSite ,以兼容新舊版本 Chrome
更多 cookie 相關,可以查看我之前總結的一篇關于 cookie 的文章 前端須知的 Cookie 知識小結
跨域資源共享( CORS )是一種機制,它使用額外的 HTTP 頭告訴瀏覽器,讓運行在一個 origin ( domain ) 上的 web 應用被準許訪問來自不同源服務器上的指定的資源
跨域資源共享標準新增了一組 HTTP 首部字段,允許服務器聲明哪些源站通過瀏覽器有權限訪問哪些資源。
簡單請求(不會觸發 CORS 的預檢請求)需要同時滿足以下三點:
以下為一個簡單請求的請求報文以及響應報文
簡化以下:
請求首部字段 Origin 表明該請求來源于 http://foo.example
本例中,服務端返回的 Access-Control-Allow-Origin: * 表明,該資源可以被任意外域訪問。如果服務端僅允許來自 http://foo.example 的訪問,該首部字段的內容如下:
Access-Control-Allow-Origin: http://foo.example
復制代碼
Access-Control-Allow-Origin 應當為 * 或者包含由 Origin 首部字段所指明的域名。
規范要求,對那些可能對服務器數據產生副作用的 HTTP 請求方法。瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求( preflight request ),從而獲知服務端是否允許該跨域請求。
服務器確認允許之后,才發起實際的 HTTP 請求。在預檢請求的返回中,服務器端也可以通知客戶端,是否需要攜帶身份憑證(包括 Cookies 和 HTTP 認證相關數據)
預檢請求中同時攜帶了下面兩個首部字段:
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
復制代碼
首部字段 Access-Control-Request-Method 告知服務器,實際請求將使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服務器,實際請求將攜帶兩個自定義請求首部字段: X-PINGOTHER 與 Content-Type 。服務器據此決定,該實際請求是否被允許。
預檢請求的響應中,包括了以下幾個字段
Access-Control-Allow-Origin: http://foo.example
// 表明服務器允許客戶端使用 POST, GET 和 OPTIONS 方法發起請求
Access-Control-Allow-Methods: POST, GET, OPTIONS
// 表明服務器允許請求中攜帶字段 X-PINGOTHER 與 Content-Type
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
// 表明該響應的有效時間為 86400 秒,也就是 24 小時。在有效時間內,瀏覽器無須為同一請求再次發起預檢請求。
Access-Control-Max-Age: 86400
復制代碼
一般而言,對于跨域 XMLHttpRequest 或 Fetch 請求,瀏覽器不會發送身份憑證信息。如果要發送憑證信息,需要設置 XMLHttpRequest 的某個特殊標志位。比如說 XMLHttpRequest 的 withCredentials 標志設置為 true ,則可以發送 cookie 到服務端。
對于附帶身份憑證的請求,服務器不得設置 Access-Control-Allow-Origin 的值為“*”。 這是因為請求的首部中攜帶了 Cookie 信息,如果 Access-Control-Allow-Origin 的值為“*”,請求將會失敗。而將 Access-Control-Allow-Origin 的值設置為 http://foo.example ,則請求將成功執行。
CORS 涉及到的請求和響應頭如下: HTTP 響應首部字段
HTTP 請求首部字段
Origin
Access-Control-Request-Method
Access-Control-Request-Headers
有感興趣的朋友可以關注一下我的公眾號:前端維他命,不定時更新優秀文章。
稱為前端三劍客的HTML、CSS、JS
HTML我們上節課已經進行了簡單的介紹,未看過的同學可以點擊傳送門:
果凍公開課:什么是HTML
本節課,我們就來用幾分鐘快速了解下,附著在HTML骨骼上,使得頁面呈現出豐富內容的CSS層疊樣式表。
動畫視頻:
果凍公開課:三分鐘了解CSS
文字解析:
CSS,全稱為層疊樣式表。
簡單來說,就是給被HTML標記的內容加上裝飾,讓它能有所不同,不管是外觀還是內在,都有一個新的變化。
這個過程我們可以稱之為為內容增加新的屬性,賦予它更多的可能。
與HTML不同的是,它用的是花括號{}來包裹屬性。
CSS的屬性大體可以分為5大類。
其中樣式、框模型、定位、選擇器為較為常用的四類,而其余屬性皆歸為高級屬性。
CSS的語言規則分為兩部分:
第一部分是選擇器,顧名思義我們要告訴瀏覽器這個屬性是用在哪個或者哪幾個標簽上。
第二部分是聲明,是告訴瀏覽器具體我要為它附加什么屬性,增加什么變化的部分。
讓我們看看加上了屬性之后,我們的HTML有什么變化吧~
color,改變了文字的顏色
font-size可以讓文字的大小發生變化
background-color可以添加背景顏色
border可以讓文字的外邊出現了邊框
margin和padding可以添加內外邊距,讓文字和線框,線框和塊之間出現了新的空間
float可以讓文字浮動
top給文字增加了頂部的距離
在有了內容和樣式后,我們的網頁現在是這個樣子,看起來和我們平時看到的網頁沒什么不同。
但當你對他進行操作時,你會發現,為什么這里不動了,為什么那里沒反應了?
這是因為我們缺少激活它的語言JS,JS全稱為javascript,是一種腳本語言。
整體來說,JS在網頁中起到的作用,就像裝修好的房子,你要通電才能使用這些電器一樣,只有有了電,你才能使用這些電器。
而電器就是我們的CSS和HTML。
那么,為什么瀏覽器可以把這些代碼變成我們平時瀏覽的網頁呢?
這里可以給大家舉一個很簡單的例子:
大家都知道記事本,只可以在里面輸入的文字。
但當我們在word中輸入文字的時候,可以通過word中的各種按鈕給他增加字體、字號、顏色,還可以插入表格、排版等。
而這些按鈕就是前面說到的標簽和屬性,他為文字增加了很多新的東西。
而瀏覽器就相當于我們的word,可以把我們寫好的HTML文件打開,讓大家看到編輯好的內容。
網頁沒有我們想的那么復雜,HTML和CSS也沒有我們想的那么神秘,它只是換了一種方式的word。
我們要先用一個軟件打開和編輯我們的HTML文件,然后再用瀏覽器打開它,就能看到我們平時看到的那些網頁了。
而我們只是將編輯的過程給了編譯器,顯示的過程給了瀏覽器,各司其職而已。
好了,今天的果凍公開課就先到這里,下期我們將向大家介紹CSS的選擇器都有哪些。
★★★★★
這里是果凍公開課,一個用趣味的動畫來分享IT知識的課堂
我們將原本復雜、不易理解的編程知識,轉化為一個個有趣的動畫短視頻,為更多人提供生動有趣的IT內容/服務
無論是大咖還是小白,都可以快速學會并深度了解每一個知識點,讓IT,Q彈可口。
更多內容,歡迎加大師姐微信it_xzy,入群717415872了解課程動態、幕后花絮,還有機會參與到課程制作,成為聯合制作人
記得備注來自果凍課堂喲
*請認真填寫需求信息,我們會在24小時內與您取得聯系。