關(guān)于性能優(yōu)化 近8000字總結(jié)

在互聯(lián)網(wǎng)發(fā)展的當(dāng)下,webApp 項(xiàng)目越來(lái)越大,需求越來(lái)越繁重,功能越來(lái)越大,導(dǎo)致代碼打包體積越來(lái)越大,
頁(yè)面的打開(kāi)速度,頁(yè)面的流暢度 ,用戶體驗(yàn)也是一項(xiàng)對(duì)產(chǎn)品的考核標(biāo)準(zhǔn)之一,性能優(yōu)化也是前端開(kāi)發(fā)的必要工作。
對(duì)于性能優(yōu)化我們 通過(guò)工程化、加載、代碼優(yōu)化等方面分開(kāi)講解。
性能優(yōu)化核心 就是”小“字為先

工程化

打包

資源壓縮

代碼壓縮可以減少代碼體積,節(jié)約帶寬,提高下載速度
在線壓縮工具

  1. 壓縮:刪除 Javascript 代碼中所有注釋、跳格符號(hào)、換行符號(hào)及無(wú)用的空格,從而壓縮 JS 文件大小。
  2. 混淆:經(jīng)過(guò)編碼將變量和函數(shù)原命名改為毫無(wú)意義的命名,以防止他人窺視和竊取 Javascript 源代碼。
webpack 配置壓縮
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

optimization: {
    minimizer: [ // 用于配置 minimizers 和選項(xiàng)
        new UglifyJsPlugin({
            cache: true,
            parallel: true,
            sourceMap: true // set to true if you want JS source maps
        }),
        new OptimizeCSSAssetsPlugin({})
    ]
}

tree shaking

tree-shaking可以理解為通過(guò)工具"搖"我們的JS文件,將其中用不到的代碼"搖"掉,是一個(gè)性能優(yōu)化的范疇

  1. webpack4 通過(guò)設(shè)置mode就可以支持 tree shaking
module.exports = {
   mode: 'production',
   }

注:webpack自身的Tree-shaking不能分析副作用的模塊

  1. webpack-deep-scope-plugin: 這個(gè)插件主要用于填充webpack4自身Tree-shaking的不足,通過(guò)作用域分析來(lái)消除無(wú)用的代碼 在線演示demo

  2. webpack5 tree shaking

module.exports = {
   optimization: {
       usedExports: true, // 識(shí)別無(wú)用代碼
       minimize: true,    // 將無(wú)用代碼在打包中刪除
       concatenateModules: true, // 盡可能將所有模塊合并輸出到一個(gè)函數(shù)中
   }
}

  1. eslint-plugin-you-dont-need-momentjs
    如果你正在使用ESLint,你可以安裝一個(gè)插件來(lái)幫助你識(shí)別你代碼庫(kù)中不需要(可能不需要)Moment.js的地方。

按需加載

首屏的加載很重要,對(duì)與SPA的項(xiàng)目來(lái)說(shuō),如果是大文件,使用按需加載就十分合適。比如一個(gè)近1M的全國(guó)城市省市縣的js文件,在我首屏加載的時(shí)候并不需要引入,而是當(dāng)用戶點(diǎn)擊選項(xiàng)的時(shí)候才加載。如果不點(diǎn)擊,則不會(huì)加載。就可以縮短首屏http請(qǐng)求的數(shù)量以及時(shí)間。

代碼拆分

在互聯(lián)網(wǎng)發(fā)展的當(dāng)下,webApp 項(xiàng)目越來(lái)越大,文件體積過(guò)大是很影響性能的一項(xiàng)。特別是對(duì)于移動(dòng)端的設(shè)備而言簡(jiǎn)直是災(zāi)難。
此外對(duì)于某些只要特定環(huán)境下才需要的代碼,一開(kāi)始就加載進(jìn)來(lái)顯然也不那么合理,這就引出了按需加載的概念了。為了解決這些情況,代碼拆分就應(yīng)運(yùn)而生了。代碼拆分故名思意就是將大的文件按不同粒度拆分,以滿足解決生成文件體積過(guò)大、按需加載等需求。

webpack代碼拆分

webpack通過(guò)一下三種方式實(shí)現(xiàn)了代碼拆分方式

  1. 多入口分開(kāi)打包
  2. 去重,抽離公共模塊和第三方庫(kù)
  3. 動(dòng)態(tài)加載
clean-css

uncss( 去除無(wú)用的 css)Simply UnCSS your styles online!

加載優(yōu)化

關(guān)于加載優(yōu)化,我們首先需要明確幾個(gè)瀏覽器的重要性能指標(biāo),參考可參考 performance

  1. TTFB(Time to First Byte): 表示瀏覽器接收第一個(gè)字節(jié)的時(shí)間
  2. FP(First Paint):頁(yè)面的反應(yīng),第一個(gè)像素點(diǎn)落地 background:#ddd;看的見(jiàn)
    頁(yè)面在導(dǎo)航后首次呈現(xiàn)出不同于導(dǎo)航前內(nèi)容的時(shí)間點(diǎn).當(dāng)瀏覽器開(kāi)始渲染頁(yè)面,白屏觸發(fā),這時(shí)候你如果設(shè)置了背景顏色的話,就可以看到頁(yè)面出現(xiàn)了背景色
  3. FCP(First Contentful Paint):首次繪制頁(yè)面“主要內(nèi)容”的時(shí)間點(diǎn)。
  4. FMP(First Meaningful Paint):首次繪制頁(yè)面“主要內(nèi)容”的時(shí)間點(diǎn)。 有意義的繪制 (自定義的)
  5. DCL(DOMContentLoaded): 表示 HTML 加載完成事件, L(onLoad) 表示頁(yè)面所有資源加載完成事件
  6. LCP(Largest Contentful Paint):第一個(gè)繪制的最大內(nèi)容 可視區(qū)域“內(nèi)容”最大的可見(jiàn)元素開(kāi)始出現(xiàn)在頁(yè)面上的時(shí)間點(diǎn)。
  7. CLS(Cumulative Layout Shift): 表示用戶經(jīng)歷的意外 layout 偏移的頻率。
  8. TBT(Total Blocking Time): 表示從 FCP 到 TTI 之間,所有 long task 的阻塞時(shí)間之和
  9. TTi(Time to Interactive):頁(yè)面可交互

performance timing

performance.timing:是一系列關(guān)鍵時(shí)間點(diǎn),它包含了網(wǎng)絡(luò)、加載、解析等一系列的時(shí)間數(shù)據(jù)。
通過(guò)下圖來(lái)解析下各個(gè)關(guān)鍵時(shí)間點(diǎn)的含義如下所示:


pageload-1886-93237e4321.png
  1. navigationStart 瀏覽器窗口的前一個(gè)網(wǎng)頁(yè)關(guān)閉時(shí)發(fā)生 unload 事件時(shí)的 Unix 時(shí)間戳,屬于最前的測(cè)量時(shí)間點(diǎn)
  2. unloadEventStart 前網(wǎng)頁(yè)與當(dāng)前網(wǎng)頁(yè)同屬一個(gè)域名時(shí),返回前一個(gè)網(wǎng)頁(yè)的 unload 事件發(fā)生時(shí)的 Unix 時(shí)間戳
  3. unloadEventEnd 前網(wǎng)頁(yè)與當(dāng)前網(wǎng)頁(yè)同屬一個(gè)域名時(shí),返回前一個(gè)網(wǎng)頁(yè) unload 事件的回調(diào)函數(shù)結(jié)束時(shí)的 Unix 時(shí)間戳
  4. redirectStart 返回第一個(gè) HTTP 跳轉(zhuǎn)開(kāi)始時(shí)的 Unix 時(shí)間戳
  5. redirectEnd 返回最后一個(gè) HTTP 跳轉(zhuǎn)結(jié)束時(shí)的 Unix 時(shí)間戳
  6. fetchStart 返回瀏覽器準(zhǔn)備使用 HTTP 請(qǐng)求讀取文檔等資源時(shí)的 Unix 時(shí)間戳,在網(wǎng)頁(yè)查詢本地緩存之前發(fā)生
  7. domainLookupStart 返回域名查詢開(kāi)始時(shí)的 Unix 時(shí)間戳。如果使用持久連接,或者信息是從本地緩存獲取的,則返回值等同于 fetchStart 屬性的值
  8. domainLookupEnd 返回域名查詢結(jié)束時(shí)的 Unix 毫秒時(shí)間戳。如果使用持久連接,或者信息是從本地緩存獲取的,則返回值等同于 fetchStart 屬性的值
  9. connectStart 返回 HTTP 請(qǐng)求開(kāi)始向服務(wù)器發(fā)送時(shí)的 Unix 毫秒時(shí)間戳。如果使用持久連接(persistent connection),則返回值等同于 fetchStart 屬性的值
  10. connectEnd 返回瀏覽器與服務(wù)器之間的連接建立時(shí)的 Unix 毫秒時(shí)間戳。如果建立的是持久連接,則返回值等同于 fetchStart 屬性的值。連接建立指的是所有握手和認(rèn)證過(guò)程全部結(jié)束
  11. secureConnectionStart 返回瀏覽器與服務(wù)器開(kāi)始安全鏈接的握手時(shí)的 Unix 毫秒時(shí)間戳。如果當(dāng)前網(wǎng)頁(yè)不要求安全連接,則返回 0
  12. requestStart 返回瀏覽器向服務(wù)器發(fā)出 HTTP 請(qǐng)求時(shí)(或開(kāi)始讀取本地緩存時(shí))的 Unix 毫秒時(shí)間戳
  13. responseStart 返回瀏覽器從服務(wù)器收到(或從本地緩存讀?。┑谝粋€(gè)字節(jié)時(shí)的 Unix 毫秒時(shí)間戳
  14. responseEnd 返回瀏覽器從服務(wù)器收到(或從本地緩存讀?。┳詈笠粋€(gè)字節(jié)時(shí)(如果在此之前 HTTP 連接已經(jīng)關(guān)閉,則返回關(guān)閉時(shí))的 Unix 毫秒時(shí)間戳
  15. domLoading 返回當(dāng)前網(wǎng)頁(yè) DOM 結(jié)構(gòu)開(kāi)始解析時(shí)(即 Document.readyState 屬性變?yōu)椤發(fā)oading”、相應(yīng)的 readystatechange 事件觸發(fā)時(shí))的 Unix 毫秒時(shí)間戳
  16. domInteractive 返回當(dāng)前網(wǎng)頁(yè) DOM 結(jié)構(gòu)結(jié)束解析、開(kāi)始加載內(nèi)嵌資源時(shí)(即 Document.readyState 屬性變?yōu)椤癷nteractive”、相應(yīng)的 readystatechange 事件觸發(fā)時(shí))的 Unix 毫秒時(shí)間戳
  17. domContentLoadedEventStart 返回當(dāng)前網(wǎng)頁(yè) DOMContentLoaded 事件發(fā)生時(shí)(即 DOM 結(jié)構(gòu)解析完畢、所有腳本開(kāi)始運(yùn)行時(shí))的 Unix 毫秒時(shí)間戳
  18. domContentLoadedEventEnd 返回當(dāng)前網(wǎng)頁(yè)所有需要執(zhí)行的腳本執(zhí)行完成時(shí)的 Unix 毫秒時(shí)間戳
  19. domComplete 返回當(dāng)前網(wǎng)頁(yè) DOM 結(jié)構(gòu)生成時(shí)(即 Document.readyState 屬性變?yōu)椤癱omplete”,以及相應(yīng)的 readystatechange 事件發(fā)生時(shí))的 Unix 毫秒時(shí)間戳
  20. loadEventStart 返回當(dāng)前網(wǎng)頁(yè) load 事件的回調(diào)函數(shù)開(kāi)始時(shí)的 Unix 毫秒時(shí)間戳。如果該事件還沒(méi)有發(fā)生,返回 0
  21. loadEventEnd 返回當(dāng)前網(wǎng)頁(yè) load 事件的回調(diào)函數(shù)運(yùn)行結(jié)束時(shí)的 Unix 毫秒時(shí)間戳。如果該事件還沒(méi)有發(fā)生,返回 0
一個(gè)網(wǎng)頁(yè)加載的時(shí)間周期
perfor05.png

關(guān)鍵的指標(biāo)性能計(jì)算

  1. 上個(gè)頁(yè)面的到這個(gè)頁(yè)面的時(shí)長(zhǎng) fetchStartfet-navigationStart
  2. 重定向時(shí)常 : redirectEnd-redirectStart
  3. DNS 查詢耗時(shí) :domainLookupEnd - domainLookupStart
  4. TCP 鏈接耗時(shí) :connectEnd - connectStart
  5. request 請(qǐng)求耗時(shí) :responseEnd - responseStart
  6. 解析 dom 樹(shù)耗時(shí) : domComplete - domInteractive
  7. 白屏?xí)r間 :responseStart - navigationStart
  8. domready 時(shí)間(用戶可操作時(shí)間節(jié)點(diǎn)) :domContentLoadedEventEnd - navigationStart
  9. onload 時(shí)間(總下載時(shí)間) :loadEventEnd - navigationStart

優(yōu)化的時(shí)間可參考web.dev

網(wǎng)絡(luò)

QPS即每秒查詢率,是對(duì)一個(gè)特定的查詢服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)。
QPS = 并發(fā)量 / 平均響應(yīng)時(shí)間
合理計(jì)算 QPS 未雨綢繆

開(kāi)啟 cnd 加速(并行最多 5 個(gè))。節(jié)約 cookie 帶寬 節(jié)約主域名的連接數(shù),優(yōu)化頁(yè)面響應(yīng)速度
開(kāi)啟頁(yè)面懶加載
緩存靜態(tài)資源文件 localstrage
nginx:
nginx 開(kāi)啟 gzip 壓縮 etag expires 緩存
nginx 開(kāi)啟 反向代理 負(fù)載均衡

(html webpsack plugin)
preload 提前加載
prefetch 預(yù)判加載
Preconnect 預(yù)解析

DNS預(yù)解析

DNS

域名系統(tǒng)(英文:Domain Name System,縮寫:DNS)是互聯(lián)網(wǎng)的一項(xiàng)服務(wù)。它作為將域名和 IP 地址相互映射的一個(gè)分布式數(shù)據(jù)庫(kù),能夠使人更方便地訪問(wèn)互聯(lián)網(wǎng)。

dns-prefetch域名解析:從域名查詢IP的過(guò)程,這個(gè)過(guò)程一般都很快的,但也會(huì)引起延遲。一般瀏覽器會(huì)適當(dāng)?shù)膶?duì)解析結(jié)果緩存,并對(duì)頁(yè)面中出現(xiàn)的新域名進(jìn)行預(yù)解析,但并不是所有的瀏覽器都會(huì)這么做,為了幫助其它瀏覽器對(duì)某些域名進(jìn)行預(yù)解析,你可以在頁(yè)面的html標(biāo)簽中添加dns-prefetch告訴瀏覽器對(duì)指定域名預(yù)解析

典型的一次DNS解析需要耗費(fèi) 20-120 毫秒,減少DNS解析時(shí)間和次數(shù)是個(gè)很好的優(yōu)化方式

DNS解析方式

瀏覽器對(duì)網(wǎng)站第一次的域名DNS解析查找流程依次為:瀏覽器緩存——系統(tǒng)緩存——路由器緩存——ISP DNS緩存——遞歸搜索

24172033-6952f84c4e7140839d3e6866eb0c0613.png
<!--用meta信息來(lái)告知瀏覽器, 當(dāng)前頁(yè)面要做DNS預(yù)解析-->
<meta http-equiv="x-dns-prefetch-control" content="on" /> 
<!--在頁(yè)面header中使用link標(biāo)簽來(lái)強(qiáng)制對(duì)DNS預(yù)解析-->
<link rel="dns-prefetch"  />

CDN

CDN 的全稱是 Content Delivery Network,即內(nèi)容分發(fā)網(wǎng)絡(luò)。CDN 是構(gòu)建在現(xiàn)有網(wǎng)絡(luò)基礎(chǔ)之上的智能虛擬網(wǎng)絡(luò),依靠部署在各地的邊緣服務(wù)器,通過(guò)中心平臺(tái)的負(fù)載均衡、內(nèi)容分發(fā)、調(diào)度等功能模塊,使用戶就近獲取所需內(nèi)容,降低網(wǎng)絡(luò)擁塞,提高用戶訪問(wèn)響應(yīng)速度和命中率。CDN 的關(guān)鍵技術(shù)主要有內(nèi)容存儲(chǔ)和分發(fā)技術(shù)

緩存刷新

源站內(nèi)容更新后,希望用戶可以獲取到最新資源,CDN 租戶可以通過(guò)提交刷新請(qǐng)求將 CDN 節(jié)點(diǎn)上指定的緩存內(nèi)容強(qiáng)制過(guò)期。當(dāng)用戶再次訪問(wèn)時(shí),CDN 節(jié)點(diǎn)將回源獲取已更新內(nèi)容返回給用戶并在節(jié)點(diǎn)緩存最新資源。(簡(jiǎn)單來(lái)說(shuō)就是刪除 cdn 各節(jié)點(diǎn)上的緩存,有用戶獲取文件的時(shí)候,直接回源取文件?。?/p>

緩存預(yù)熱

提交指定資源的緩存預(yù)熱請(qǐng)求后,對(duì)應(yīng)源站資源將分發(fā)到 CDN 節(jié)點(diǎn),當(dāng)用戶發(fā)起訪問(wèn)請(qǐng)求時(shí),可以直接從 CDN 節(jié)點(diǎn)獲取,有效地降低了回源率。(簡(jiǎn)單來(lái)說(shuō)就是直接從源站下發(fā)文件到 cdn 各節(jié)點(diǎn)上的緩存,有用戶獲取文件的時(shí)候就可以直接取到最新文件!)

HTTP

keep-alive

在早期的HTTP/1.0中,每次http請(qǐng)求都要?jiǎng)?chuàng)建一個(gè)連接,而創(chuàng)建連接的過(guò)程需要消耗資源和時(shí)間,為了減少資源消耗,縮短響應(yīng)時(shí)間,就需要重用連接。在后來(lái)的HTTP/1.0中以及HTTP/1.1中,引入了重用連接的機(jī)制,就是在http請(qǐng)求頭中加入Connection: keep-alive來(lái)告訴對(duì)方這個(gè)請(qǐng)求響應(yīng)完成后不要關(guān)閉,下一次咱們還用這個(gè)請(qǐng)求繼續(xù)交流。協(xié)議規(guī)定HTTP/1.0如果想要保持長(zhǎng)連接,需要在請(qǐng)求頭中加上Connection: keep-alive,而HTTP/1.1默認(rèn)是支持長(zhǎng)連接的,有沒(méi)有這個(gè)請(qǐng)求頭都行

http2.0

HTTP2.0大幅度的提高了web性能,在HTTP1.1完全語(yǔ)義兼容的基礎(chǔ)上,進(jìn)一步減少了網(wǎng)絡(luò)的延遲。實(shí)現(xiàn)低延遲高吞吐量。對(duì)于前端開(kāi)發(fā)者而言,減少了優(yōu)化工作,http2.0請(qǐng)求demo。

http2.0優(yōu)勢(shì)

  1. 二進(jìn)制分幀:在應(yīng)用層(HTTP/2)和傳輸層(TCP or UDP)之間增加一個(gè)二進(jìn)制分幀層,HTTP/2 會(huì)將所有傳輸?shù)男畔⒎指顬楦〉南⒑蛶╢rame),并對(duì)它們采用二進(jìn)制格式的編碼 。
  2. 首部壓縮:HTTP/2 使用了專門為首部壓縮而設(shè)計(jì)的 HPACK 算法,達(dá)到請(qǐng)求頭壓縮的目的。
  3. 多路復(fù)用:多路復(fù)用允許同時(shí)通過(guò)單一的 HTTP/2 連接發(fā)起多重的請(qǐng)求-響應(yīng)消息
  4. 請(qǐng)求優(yōu)先級(jí):把HTTP消息分為很多獨(dú)立幀之后,就可以通過(guò)優(yōu)化這些幀的交錯(cuò)和傳輸順序進(jìn)一步優(yōu)化性能
  5. 服務(wù)器推送:服務(wù)端推送是一種在客戶端請(qǐng)求之前發(fā)送數(shù)據(jù)的機(jī)制

Nginx

nginx:是一個(gè)高性能的HTTP和反向代理web服務(wù)器,同時(shí)也提供了IMAP/POP3/SMTP服務(wù)。

緩存

強(qiáng)緩存

Expires: 頭能有效的利用瀏覽器的緩存能力來(lái)改善頁(yè)面的性能,能在后續(xù)的頁(yè)面中有效避免很多不必要的Http請(qǐng)求,WEB服務(wù)器使用Expires頭來(lái)告訴Web客戶端它可以使用一個(gè)組件的當(dāng)前副本,直到指定的時(shí)間為止,Expires有一個(gè)非常大的缺陷,它使用一個(gè)固定的時(shí)間,要求服務(wù)器與客戶端的時(shí)鐘保持嚴(yán)格的同步,并且這一天到來(lái)后,服務(wù)器還得重新設(shè)定新的時(shí)間。

Cathe-Control:http1.1 引入,它使用max-age指定組件被緩存多久,從請(qǐng)求開(kāi)始在max-age時(shí)間內(nèi)瀏覽器使用緩存,之外的使用請(qǐng)求,這樣就可以消除Expires的限制,

注: Cache-Control(1.1版本) 的優(yōu)先級(jí)高于 Expires(1.0 版本)

協(xié)商緩存

etag:數(shù)據(jù)簽名,資源內(nèi)容會(huì)對(duì)應(yīng)有一個(gè)唯一的簽名(sha1),如果資源數(shù)據(jù)更改,簽名也會(huì)變。配合If-Match或者If-None-Match使用,

last-modified:上次修改時(shí)間(精確到秒),配合If-Modified-Since或If-Unmodified-Since使用,通常瀏覽器使用If-Modified-Since

瀏覽器緩存流程圖

nginx03.png

開(kāi)啟gzip

GZIP是若干文件壓縮程序的簡(jiǎn)稱,通常指GNU計(jì)劃的實(shí)現(xiàn),此處的GZIP代表的就是GUN ZIP,這也是HTTP1.1協(xié)議定義的兩種壓縮方法中最常用的一種壓縮方法,客戶端瀏覽器大都支持這種壓縮格式。

  gzip on;
  gzip_static on; //靜態(tài)資源
  gzip_vary on;  //是否在 http header 中添加 Vary: Accept-Encoding,建議開(kāi)啟
  gzip_comp_level 5; //(建議) gzip 壓縮比,1 壓縮比最小處理速度最快,9 壓縮比最大但處理最慢(傳輸快但比較消耗 cpu)
  gzip_min_length 0 ; //默認(rèn)值是 0,不管頁(yè)面多大都?jí)嚎s。 建議設(shè)置成大于 1k 的字節(jié)數(shù),小于 1k 可能會(huì)越壓越大
  gzip_http_version 1.1; //版本信息
  gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

負(fù)載均衡

upstream web_mgrsys {
    server 127.0.0.1:8090 weight=10;
    server 127.0.0.1:3000 weight=3;
}
proxy_pass http://web_mgrsys;

可參考 幸福拾荒者文檔

預(yù)加載

  1. prefetch: 它的作用是告訴瀏覽器加載下一頁(yè)面可能會(huì)用到的資源,注意,是下一頁(yè)面,而不是當(dāng)前頁(yè)面。因此該方法的加載優(yōu)先級(jí)非常低,也就是說(shuō)該方式的作用是加速下一個(gè)頁(yè)面的加載速度

  2. preload: 提供了一種聲明式的命令,讓瀏覽器提前加載指定資源(加載后并不執(zhí)行),需要執(zhí)行時(shí)再執(zhí)行

    1、將加載和執(zhí)行分離開(kāi),不阻塞渲染和document的onload事件
    2、提前加載指定資源,不再出現(xiàn)依賴的font字體隔了一段時(shí)間才刷出的情況

async & defer

284aec5bb7f16b3ef4e7482110c5ddbb_fix732.jpeg

藍(lán)色線代表網(wǎng)絡(luò)讀取,紅色線代表執(zhí)行時(shí)間,綠色線代表 HTML 解析。

  1. async:加載和渲染后續(xù)文檔元素的過(guò)程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)
  2. defer:加載后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成,并且多個(gè) defer 會(huì)按照順序進(jìn)行加載。

代碼優(yōu)化

雅虎軍規(guī)

雅虎軍規(guī):無(wú)論是在工作中,還是在面試中,web 前端性能的優(yōu)化都是很重要的,那么我們進(jìn)行優(yōu)化需要從哪些方面入手呢?可以遵循雅虎的前端優(yōu)化 34 條軍規(guī),不過(guò)現(xiàn)在已經(jīng)是 35 條了,所以可以說(shuō)是雅虎前端優(yōu)化的 35 條軍規(guī)。已經(jīng)分類,這樣對(duì)于優(yōu)化有一個(gè)比較清晰的方向。

js

js優(yōu)化方案

  1. 精簡(jiǎn) js 代碼 巧用數(shù)據(jù)結(jié)構(gòu)與算法
  2. 避免內(nèi)存泄漏,避免全局變量、閉包、降低循環(huán)
  3. 脫離的 dom 元素及時(shí)清理其綁定的事件

css

Reflow (重排)

當(dāng)涉及到DOM節(jié)點(diǎn)的布局屬性發(fā)生變化時(shí),就會(huì)重新計(jì)算該屬性,瀏覽器會(huì)重新描繪相應(yīng)的元素,此過(guò)程叫 回流(Reflow)

Repaint(重繪)

當(dāng)影響DOM元素可見(jiàn)性的屬性發(fā)生變化 (如 color) 時(shí), 瀏覽器會(huì)重新描繪相應(yīng)的元素, 此過(guò)程稱為 重繪(Repaint)。因此重排必然會(huì)引起重繪。

1414709-20181115192855608-1989140804.png
重排觸發(fā)機(jī)制
  1. 添加或刪除可見(jiàn)的DOM元素
  2. 元素位置改變
  3. 元素本身的尺寸發(fā)生改變
  4. 內(nèi)容改變
  5. 頁(yè)面渲染器初始化
  6. 瀏覽器窗口大小發(fā)生改變
重繪觸發(fā)機(jī)制
  1. 背景顏色樣式修改

重繪&重排優(yōu)化方式

  1. 對(duì)需要修改的dome,盡量使用文檔片段一次插入頁(yè)面
  2. 對(duì)動(dòng)畫盡量使用css3 動(dòng)畫,開(kāi)啟動(dòng)畫的GPU加速,把渲染計(jì)算交給GPU。
    本文原創(chuàng)發(fā)布于慕課網(wǎng) ,轉(zhuǎn)載請(qǐng)注明出處,謝謝合作
  3. 將需要多次重排的元素,position屬性設(shè)為absolute或fixed,元素脫離了文檔流,它的變化不會(huì)影響到其他元素

css 優(yōu)化方案

  1. 降低層級(jí)復(fù)雜度 減少css層級(jí)嵌套
  2. 降低渲染阻塞
  3. 使用css3動(dòng)畫 開(kāi)啟3d加速,減少動(dòng)畫對(duì)頁(yè)面的重排重繪
  4. contain:layout
  5. 隱藏元素使用display為none,
  6. 將需要多次重排的元素,position屬性設(shè)為absolute或fixed,元素脫離了文檔流,它的變化不會(huì)影響到其他元素

html

  1. iframe 延遲加載
  2. 壓縮刪除注釋 html-minifier :HTMLMinifier is a highly configurable, well-tested, JavaScript-based HTML minifier.
  3. 降低節(jié)點(diǎn)過(guò)渡嵌套
  4. css javascript 盡量外鏈

font

字體優(yōu)化方式

font-display:auto
auto:默認(rèn)值。典型的瀏覽器字體加載的行為會(huì)發(fā)生,也就是使用自定義字體的文本會(huì)先被隱藏,直到字體加載結(jié)束才會(huì)顯示。著作權(quán)歸作者所有。

  1. block: 阻塞等字體下載完成在顯示 3s
  2. swap:默認(rèn)字體-后期替換
  3. Fallback:不顯示
  4. optional:移動(dòng)端 默認(rèn) 或者自定義

圖片

1.tiny 在線壓縮圖片工具
https://tinyjpg.com/

圖片 imagemin

漸進(jìn)式圖片方式:baseline jpeg 一次將圖像由左到右、由上到下順序處理。當(dāng)您的 JPEG 圖像低于 10K 時(shí),最好保存為基本 JPEG(估計(jì)有 75%的可能性會(huì)更?。?/p>

20190228235251249.gif

Progressive jpeg 當(dāng)圖像傳輸?shù)臅r(shí)間較長(zhǎng)時(shí),可將圖像分?jǐn)?shù)次處理,以從模糊到清晰的方式來(lái)傳送圖像(效果類似 GIF 在網(wǎng)絡(luò)上的傳輸)。

20190228235302963.gif

圖片優(yōu)化npm依賴包

  1. Progressive-image
    : A dead simple progressive-image module for Vanilla JavaScript and Vue.js 1.0+ & 2.0+ progressive-image-demo

  2. ImageMagick: 是一套功能強(qiáng)大、穩(wěn)定而且開(kāi)源的工具集和開(kāi)發(fā)包,可以用來(lái)讀、寫和處理超過(guò) 89 種基本格式的圖片文件,包括流行的 TIFF、JPEG、GIF、 PNG、PDF 以及 PhotoCD 等格式。利用 ImageMagick,你可以根據(jù) web 應(yīng)用程序的需要?jiǎng)討B(tài)生成圖片, 還可以對(duì)一個(gè)(或一組)圖片進(jìn)行改變大小、旋轉(zhuǎn)、銳化、減色或增加特效等操作,并將操作的結(jié)果以相同格式或其它格式保存,對(duì)圖片的操作,即可以通過(guò)命令行進(jìn)行,也可以用 C/C++、Perl、Java、PHP、Python 或 Ruby 編程來(lái)完成。同時(shí) ImageMagick 提供了一個(gè)高質(zhì)量的 2D 工具包,部分支持 SVG。ImageMagic 的主要精力集中在性能,減少 bug 以及提供穩(wěn)定的 API 和 ABI 上。

  3. jpeg-recompress:Compress JPEGs by re-encoding to the smallest JPEG quality while keeping perceived visual quality the same and by making sure huffman tables are optimized

  4. imagemin:Minify images seamlessly

  5. yall.js

  6. BlazyA lazy loading and multi-serving image script 演示demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 寫在前面 本文來(lái)自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iO...
    seeek閱讀 589評(píng)論 0 0
  • 參考自:https://www.tuicool.com/articles/J3uyaa# 前端性能優(yōu)化總共分 7 ...
    晴天的晴q閱讀 241評(píng)論 0 0
  • 前言: 在同樣的網(wǎng)絡(luò)環(huán)境下,兩個(gè)同樣能滿足你的需求的網(wǎng)站,一個(gè)“Duang”的一下就加載出來(lái)了,一個(gè)糾結(jié)了半天才出...
    han2019閱讀 475評(píng)論 0 1
  • 簡(jiǎn)介 前端優(yōu)化的目的是什么 ? 從用戶角度而言,優(yōu)化能夠讓頁(yè)面加載得更快、對(duì)用戶的操作響應(yīng)得更及時(shí),能夠給用戶提供...
    JuanitaLee閱讀 883評(píng)論 0 5
  • 什么是前端性能優(yōu)化(what)? 從用戶訪問(wèn)資源到資源完整的展現(xiàn)在用戶面前的過(guò)程中,通過(guò)技術(shù)手段和優(yōu)化策略,縮短每...
    我性本傲閱讀 3,591評(píng)論 0 3

友情鏈接更多精彩內(nèi)容