從優化到面試裝逼指南——網絡系列

與普通的面試文不一樣,從問題出發完全瞭解原理到實踐,讓你能在面試現場直接裝逼。
ps: 我好像也裝了個逼?javascript

此文深刻閱讀須要15分鐘左右請各位不要再帶薪如廁的時候觀看,以避免痔瘡——用心微醫php

狗蛋來到了面試場地,面試官是個凶神惡煞的紋身男人,內心充滿了膽怯,感受亞歷山大~~css

面試官:來,說說你以爲優化什麼最能給你的項目提供質的飛躍?html

狗蛋:H T T P 資源前端

面試官冷笑😏小夥子開始挖坑了vue

面試官:怎麼優化?java

狗蛋:倆個方向,減小請求數或資源大小react

面試官男人:具體有哪些呢?webpack


減小資源體積

gzip

gzip 使用了 LZ77 算法與 Huffman 編碼來壓縮文件,重複度越高的文件可壓縮的空間就越大nginx

開啓gzip能夠壓縮代碼,如何查看是否開啓gzip?

—— 打開控制面板進入NetWork,右鍵選取response headers 選擇查看Content-Encoding

Content-Encoding:內容編碼格式gzip 和 deflate

1.首先瀏覽器(也就是客戶端)發送請求時,經過Accept-Encoding帶上本身支持的內容編碼格式列表
2.服務端在接收到請求後,從中挑選出一種用來對響應信息進行編碼,並經過Content-Encoding來講明服務端選定的編碼信息
3.瀏覽器在拿到響應正文後,依據Content-Encoding進行解壓。
複製代碼

案例


咱們能夠看到圖片中開啓gzip壓縮以後文件小了不少(越小的文件越不明顯)

優化

nginx開啓

列出了一些重點

gzip on;
gzip_min_length 1k; //不壓縮臨界值,大於1K的才壓縮,通常不用改
gzip_comp_level 2//壓縮級別,1-10,數字越大壓縮的越細,時間也越長
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; //進行壓縮的文件類型
gzip_disable "MSIE [1-6]\.";//ie兼容性很差因此放棄
複製代碼

webpack開啓

compression-webpack-plugin 這個插件能夠提供功能,伸手黨福利

const CompressionWebpackPlugin = require('compression-webpack-plugin');
plugins.push(
    new CompressionWebpackPlugin({
        asset'[path].gz[query]',// 目標文件名
        algorithm: 'gzip',// 使用gzip壓縮
        test: new RegExp(
            '\\.(js|css)$' // 壓縮 js 與 css
        ),
        threshold10240,// 資源文件大於10240B=10kB時會被壓縮
        minRatio: 0.8 // 最小壓縮比達到0.8時纔會被壓縮
    })
);
複製代碼

面試官:webpack的gzip和nginx的有什麼關係?

1.nginx沒有開啓gzip壓縮,webpack打包出的.gz文件是用不到的
2.nginx開啓了gzipnginx查找靜態資源是否存在已經壓縮好的gzip壓縮文件,若是沒有則自行壓縮(消耗cpu但感知比較少)
3.nginx開啓gzip壓縮,webpack打包出的.gz文件被找到,提早(打包)壓縮直接使用,減小了nginx的壓縮損耗
複製代碼

深刻

面試官:gzip是怎麼壓縮的?

到這一步的都不是通常人了,我就簡述一下:使用"滑動窗口"的方法,來尋找文件中的每個匹配長度達到最小匹配的串
,重複的內容以一個哈希值存儲在字典表中並替換到匹配的串上,以此來達到壓縮,所以重複度越高的文件可壓縮的空間就越大。
複製代碼

源文件控制

這裏有不少方案,例如咱們常說的webpack利用splitchunks進行拆包配合一些加載方式,使本來特別大的appjs分紅若干個細小的包,webpack優化將會在下一期的專題裏講到。

圖片

webp,是一種同時提供了有損壓縮與無損壓縮(可逆壓縮)的圖片文件格式,無損壓縮後的WebP比PNG文件少了26%的體積,有損壓縮後的WebP圖片相比於等效質量指標的JPEG圖片減小了25%~34%的體積。

惟一的問題可能就是兼容性了!!萬惡的兼容性我與你不共戴天

還有一種方案,在上古時代咱們也會採用直接有損壓縮圖片來下降體積
zhainanba.net/go/13513

http2——頭部壓縮

HTTP 請求和響應都是由「狀態行、請求 / 響應頭部、消息主體」三部分組成。通常而言,消息主體都會通過 gzip 壓縮,或者自己傳輸的就是壓縮事後的二進制文件(例如圖片、音頻),但狀態行和頭部卻沒有通過任何壓縮,直接以純文本傳輸。
一個網站內總有多個http請求,而其headers所佔的字節也很多,尤爲cookie,有些時headers甚至超過了主體大小,


隨意打開一個網址,看看這張圖是否是基本上大部分http的headers內容都是重複的,

深刻

面試官:頭部壓縮是怎麼實現的?

幀的感念會在後面講到。


相似於對象鍵值對的形式:

1、徹底匹配的頭部鍵值對例如 :method: GET,能夠直接使用一個字符表示
2)HTTP/2 中的靜態字典大體以下:

    method    GET
    path    /index.html
    scheme    https
    cookie

同時,瀏覽器能夠告知服務端,將 cookie: xxxxxxx 添加到動態字典中,這樣後續整個鍵值對就可使用一個字符表示了。
相似的,服務端也能夠更新對方的動態字典。須要注意的是,動態字典上下文有關,須要爲每一個 HTTP/2 鏈接維護不一樣的字典。

其中靜態字典在首次請求中就可使用,對於靜態、動態字典中不存在的內容,還可使用哈夫曼編碼來減少體積。
HTTP/2 使用了一份靜態哈夫曼碼錶,須要內置在客戶端和服務端之中。
複製代碼

減小資源請求

DNS

dns是什麼?

是將域名解析爲ip,例如訪問baidu.com經過dns系統查出他的ip地址,才能訪問,主要是ip對於咱們用戶太難記住,dns作了域名到ip的解析。

在DNS查詢過程當中,瀏覽器進入等待,白屏時間過長,若是DNS查詢過多,會受到性能影響,所以須要用到DNS緩存。

深刻

面試官:dns是怎麼運做的?

1.瀏覽器是否有緩存
2.操做系統是否緩存,常見的如hosts文件
3.路由器是否有緩存
4.域名服務器是否有緩存:根域服務器(.) -> 頂級域名服務器(com->主域名服務器(baidu.com
複製代碼

優化

<link rel="dns-prefetch" href="//baidu.com">
複製代碼

須要注意的是,雖然使用 DNS Prefetch 可以加快頁面的解析速度,可是也不能濫用,由於有開發者指出 禁用DNS 預讀取能節省每個月100億的DNS查詢 。

要禁止隱式的 DNS Prefetch:

<meta http-equiv="x-dns-prefetch-control" content="off">
複製代碼

http協議

主要仍是http2的優化,

核心 二進制分層
爲何說是核心主要是由於http2的一些優化都是基於二進制分層實現的

幀(Frame)是 HTTP2 通信中的最小傳輸單位,全部幀以固定的 9 個八位字節頭部開頭,隨後是一個可變長度的有效載荷


如上圖將一個http消息拆分紅DATA幀 和 HEADERS幀。

多路複用

當一個tcp創建鏈接以後,http2將多個請求重複利用這個tcp,而且分紅多個stream交錯傳輸,慢的請求或者先發送的請求不會阻塞其餘請求的返回,最終根據stream的標識再重組返回,相似併發的感受非並行。

Header 幀必須在 data 幀前面,data 幀依賴 header 幀的信息解析

深刻

面試官:http2多路複用和http1.x的keep-alive有什麼區別?

乍一看好像都是複用了TCP鏈接,但倆這是大相徑庭的。

http1.x
    它是遵循先進先出,服務端只能按順序響應請求,因此若是前面的請求沒有響應完變灰髮生 隊頭阻塞,形成延遲,同時保持沒必要要的鏈接會影響服務器性能,同時瀏覽器限制了http同時併發的上限。
http2
    多個請求能夠同時發送(不分前後),按序響應,解決1.x的一些問題。
複製代碼

服務推送

服務端能夠在發送頁面HTML時主動推送其它資源,而不用等到瀏覽器解析到相應位置,發起請求再響應,客戶端能夠經過發送一個 RST_STREAM 幀來停止推送。

案例

服務端能夠主動把JS和CSS文件推送給客戶端,而不須要客戶端解析HTML時再發送這些請求。

實現:

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    http2_push /Home.css;     //推送css
    http2_push /Home.png;     //推送圖片
  }
複製代碼

深刻

面試官:爲啥你公司還沒啓用http2???

大胸弟前端nginx配一下就完事,你有沒有考慮過我後端老哥的感覺?

  1. nginx 1.1 及其更高版本(nginx會作優雅降級,若是不支持則採用1.1)
  2. 首先我須要https的支持
  3. jetty 9.3 及其更高版本
  4. Apache 2.4.17 及其更高版本

若是你想升級可是無奈服務端不支持怎麼辦?

方案來了:
  client->nginx http2.0    
  nginx->service http1.1
複製代碼

緩存

這塊都是被人問(寫)爛的題目了,若是你還不清楚,須要從新審視(抽打)下本身了

如果http的code碼爲304,意味着命中了緩存。

緩存流程圖

強緩存: Expires、Cache-Control

比較強硬,命中了緩存規則就直接緩存

面試官:Expires和Cache-control的區別

  Expires 如:Thu, 01 Dec 1994 16:00:00 GMT
  表示資源的具體過時時間,過時了就得向服務端發請求,
  然而服務器資源和電腦本地時間不一樣步會致使緩存更新策略不一致,例如用戶本身修改時間。

  Cache-control,指定從請求的時間開始,容許獲取的響應被重用的最長時間(單位:秒)。
  例如,max-age=60 表示可在接下來的 60 秒緩存和重用響應。

  若倆者同時存在Expires則被Cache-Control的max-age覆蓋
複製代碼

深刻

面試官:Cache-control有哪些屬性瞭解過嗎

  no-cache: 數據內容不能被緩存,每次請求都從新訪問服務器, 如有max-age,則緩存期間不訪問服務器
  no-store: 不只不能緩存,連暫存也不能夠(即: 臨時文件夾中不能暫存該資源).
  private(默認): 只能在瀏覽器中緩存,只有在第一次請求的時候才訪問服務器,如有max-age, 則緩存期間不訪問服務器
  public: 能夠被任何緩存區緩存, 如: 瀏覽器、服務器、代理服務器等
  max-age: 相對過時時間, 即以秒爲單位的緩存時間
  s-maxage: 只用於共享緩存,好比CDN緩存(s -> share)。與max-age 的區別是:max-age用於相對過時時間的普通緩存
            而s-maxage用於代理緩存。若是存在s-maxage,則會覆蓋max-age 和 Expires複製代碼

資源緩存超出了強緩寸限定的時間即是協商緩存了

協商緩存: Last-Modified、ETag

顧名思義,能夠以與服務器協商是否緩存

協商緩存有倆對:

 If-Modified-since: Last-Modifed

 If-None-Match: Etag
複製代碼

Last-Modified

瀏覽器請求 → 服務器返回Last-Modified字段(最後修改時間) → 瀏覽器再次請求 → 瀏覽器請求頭攜帶字段If-Modified-Since:服務器返回的最後修改時間 → 服務器拿If-Modified-Since和服務器中資源最後修改時間對比 → 相等返回304讀取緩存,小於最後修改時間重複第一次訪問

ETag
瀏覽器請求 → 服務器返回ETagd字段(根據當前文件的內容生成的惟一標識碼) → 瀏覽器再次請求 → 瀏覽器請求頭攜帶字段If-None-Match:惟一標識碼 → 服務器拿If-None-Match和服務器中資源當前ETag對比 → 相等返回304讀取緩存,不等說明資源被更新,須要從新請求

深刻

面試官: Last-Modified和ETag的區別

Last-Modified在秒級改變的狀況下是沒法更新的,也就是說若是文件在 1 秒內改變了屢次,是沒法監聽到變化的,可能致使文件被緩存住。

可是Last-Modified的計算方式比Etag簡單,緣由上面也說過了時間點和計算惟一標識哈希碼的算法難度是不一樣的,因此性能上是Last-Modified佔優

服務器優先級ETag>Last-Modified。
複製代碼

複習

你看懂裏面的緩存屬性了嗎?

localStorage、sessionStorage

瀏覽器級別的本地存儲,都存在於用戶本地瀏覽器中,能夠經過瀏覽器中Application的storage查看

storage的大小完爆cookie(storage爲5M,cookie4k),同時也是對應一個域名,

注意,若是使用localstorage永久存儲的內容很是龐大注意利用代碼按期釋放

只存在客戶端不參與服務端通訊,所以在身份校驗上避免了 Cookie 的安全問題。

    const Interviewer = { name:"李狗蛋"position:"FE"};
    // 設置
    sessionStorage.setItem("Interviewer"JSON.stringify(Interviewer));
    localStorage.setItem("Interviewer"JSON.stringify(Interviewer));
    // 讀取
    const localviewer = sessionStorage.getItem("Interviewer");
    const sessionviewer = localStorage.getItem("Interviewer");
複製代碼

深刻

面試官: localStorage和sessionStorage的區別,以及應用場景

localStorage:瀏覽器關閉依舊存在
1.存儲token
2.資源存儲
3.用戶習慣存儲

sessionStorage:瀏覽器關閉隨之消失
1.當前數據存儲節省http請求
2.翻頁,先後數據存儲
複製代碼

cdn


如圖,cdn就是咱們所說的就近原則。

深刻

面試官: 說說cdn原理

基於智能DNS對用戶的IP地址綜合參考規則和數值指標的解析,將用戶調度到擇最快的Cache服務器

說人話!:選取最近站點進行請求,節省了對源站的消耗(回源)
複製代碼

瀏覽器同一時間段對同一個域名請求文件的最大下載數是有限的,能夠利用多域名來存放不一樣的靜態資源,增大頁面加載時資源的並行下載數,縮短頁面資源加載的時間,一般把圖片放在一個專用的cdn域名就是一種解決方案。

cdn還能作緩存、防止攻擊等等,想詳細瞭解的不如參考下業界大廠提供的cdn方案

圖片

面試官:區別於減小圖片體積,減小圖片資源請求的方案有哪些?

1.雪碧圖
2.圖片轉base64
複製代碼

雪碧圖

就是把多個圖片拼在一塊兒的圖片,利用背景定位的方式獲取本身想要的,經常使用於icon合集,這樣經過一張圖片能夠減小多個icon的http請求。

固然這個方案的弊端就是background-position很麻煩啊還要算吶,人家不想要那麼麻煩啊~

若是採用HTTP2的話,這個請求頭阻塞的問題固然能解決了

base64

Base64是一種基於選用了"A-Z、a-z、0-九、+、/"64個可打印字符來表示二進制數據的表示方法。
Base64最初的又來是由於二進制文件包含不少沒法顯示和打印的字符,Base64便能將二進制字符串轉換並顯示,例如用記事本打開exe、jpg、pdf這些文件時,會有沒法顯示的二進制數據。

最新的瀏覽器自帶了兩個方法用於base64的編碼和解碼

分別是atob(Base64轉成ASCII)和btoa (將ASCII轉成Base64)

深刻

面試官: base64如何轉碼及應用場景?

Base64轉碼是將4個字節轉換成3個字節.先讀入4個6位(用或運算),每次左移6位,再右移3次,每次8位,這樣就還原了。

場景:

  1. 簡單的數據編碼
  2. 內容無錯傳輸
  3. 電子郵件(SMTP協議)
  4. 圖片base64編碼

面試官:圖片轉base64是爲了達到什麼目的?

比較小的圖片例如icon,使用base64編碼,能夠減小一次圖片的網絡請求;比較大的圖片,使用base64編碼會和html混在一塊兒,加大了html頁面的大小,反而加大了下載頁面的大小,所以url-loader提供設置limit的功能

base64編碼的圖片不能像正常的圖片能夠進行緩存,但寫在css裏面可讓瀏覽器對css文件進行緩存

怎麼實現?

1. window.btoa(str)
2. canvas.toDataURL();
3. var reader = new FileReader();
   imgUrlBase64 =reader.readAsDataURL(file);
4. webpack:url-loader 
複製代碼

異步加載

defer、async、module

<script async src="index1.js"></script>
<script defer src="index2.js"></script>
<script type="module" src="index3.js"></script>
複製代碼

先來了解下 DOMContentLoaded

當初始的 HTML 文檔被徹底加載和解析完成以後,DOMContentLoaded 事件被觸發,而且DOM樹已經生成好了。
可是其餘外部資源,如樣式文件、圖片、字體等並無加載好。
複製代碼

defer DOMContentLoaded事件以前執行,按照 defer 腳本的聲明順序來執行腳本(排隊執行)。ps.根據不一樣瀏覽器不必定老是在DOMContentLoaded事件以前執行,因此最好只包含一個延遲腳本

async 下載完便執行,所以會中斷渲染,所以async是不能保證順序的。

module/nomodule 瀏覽器直接支持es6代碼,也支持defer(默認)和async。

介於瀏覽器兼容性問題不建議所有采用module來優化文件大小(減小轉碼體積)

上圖複習:

dom渲染
下載
執行
三種顏色對應下圖橫線

深刻

面試官:說說 defer 和 async 的使用場景

不難揣測,defer確定是更加適合多個js互相依賴且有執行順序的場景,大多數狀況都適用,包括各大腳手架也是默認defer(頁面底部),業務代碼最合適。

async則更加適合存放sdk或者其餘絕不相關的第三方資源。
複製代碼

交互方案

  • 圖片懶加載
  • 瀑布流
  • 滾動加載

異步加載方案千千萬,萬變不離其宗,這裏就不展開細說,注意節流和防抖。下面推薦個不錯的api

Intersection Observer 具體能夠看MDN

預加載

preload

<link rel="preload" href="style.css" as="style">
複製代碼

這個指令能夠在 link標籤 中使用,如上文,表示預先請求當前頁面須要的資源。

截圖MDN對preload的可預加載內容的介紹:


當標籤中含有as 屬性則表示優先級最高記號,沒有則被降級爲普通預加載

prefetch

瀏覽器在空閒時(沒有在請求時)獲取設置prefetch的資源,而且將他們存儲在瀏覽器的緩存中,當使用了含有 prefetch的靜態資源,便從緩存中加載內容。

深刻

面試官:preload 和 prefetch 的共同點和不一樣點

共同點

異步預加載
頁面加載中發現資源含有 preload 或者 prefetch 時,會從網絡堆棧傳輸到 HTTP 緩存並進入渲染器的內存緩存。

若資源含有緩存字段(例如,存在有效的 cache-control 和 max-age),它將存儲在 HTTP 緩存中,可用於當前和將來觸發它的請求;
如果沒有設置緩存則它會被緩存到內存緩存中並保持不變直到它被使用。
複製代碼

不一樣點

preload:  直接請求
prefetch: 空閒時間請求
複製代碼

注意使用這倆個屬性的必要性,如果沒有用到,這是額外的帶寬浪費,屬於負優化,尤爲移動端的流量浪費

安全方向

這是個不得不提起的面試問題

https

痛點

HTTP 是無狀態的明文傳輸,https提供了加密傳輸、身份認證等功能,相對來講是基本不能破解的

與http區別


如圖,咱們看到在tcp到http中加加了一層 SSL\TLS

  • HTTP 的端口號是 80,HTTPS 是 443
  • 使用 HTTPS 是收費的,主要是由於中間的ca證書機構

結合下面問題看圖思考,幫你完全深刻理解

名詞解釋

對稱密鑰: 相同的密鑰能夠用於信息的加密和解密
非對稱密鑰:一個私鑰一個公鑰。用私鑰加密的數據,只有對應的公鑰才能解密,用公鑰加密的數據, 只有對應的私鑰才能解密。
複製代碼

深刻

面試官:爲何要有ca機構?

防監聽
http是明文的,而https監聽獲得的數據是密文。

防中間人攻擊
在服務端和客戶端中間進行劫持通信,假裝爲客戶端假裝和服務器假裝,再加以篡改的攻擊方式。

** ca機構怎麼解決 **
證書由第三方權威機構頒佈,在客戶端瀏覽器中存在ca根證書的公鑰
tcp握手的時候,服務端會返回本身包裝過的ca證書,
ca證書包裝包含了申請者公鑰、申請者的組織信息和我的信息、簽發機構 CA 的信息、有效時間、證書序列號等信息的明文和CA私鑰對信息摘要加密的簽名,
最主要是攜帶了公司信息、域名、
服務器信息,所以即便經過了劫持也沒法完美僞造。
複製代碼

面試官:爲何經過ca驗證後客戶端生成的是隨機對稱密鑰而不是非對稱密鑰?

HTTPS 在內容傳輸的加密上使用的是對稱加密,非對稱加密只做用在證書驗證階段。

非對稱加密的加解密效率是很是低的,而 http 的應用場景中一般端與端之間存在大量的交互,非對稱加密的效率是沒法接受的。

同時,在 HTTPS 的場景中只有服務端保存了私鑰,一對公私鑰只能實現單向的加解密,因此 HTTPS 中內容傳輸加密採起的是對稱加密,而不是非對稱加密。
複製代碼

基本攻擊

知道大家學不動了,我就精簡一下,詳細能夠查看其餘文章!

跨站腳本攻擊XSS(cross site script)

xss就是把他人的惡意腳本注入到你的頁面中

  • 反射型:服務端返回腳本,客戶端執行(經過URL參數直接注入)
  • 存儲型:後臺存儲,前端展現(發帖或評論輸入內容處,存儲到數據庫後讀取時注入)
  • DOM型:基於DOM(流量劫持、DNS劫持,修改頁面腳本結構)

防護方案

  • http-only:在 cookie 中設置 HttpOnly 屬性後,js腳本將沒法讀取到 cookie 信息。
  • 過濾與轉譯:例如掘金,是有評論功能的然而咱們的alert(1)並無執行不是麼?前端是須要對敏感文字作處理的,.innerHTML、.outerHTML、document.write()、eval()、setTimeout()、setInterval()、v-html(vue)、dangerouslySetInnerHTML(react)等甚至 pre 標籤也都會直接運行代碼須要絕對注意字符串的內容。

推薦一個 xss 的npm包

深刻

sql注入是啥

這不是後端知識嗎?不少同窗下意識的就慫了

別緊張其實就是以前說過的xss,只不過注入的是sql命令語句,
達到欺騙服務器執行惡意的SQL命令。
複製代碼

跨站請求僞造CSRF(cross site request forgery)/XSRF

結餘成本和複雜度,這種攻擊手段相較於xss偏少

盜用身份進行僞造,作一些惡意操做

  • 僞造身份:截取cookie、獲取用戶信息他用、盜用帳號、非法交易、轉帳
  • 跨站點: img等標籤跨域GET請求、POST自動錶單提交、惡意連接跳轉,利用登陸態及cookie完成跨站僞造請求

防護方案

最主要是第三方的冒充,因此要作好身份認證的防範措施

  • 認證手段:驗證 Referer、圖片驗證、活體認證、語音提示、人臉識別巴拉巴拉…
  • token: 頁面插入token(隱藏的一個標籤內,一般在表單input中,而不是在cookie中),JWT(JSON Web Token)

結束撒花✿✿ヽ(°▽°)ノ✿

面試官:不錯不錯,明天去保安大隊報道

狗蛋:???

投遞簡歷砸我郵箱 yangyz1@guahao.com


接近明年的跳槽期又近了一步,如今不抓緊何時抓緊,關注我,微醫保你在求職路上藥到病除,一路飛昇

素質四連,點贊、關注、轉發、評論

瞭解更多,關注技術公衆號:ihap 技術黑洞 !!!

相關文章
相關標籤/搜索