介紹#
在開始我們的 Web 開發旅程之前,讓我們先來聊一聊啥是 Web,希望能讓大家先有一個感性的認知。首先,可以做這樣一個比喻,Web 就是一個複雜的城市交通網絡,Web 中的客戶端,就像你在這座城市中的家,而伺服器就像你想去的城市中的某個商店,那麼就可以試著把一些 web 中的術語 / 組成部分放進這樣一個 context 中:
- 網路連接:允許你在互聯網上發送和接收數據,可以想像成是連接你家和商店的街道,它可以承載一定量的車流 (數據流)
- TCP/IP: 傳輸控制協議 (Transmission Control Protocol) 和因特網互連協議 (Internet Protocol) 是定義數據如何傳輸的通信協議。這就像你去商店購物所使用的交通方式,比如汽車或自行車 (或是你能想到的其他可能)。相關的交通規則 (協議) 規定了什麼樣的車輛可以通行 (數據格式)、車輛該如何行駛 (數據如何被傳遞) ... 诸如堵車、車禍等意外情況在網路傳輸過程中也屢見不鮮 (不過,在網路世界裡行駛,倒不需要你把科一到科四考一遍,哈哈)
https://en.wikipedia.org/wiki/Internet_protocol_suite - DNS: 域名系統 (Domain Name System) 伺服器像是一本網站通訊錄,記錄了域名和 IP 地址的對應關係。當你在瀏覽器內輸入一個網址時,瀏覽器獲取網頁之前將會查看對應的域名系統,將域名翻譯為一個可識別的 IP 地址,只有這樣瀏覽器才能找到存放你想要的網頁的伺服器,才能發送 HTTP 請求到正確的地方,這就像你確定了你要去的商店之後還需要知曉它的具體地理位置,並在地圖上找到它的定位
https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/What_is_a_domain_name - HTTP: 超文本傳輸協議 (Hyper Text Transfer Protocol) 是一個定義客戶端和伺服端之間交流的語言的協議,屬於應用層協議,比 TCP/IP 所處的傳輸層更高一層 (詳見本文底部的 OSI 模型圖)。這就像你在網購下訂單時所填寫的表單,詳細說明了你的通訊方式、收貨地址、商品信息 ... 在這個過程中你不需要擔心商品具體是如何被運輸的,只要和商家達成了交易並成功下單,就可以安心在家等待送貨上門了 (這就是一種抽象!HTTP 作為更高層的抽象,不需要知道底層 TCP/IP 協議的實現方式,只要大家商量好不同層之間交流的形式 - 接口,之後各自做好自己分內的事就行了)
- 組成文件:一個網頁由許多不同類型的文件組成,就像商店裡不同類目的商品一樣。這些文件大致可以分為兩種類型:
- 代碼 : 網頁大體由 HTML、CSS、JavaScript 組成,不過你會在後面的內容裡看到更多不同的技術
- 資源 : 其他組成網頁的靜態文件的集合,比如圖像、音樂、視頻、Word 文檔、PDF 文件 ... 一旦確定之後就很少會發生改動
https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/How_the_Web_works
沒事兒多逛逛 MDN (https://developer.mozilla.org/),在裡面你能夠看到對很多技術細節 / 名詞的權威解讀
經過了對 Web 的宏觀性描述,接下來讓我們再逐個深入 Web 世界裡的一些專業名詞和重要技術(為了保證意義的準確傳達,以下內容保留了部分英文原版描述,相信各位大佬閱讀起來應該也不會有太大障礙,的吧)
世界網路#
網頁伺服器#
網頁伺服器(Web server)可以代指硬體或軟體,或者是它們協同工作的整體
- 硬體部分 (商場裡存放商品的貨架):一個網頁伺服器是一台存儲了網路服務軟體以及網站的組成文件(比如,HTML 文檔、圖片、CSS 樣式表和 JavaScript 文件)的計算機。它接入到互聯網並且支持與其他連接到互聯網的設備進行物理數據的交互。
- 軟體部分 (商場內部的商品庫存管理系統,可與電商平台對接):網頁伺服器包括控制網路用戶如何訪問托管文件的幾個部分,至少他要是一台 HTTP 伺服器。一台 HTTP 伺服器是一種能夠理解 URL 和 HTTP 的軟體。通過伺服器上存儲的網站的域名(比如 mozilla.org)可以訪問這個伺服器,並且他還可以將他的內容分發給不同用戶的設備
基本上,當瀏覽器需要一個 托管 在網頁伺服器上的文件的時候,瀏覽器通過 HTTP 請求這個文件。當這個請求到達正確的網頁伺服器(硬體)時,HTTP 伺服器(軟體)收到這個請求,找到這個被請求的文檔(如果這個文檔不存在,那麼將返回一個 404 響應),並把這個文檔通過 HTTP 發送給瀏覽器 (可以想像成是一個網購下單收貨的過程)。在之後學習 Spring Boot 的時候,你將會對這一過程有更加深刻的理解。
https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/What_is_a_web_server
網頁瀏覽器 (客戶端)#
瀏覽器是一種通過 URL 獲取 Web 資源並將其以某種可視化的方式展示在用戶設備上的應用軟體。在 Web 世界裡,有一個叫宿主環境的概念,簡單來說,它就是我們編寫的 JavaScript 代碼執行的具體環境,或者說是一種運行時環境 (runtime environment),而瀏覽器就是其中一種,除此之外還有像 Node.js 等伺服器端的宿主環境,感興趣的同學可以自行了解
更多關於瀏覽器的內容會在之後的 “瀏覽器中頁面的渲染過程” 部分進行介紹
統一資源定位符 (URL)#
一種 URI (Uniform Resource Identifier) 的形式,提供資源的路徑或位置
格式
- 一般格式: Scheme(protocol, e.g. http/https)://DomianName/path:Port
- 特殊格式: file://path-to-document (“file” indicates the documents resides on the machine running the browser)
文本 http:// 表示應使用 HTTP 獲取資源。接下來在 URL 中是伺服器的完全合格 主機名 (e.g. www.deitel.com) — 資源所在的網頁伺服器計算機的名稱。主機名 www.deitel.com 被轉換為一個 IP 地址 — 一個唯一識別互聯網上伺服器的數值。互聯網域名系統 (DNS) 伺服器維護著主機名及其對應的 IP 地址的數據庫,並自動執行轉換。
提示
- 如果伺服器已配置為使用其他 端口號, 則有必要將該端口號附加到 URL 中的主機名 (e.g. :80 for HTTP, :443 for HTTPS)
- 嵌入空格 和 (; , &) 不能出現在 URL 中 (如果 San Jose 是一個域名,則必須輸入為 San%20Jose,20 是空格的十六進制 ASCII 代碼)
路徑#
絕對路徑 包含沿途的所有目錄
相對路徑 相對於伺服器配置文件中指定的某個 基礎路徑
提示
- http://www.gumboco.com/departments/ (結尾的斜杠表示指定的文檔是一個目錄)
- http://www.gumboco.com/ (伺服器將在目錄的頂層搜索 index.html)
多用途互聯網郵件擴展 (MIME) 文件類型#
指定從伺服器接收的文檔的形式(附加到文檔開頭,由伺服器附加,伺服器通過使用文件名擴展作為類型表的鍵來確定文檔的類型)
形式: type/subtype (e.g. text/html, text/plain)
自學: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types
相信現在的你對 Web 技術的全貌已經有了一定的了解,是時候深入 HTTP 這一 Web 的底層協議了 (Web 原理的精髓部分)。理解這個協議的細節無論對於前端開發還是後端開發都是十分重要的!
不過,由於課程長度的限制,很多 HTTP 的衍生技術點無法在此逐個展開,感興趣的同學可以移步相應內容下方的鏈接
超文本傳輸協議 (HTTP)#
超文本傳輸協議(HTTP)是一個基於 TCP 協議的用於傳輸超媒體文檔(例如 HTML)的 應用層協議(作為最頂層的協議,它隱藏了很多網路層和傳輸層的細節,詳見 Bonus 中的 OSI 模型)。它是為了約束 / 規範 Web 瀏覽器與 Web 伺服器之間的通信而設計的,但也可以用於其他目的。HTTP 遵循經典的 客戶端 - 伺服端模型,客戶端打開一個連接以發出請求,然後等待直到收到伺服器端響應,就像兩個人談話一問一答的回合制形式。HTTP 是 無狀態協議,這意味著伺服器不會在兩個請求之間保留任何數據(狀態),即一般情況下伺服器無法分辨多次請求的發起人分別是誰
自學: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview
報文 作為 HTTP 傳輸數據最重要的一種形式,有著自己的一套規範化的數據格式,讓我們一起來看一下它們由哪些部分構成 (它就像我們平時對話時所使用的語言,有著自己的語法和語義,理解它對於你理解客戶端伺服端之間的信息交流非常有幫助)
請求階段#
- HTTP 方法,URL 的域名部分,HTTP 版本
- 標頭字段
- 空行
- 消息主體
請求方法#
方法 | 描述 |
---|---|
GET | 返回指定文檔的內容 |
POST | 執行指定文檔,使用封閉的數據 |
HEAD | 返回指定文檔的標頭信息 |
PUT | 用封閉的數據替換指定文檔 |
DELETE | 刪除指定文檔 |
自學: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods
標頭字段#
- 通用標頭: 用於一般信息,例如日期
- 請求標頭: 包含在請求標頭中
例如:- Accept: text/plain (指定瀏覽器對請求文檔的 MIME 類型的偏好)
- Host: host name
- If-Modified-Since: date (指定請求的文件應僅在自給定日期以來已被修改的情況下發送)
- 響應標頭: 用於響應標頭
- 實體標頭: 用於請求和響應標頭中
自學: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
響應階段#
- 狀態行 (例如 HTTP/1.1 200 OK)
HTTP 狀態碼的首位數字:首位數字 類別 1 信息 2 成功 3 重定向 4 客戶端錯誤 5 伺服器錯誤 - 響應標頭字段
- 空行
- 響應主體 (.html)
自學: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
讓我們把請求和響應的報文再放在一起比對一下
HTTPS#
HTTPS = HTTP + SSL/TLS (* 傳輸層安全性 ***) 會話層協議 **
HTTPS 有兩個作用,一是確定請求的目標伺服端身份,二是保證傳輸的數據不會被網路中間節點竊聽或者篡改。
HTTPS 是使用加密通道來傳輸 HTTP 的內容,即 HTTPS 首先會與伺服端建立一條 TLS 加密通道。TLS 建立於 TCP 協議之上,它實際上是對傳輸的內容做一次加密 (非對稱加密),所以從傳輸內容上看,HTTPS 跟 HTTP 沒有任何區別。
自學: https://zh.wikipedia.org/wiki/ 超文本傳輸安全協議
緩存 (HTTP 緩存)#
緩存是一種保存資源副本並在下次請求時直接使用該副本的技術 (空間換時間)。當 web 緩存發現請求的資源已經被存儲,它會攔截請求,返回該資源的拷貝,而不會去伺服器重新下載。對於網站來說,緩存是達到高性能的重要組成部分。同時,緩存需要合理配置,因為並不是所有資源都是永久不變的,重要的是對一個資源的緩存應截止到其下一次發生改變(即不能緩存過期的資源)
自學: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching
HTTP 歷史演進:HTTP/0.9 → HTTP/1.0 → HTTP/1.1 → HTTP/2.0 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP
動手試一試:
https://developer.chrome.com/docs/devtools/network/ | chrome 瀏覽器的網路查看工具,按下 F12, magic happens !
https://hoppscotch.io/ | 超好用的在線抓包工具,看報文超方便!
編程世界網路 (第八版)
網際網路與世界網路如何編程 (2011)
可能前面的這些內容會讓你有一些 overwhelmed,不用擔心,接下來我們就把這些知識點放置到 瀏覽器渲染 這一實際場景中,將它們按照邏輯順序串聯起來,釐清它們之間的關係,並做一些適當的拓展 (此部分內容會涉及到一些前端三大件的內容,且當是給接下來的課程做一下預熱吧,不完全理解也沒關係)
瀏覽器中頁面的渲染過程#
實際上當我們在瀏覽器輸入網頁地址,按下回車鍵後,瀏覽器的處理過程是這樣子的:
- DNS 域名解析(此處涉及 DNS 的尋址過程),找到網頁的存放伺服器
- 瀏覽器與伺服器建立 TCP 連接
- 瀏覽器發起 HTTP 請求
- 伺服器響應 HTTP 請求,返回該頁面的 HTML 內容
- 瀏覽器解析 HTML 代碼,並請求 HTML 代碼中的資源(如 JavaScript、CSS、圖片等,此處可能涉及 HTTP 緩存)
- 瀏覽器對頁面進行渲染呈現給用戶(此處涉及瀏覽器的渲染原理)
進一步分析,我們可以將瀏覽器中頁面的渲染過程分為兩大部分 (詳見 Bonus)
- 頁面導航:用戶輸入 URL,瀏覽器進程進行請求和準備處理。
- 頁面渲染:獲取到相關資源後,渲染器進程負責當前標籤頁內部的渲染處理。
對瀏覽器渲染的整體流程有了一定理解之後,我們再來深入看一看網頁從 0 到 1 的生命週期吧~(提前了解一下瀏覽器提供給我們的兩個重要 API - DOM 和 BOM,任何前端框架的底層都離不開和這兩個家伙打交道!哦對了,還有瀏覽器的事件機制,一名合格的前端工程師應該掌握它!)
瀏覽器對象模型(Browser Object Model),簡稱 BOM,表示由瀏覽器(宿主環境)提供的用於處理文檔(document)之外的所有內容的其他對象 (瀏覽器在 JavaScript 中的表示形式)
文檔對象模型(Document Object Model),簡稱 DOM,將所有頁面內容表示為可以修改的對象。document
對象是頁面的主要 “入口點”。我們可以使用它來更改或創建頁面上的任何內容 (HTML 標籤在 JavaScript 中的表示形式)
動手試一試:
按下 F12,在控制台 console 裡敲入 window 或 document,看看會出現什麼
自學: https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Introduction
事件 (Event-driven 事件驅動)
- 瀏覽器事件,例如當頁面加載完成或即將卸載時
- 網路事件,例如來自伺服器的響應 (Ajax 事件,伺服器端事件)
- 用戶事件,例如鼠標點擊、鼠標移動和鍵盤按鍵
- 計時器事件,例如當超時到期或間隔觸發時 (setTimeout, setInterval)
自學:
https://zh.javascript.info/introduction-browser-events
https://zh.javascript.info/event-loop
JavaScript Ninja 的秘密,(第二版) - JOHN RESIG BEAR BIBEAULT 和 JOSIP MARAS
https://zh.javascript.info/browser-environment | 學習 JavaScript,有這一個網站就足夠了
附加內容#
加餐環節,按需食用~
軟體架構設計模式#
MVC (Model View Controller)
MVP (Model View Presenter)
MVVM (Model View View-Model) (現代前端工程師必須了解的 View-Model 雙向綁定)
https://github.com/livoras/blog/issues/11
世界網路聯盟 (W3C)#
作為 Web 領域的布道者以及標準制定者,W3C 組織是每一個 web programmer 都應該知曉並了解的組織。儘管 web 編程相對來說更為自由和開放,但是若沒有統一的標準來約束不同技術的創造者和使用者,那麼這種 freedom 將會變成一種令人苦惱的 chaos
職責與使命
- 致力於開發非專有的、可互操作的技術以促進世界網路的發展。
- 使網路普遍可 訪問 — 無論殘疾、語言或文化。W3C 主頁 (www.w3.org) 提供有關互聯網和網路技術的廣泛資源。
標準制定
W3C 標準化的 Web 技術稱為 Recommendations (這些標準並非強制性的)。當前和即將到來的 W3C Recommendations 包括超文本標記語言 5 (HTML5)、層疊樣式表 3 (CSS3) 和可擴展標記語言 (XML)。一項推薦不是一個實際的軟體產品,而是一份指定技術的角色、語法規則等的文檔。
頁面導航過程#
當用戶在地址欄中輸入內容時,瀏覽器內部會進行以下處理:
- 首先瀏覽器進程的 UI 線程會進行處理:如果是 URI,則會發起網路請求來獲取網站內容;如果不是,則進入搜索引擎
- 如果需要發起網路請求,請求過程由網路線程來完成。HTTP 請求響應如果是 HTML 文件,則將數據傳遞到渲染器進程;如果是其他文件則意味著這是下載請求,此時會將數據傳遞到下載管理器
- 如果請求響應為 HTML 內容,此時瀏覽器應導航到請求站點,網路線程便通知 UI 線程數據準備就緒
- 接下來,UI 線程會尋找一個渲染器進程來進行網頁渲染。當數據和渲染器進程都準備好後,HTML 數據通過 IPC (Inter-process Communication) 從瀏覽器進程傳遞到渲染器進程中。
- 渲染器進程接收 HTML 數據後,將開始加載資源並渲染頁面
- 渲染器進程完成渲染後,通過 IPC 通知瀏覽器進程頁面已加載
頁面渲染過程#
- 解析 (Parser):解析 HTML/CSS/JavaScript 代碼。
- 布局 (Layout):定位坐標和大小、是否換行、各種 position/overflow/z-index 屬性等計算。
- 繪製 (Paint):判斷元素渲染層級順序。
- 光柵化 (Raster):將計算後的信息轉換為螢幕上的像素。
自學: https://coolshell.cn/articles/9666.html