精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從前端性能優(yōu)化引申出來的5道經(jīng)典面試題

開發(fā) 前端
前端優(yōu)化是一個大的課題,需要花好多時間才能理解,之前對前端優(yōu)化陸陸續(xù)續(xù)有一些了解。所以這次從渲染優(yōu)化,打包優(yōu)化,代碼優(yōu)化做了一個系統(tǒng)的總結(jié),并且引申出了幾個需要關(guān)注的問題。

[[351581]]

前端優(yōu)化是一個大的課題,需要花好多時間才能理解,之前對前端優(yōu)化陸陸續(xù)續(xù)有一些了解。所以這次從渲染優(yōu)化,打包優(yōu)化,代碼優(yōu)化做了一個系統(tǒng)的總結(jié),并且引申出了幾個需要關(guān)注的問題,文章可能有點(diǎn)長,大家一定要看到最后。最后寫作不易,希望覺得還可以的話,幫忙點(diǎn)贊一波,提前感謝了。當(dāng)然如果有寫不好的地方,也請指出來,我會積極改進(jìn),共同成長。

渲染優(yōu)化

渲染優(yōu)化是前端優(yōu)化中一個很重要的部分,一個好的首屏?xí)r間能給用戶帶來很好的體驗(yàn),這里要說的一點(diǎn)是關(guān)于首屏?xí)r間的定義,不同的團(tuán)隊(duì)對首屏?xí)r間定義不一樣,有的團(tuán)隊(duì)認(rèn)為首屏?xí)r間就是白屏?xí)r間,是從頁面加載到第一個畫面出現(xiàn)的時間。但是當(dāng)我們說到用戶體驗(yàn)的時候,僅僅是這樣還達(dá)不到效果,所以有的前端團(tuán)隊(duì)認(rèn)為,首屏?xí)r間應(yīng)該是從頁面加載到用戶可以進(jìn)行正常的頁面操作時間,那么我們就依照后者來進(jìn)行說明

js css 加載順序

說渲染優(yōu)化之前,我們還需要說一個小插曲,就是比較經(jīng)典的一道問題"瀏覽器地址欄輸入url發(fā)生了什么",理解了這個我們才可以更清楚js,css加載順序?qū)︿秩镜挠绊?/p>

問題 1:地址欄輸入url 發(fā)生了什么

這個問題經(jīng)常被人提起,有人回答比較簡潔點(diǎn),有人可能回答的比較詳細(xì),下面就說一下主要流程

  •  首先會進(jìn)行 url 解析,根據(jù) dns 系統(tǒng)進(jìn)行 ip 查找
  •  根據(jù) ip 就可以找到服務(wù)器,然后瀏覽器和服務(wù)器會進(jìn)行 TCP 三次握手建立連接,如果此時是 https 的話,還會建立 TLS 連接以及協(xié)商加密算法,這里就會出現(xiàn)另一個需要注意的問題"https 和 http 的區(qū)別"(下文會講到)
  •     連接建立之后瀏覽器開始發(fā)送請求獲取文件,此時這里還會出現(xiàn)一種情況就是緩存,建立連接后是走緩存還是直接重新獲取,需要看后臺設(shè)置,所以這里會有一個關(guān)注的問題"瀏覽器緩存機(jī)制",緩存我們等會在講,現(xiàn)在我們就當(dāng)沒有緩存,直接去獲取文件
  •  首先獲取 html 文件,構(gòu)建 DOM 樹,這個過程是邊下載邊解析,并不是等 html 文件全部下載完了,再去解析 html,這樣比較浪費(fèi)時間,而是下載一點(diǎn)解析一點(diǎn)
  •  好了解析到 html 頭部時候,又會出現(xiàn)一種問題,css,js 放到哪里了?不同的位置會造成渲染的不同,此時就會出現(xiàn)另一個需要關(guān)注的問題"css,js 位置應(yīng)該放哪里?為什么",我們先按照正確的位置來說明(css 放頭部,js 放尾部)
  •  解析到了 html 頭部發(fā)現(xiàn)有 css 文件,此時下載 css 文件,css 文件也是一邊下載一邊解析的,構(gòu)建的是 CSSOM 樹,當(dāng) DOM 樹和 CSSOM 樹全部構(gòu)建完之后,瀏覽器會把 DOM 樹和 CSSOM 樹構(gòu)建成渲染樹。
  •  樣式計(jì)算, 上面最后一句"DOM 樹和 CSSOM 樹會一起構(gòu)建成渲染樹"說的有點(diǎn)籠統(tǒng),其實(shí)還有更細(xì)一點(diǎn)的操作,但是一般回答到上面應(yīng)該就可以了,我們現(xiàn)在接上面說一下構(gòu)造渲染樹的時候還做了哪些事情。第一個就是樣式計(jì)算,DOM樹 和 CSSOM樹有了之后,瀏覽器開始樣式計(jì)算,主要是為 DOM 樹上的節(jié)點(diǎn)找到對應(yīng)的樣式
  •  構(gòu)建布局樹,樣式計(jì)算完之后就開始構(gòu)建布局樹。主要是為 DOM 樹上的節(jié)點(diǎn)找到頁面上對應(yīng)位置以及一些"display:none"元素的隱藏。
  •  構(gòu)建分層樹,布局樹完成后瀏覽器還需要建立分層樹,主要是為了滿足滾動條,z-index,position 這些復(fù)雜的分層操作
  •  將分層樹圖塊化,利用光柵找到視圖窗口下的對應(yīng)的位圖。主要是因?yàn)橐粋€頁面可能有幾屏那么長,一下渲染出來比較浪費(fèi),所以瀏覽器會找到視圖窗口對應(yīng)的圖塊,將這部分的圖塊進(jìn)行渲染
  •  最終渲染進(jìn)程將整個頁面渲染出來,在渲染的過程中會還出現(xiàn)重排和重繪,這也是比較愛問的問題"重排重繪為什么會影響渲染,如何避免?"
  •  以上過程大概講解了一下從 url 到頁面渲染的整個過程,其實(shí)涉及到了幾個需要關(guān)注的問題,下面來具體講講

問題 2:js css 順序?qū)η岸藘?yōu)化影響

上面我們說到了整個渲染流程,但是沒有說到 css 和 js 對渲染的影響。渲染樹的構(gòu)成必須要 DOM 樹和 CSSOM 樹的,所以盡快的構(gòu)建 CSSOM 樹是一個重要的優(yōu)化手段,如果 css 文件放在尾部,那么整個過程就是一個串行的過程先解析了 dom,再去解析 css。所以 css 我們一般都是放在頭部,這樣 DOM 樹和 CSSOM 樹的構(gòu)建是同步進(jìn)行的。

再來看 js,因?yàn)?js 的運(yùn)行會阻止 DOM 樹的渲染的,所以一旦我們的 js 放在了頭部,而且也沒有異步加載這些操作的話,js 一旦一直在運(yùn)行,DOM 樹就一直構(gòu)建不出來,那么頁面就會一直出現(xiàn)白屏界面,所以一般我們會把 js 文件放在尾部。當(dāng)然放到尾部也不是就沒有問題了,只是問題相對較小,放到尾部的 js 文件如果過大,運(yùn)行時間長,代碼加載時,就會有大量耗時的操作造成頁面不可點(diǎn)擊,這就是另一個問題,但這肯定比白屏要好,白屏是什么頁面都沒有,這種是頁面有了只是操作不流暢。

js 腳本放在尾部還有一個原因,有時候 js 代碼會有操作 dom 節(jié)點(diǎn)的情況,如果放在頭部執(zhí)行,DOM樹還沒有構(gòu)建,拿不到 DOM 節(jié)點(diǎn)但是你又去使用就會出現(xiàn)報(bào)錯情況,錯誤沒處理好的話頁面會直接崩掉

問題 3:重排重繪為什么會影響渲染,如何避免?

重排和重繪為什么會影響渲染,哪個影響更大,如何避免是經(jīng)常被問到的一道題目,我們先來說一下重繪

  •  重繪

          重繪指的是不影響界面布局的操作,比如更改顏色,那么根據(jù)上面的渲染講解我們知道,重繪之后我們只需要在重復(fù)進(jìn)行一下樣式計(jì)算,就可以直接渲染了,對瀏覽器渲染的影響相對較小

  •  重排

         重排指的是影響界面布局的操作,比如改變寬高,隱藏節(jié)點(diǎn)等。對于重排就不是一個重新計(jì)算樣式那么簡單了,因?yàn)楦淖兞瞬季郑鶕?jù)上面的渲染流程來看涉及到的階段有樣式計(jì)算,布局樹           重新生成,分層樹重新生成,所以重排對瀏覽器的渲染影響是比較高的

  •  避免方法
    •  js 盡量減少對樣式的操作,能用 css 完成的就用 css
    •  果必須要用 js 操作樣式,能合并盡量合并不要分多次操作
    •  resize 事件 最好加上防抖,能盡量少觸發(fā)就少觸發(fā)
    •  加載對 dom 操作盡量少,能用 createDocumentFragment 的地方盡量用
    •  加圖片的時候,提前寫好寬高

問題 4:瀏覽器緩存機(jī)制

瀏覽器緩存是比較常見的問題,我會從瀏覽器緩存的方式,緩存的實(shí)現(xiàn), 緩存在哪里這幾個點(diǎn)來說明

緩存方式

我們經(jīng)常說的瀏覽器緩存有兩種,一種是強(qiáng)制緩存,一種是協(xié)商緩存,因?yàn)橄旅嬗芯唧w實(shí)現(xiàn)講解,所以這里就說一下概念

  •  協(xié)商緩存

          協(xié)商緩存意思是文件已經(jīng)被緩存了,但是否從緩存中讀取是需要和服務(wù)器進(jìn)行協(xié)商,具體如何協(xié)商要看請求頭/響應(yīng)頭的字段設(shè)置,下面會說到。需要注意的是協(xié)商緩存還是發(fā)了請求的

  •  強(qiáng)制緩存

           強(qiáng)制緩存就是文件直接從緩存中獲取,不需要發(fā)送請求

緩存實(shí)現(xiàn)

  •  強(qiáng)制緩存

強(qiáng)制緩存在 http1.0 的時候用的是 Expires,是響應(yīng)頭里面的一個字段表示的是文件過期時間。是一個絕對時間,正因?yàn)槭墙^對時間所以在某些情況下,服務(wù)器的時區(qū)和瀏覽器時區(qū)不一致的時候就會導(dǎo)致緩存失效。為了解決這個問題,HTPP1.1 引入了一個新的響應(yīng)頭 cache-control 它的可選值如下

cache-control

  •  max-age: 緩存過期時間,是一個相對時間
  •  public: 表示客戶端和代理服務(wù)器都會緩存
  •  private: 表示只在客戶端緩存
  •  no-cache: 協(xié)商緩存標(biāo)識符,表示文件會被緩存但是需要和服務(wù)器協(xié)商
  •  no-store: 表示文件不會被緩存

HTTP1.1 利用的就是 max-age:600 來強(qiáng)制緩存,因?yàn)槭窍鄬r間,所以不會出現(xiàn) Expires 問題

  •  協(xié)商緩存

          協(xié)商緩存是利用 Last-Modified/if-Modified-Since,Etag/if-None-Match 這兩對請求、響應(yīng)頭。

          Last-Modified/if-Modified-Since

          Etag/If-None-Match

由于 Last-Modified 的時間粒度是秒,有的文件在 1s 內(nèi)可能被改動多次。這種方式在這種特殊情況下還是會失效,所以HTTP1.1又引入了 Etag 字段。這個字段是根據(jù)文件內(nèi)容生成一個標(biāo)記符比如"W/"5f9583bd-10a8"",然后再和 If-None-Match 進(jìn)行對比就能更準(zhǔn)確的知道文件有沒有被改動過

  •  瀏覽器第一次發(fā)送請求獲取文件緩存下來,服務(wù)器響應(yīng)頭返回一個 if-Modified-Since,記錄被改動的時間
  •  瀏覽器第二次發(fā)送請求的時候會帶上一個 Last-Modified 請求頭,時間就是 if-Modified-Since 返回的值。然后服務(wù)器拿到這個字段和自己內(nèi)部設(shè)置的時間進(jìn)行對比,時間相同表示沒有修改,就直接返回 304 從緩存里面獲取文件

緩存在哪里

知道了緩存方式和實(shí)現(xiàn),再來說一下緩存存在哪個地方,我們打開掘金可以看到如下的信息 。緩存的來源有兩個地方 from dist cache,from memeory cache

form memory cache

這個是緩存在內(nèi)存里面,優(yōu)點(diǎn)是快速,但是具有時效性,當(dāng)關(guān)閉 tab 時候緩存就會失效。

from dist cache

這個是緩存在磁盤里面,雖然慢但是還是比請求快,優(yōu)點(diǎn)是緩存可以一直被保留,即使關(guān)閉 tab 頁,也會一直存在

何時緩存在memory,合適緩存在dist?

這個問題網(wǎng)上很少找的到標(biāo)準(zhǔn)答案,大家一致的說法是js,圖片文件瀏覽器會自動保存在memory中,css文件因?yàn)椴怀P薷谋4嬖赿ist里面,我們可以打開掘金網(wǎng)站,很大一部分文件都是按照這個規(guī)則來的,但是也有少數(shù)js文件也是緩存在dist里面。所以他的存放機(jī)制到底是什么樣了?我?guī)е@個疑問查了好多文章,雖然最后沒有確切找到答案,但是一個知乎的回答可以給我們提供思路,下面引用一個知乎回答者一段話

  •  第一個現(xiàn)象(以圖片為例):訪問-> 200 -> 退出瀏覽器再進(jìn)來-> 200(from disk cache) -> 刷新 -> 200(from memory cache)。總結(jié): 會不會是chrome很聰明的判斷既然已經(jīng)從disk拿來了, 第二次就內(nèi)存拿吧 快。(笑哭)
  •  第二個現(xiàn)象(以圖片為例):只要圖片是base64 我看都是from memroy cache。總結(jié): 解析渲染圖片這么費(fèi)勁的事情,還是做一次然后放到內(nèi)存吧。用的時候直接拿
  •  第三個現(xiàn)象(以js css為例):個人在做靜態(tài)測試的發(fā)現(xiàn),大型的js css文件都是直接disk cache。結(jié): chrome會不會說 我去 你這么大太占地方了。你就去硬盤里呆著吧。慢就慢點(diǎn)吧。
  •  第四個現(xiàn)象:隱私模式下,幾乎都是 from memroy cache。總結(jié): 隱私模式 是吧。我不能暴露你東西,還是放到內(nèi)存吧。你關(guān),我死。

上面幾點(diǎn)是雖然很幽默,但是卻可以從中找到一部分答案,但是我覺得另一個知乎回答我更贊同

瀏覽器運(yùn)行的時候也是由幾個進(jìn)程協(xié)作的,所以操作系統(tǒng)為了節(jié)省內(nèi)存,會把一部分內(nèi)存里的資源交換回磁盤的交換區(qū),當(dāng)然交換是有策略的,比如最常用的就是LRU。

什么時候存dist,什么時候存memoey都是在瀏覽器控制下的,memory不夠了可能就會考慮去存dist了,所以經(jīng)過上面所說我自己總結(jié)結(jié)果如下

  •  大一點(diǎn)的文件會緩存在dist里面,因?yàn)閮?nèi)存也是有限的,磁盤的空間更大
  •  小一點(diǎn)文件js,圖片存的是memory
  •  css文件一般存在dist
  •  特殊情況memory大小是有限制的,瀏覽器也會根據(jù)自己的內(nèi)置算法,把一部分js文件存到dist里面

問題 5:https 和 http 的區(qū)別

說到https和http的區(qū)別,可以說一下https服務(wù)器和客戶端連接的差異,以及https特定的加密算法協(xié)商,甚至可能還要說到對稱加密,非對稱加密和證書等,篇幅很長,請看我之前單獨(dú)寫的一篇https詳解,里面講的非常詳細(xì)。

請求優(yōu)化

講請求優(yōu)化的之前先來總結(jié)下上面說到的js, css文件順序優(yōu)化,為了讓渲染更快,我們需要把js放到尾部,css放到頭部,然后還要注意在書寫js的時候盡量減少重排,重繪。書寫html,css的時候盡量簡潔,不要冗余,目的是為了更快的構(gòu)建DOM樹和CSSOM樹。好了下面我們在來說說請求優(yōu)化,請求優(yōu)化可以從請求數(shù)量和請求時間兩方面入手

減少請求數(shù)量

  •  將小圖片打包成base64
  •  利用雪碧圖融合多個小圖片
  •  利用緩存上面已經(jīng)說到過

減少請求時間

  •  將js,css,html等文件能壓縮的盡量壓縮,減少文件大小,加快下載速度
  •  利用webpack打包根據(jù)路由進(jìn)行懶加載,不要初始就加載全部,那樣文件會很大
  •  能升級到高版本的http就升級到高版本(這個回答是套話),為什么高版本能提高速度具體看上面我說的那篇https文章
  •  建立內(nèi)部CDN能更快速的獲取文件

webpack優(yōu)化

介紹了渲染優(yōu)化,現(xiàn)在來看看webpack優(yōu)化,自己平常寫demo給團(tuán)隊(duì)做培訓(xùn)的時候都是自己手寫webpack配置,雖然也就幾十行,但每次都能讓我鞏固webpack的基本配置,下面直接說一下webpack優(yōu)化手段有哪些

基礎(chǔ)配置優(yōu)化

  •  extensions 這個配置是屬于resolve里面的,經(jīng)常用來對文件后綴進(jìn)行擴(kuò)展,寫法如下 
  1. resolve: {  
  2.     extensions: ['.ts', '.tsx', '.js']  

這個配置表示webpack會根據(jù)extensions去尋找文件后綴名,所以如果我們的項(xiàng)目主要用ts寫的話,那我們就可以.tsx和.ts寫前面,目的是為了讓webpack能夠快速解析

  •  alias 這個配置也是屬于resolve里面的,是用來映射路勁,能減少打包時間的主要原因是能夠讓webpack快速的解析文件路徑,找到對應(yīng)的文件,配置如下 
  1. resolve: {  
  2.   alias: {  
  3.     Components: path.resolve(__dirname, './src/components')  
  4.   }  
  •  noParse

noParse表示不需要解析的文件,有的文件可能是來自第三方的文件,被 providePlugin引入作為windows上的變量來使用,這樣的文件相對比較大,并且已經(jīng)是被打包過的,所以把這種文件排除在外是很有必要的,配置如下 

  1. module: {  
  2.   noParse: [/proj4\.js/]  
  •  exclude

某些loader會有這樣一個屬性,目的是指定loader作用的范圍,exclude表示排除某些文件不需要babel-loader處理,loader的作用范圍小了,打包速度自然就快了,用babel-loader舉一個簡單例子 

  1.  
  2.     test: /\.js$/,  
  3.     loader: "babel-loader",  
  4.     exclude: path.resolve(__dirname, 'node_modules')  
  •  devtool

這個配置是一個調(diào)試項(xiàng),不同的配置展示效果不一樣,打包大小和打包速度也不一樣,比如開發(fā)環(huán)境下cheap-source-map肯定比source-map快,至于為什么,強(qiáng)烈推薦自己之前寫的這一篇講解devtool的文章:webpack devtools篇講的非常詳細(xì)。 

  1.  
  2.     devtool: 'cheap-source-map'  

.eslintignore

這個雖不是webpack配置但是對打包速度優(yōu)化還是很有用的,在我的實(shí)踐中eslint檢查對打包的速度影響很大,但是很多情況我們不能沒有這個eslint檢查,eslint檢查如果僅僅在vs里面開啟的話,可能不怎么保險(xiǎn)。

因?yàn)橛锌赡苣鉽s中的eslint插件突然關(guān)閉了或者某些原因vs不能檢查了,只能靠webpack構(gòu)建去幫你攔住錯誤代碼的提交,即使這樣還不能確保萬無一失,因?yàn)槟憧赡苣骋淮翁峤淮a很急沒有啟動服務(wù),直接盲改提交上去了。這個時候只能通過最后一道屏障給你保護(hù),就是在CI的時候。比如我們也會是在jenkins構(gòu)建的時候幫你進(jìn)行eslint檢查,三道屏障確保了我們最終出的鏡像是不會有問題的。

所以eslint是很重要的,不能刪掉,在不能刪掉的情況下怎么讓檢查的時間更少了,我們就可以通過忽略文件,讓不必要的文件禁止eslint,只對需要的文件eslint可以很大程度提高打包速度

loader,plugins優(yōu)化

上述說了幾個基礎(chǔ)配置優(yōu)化,應(yīng)該還有其他的基礎(chǔ)配置,今后遇到了再繼續(xù)添加,現(xiàn)在在來講講利用某些loader,plugins來提高打包速度的例子

  •  cache-loader

這個loader就是在第一次打包的時候會緩存打包的結(jié)果,在第二次打包的時候就會直接讀取緩存的內(nèi)容,從而提高打包效率。但是也需要合理利用,我們要記住一點(diǎn)你加的每一個loader,plugins都會帶來額外的打包時間。這個額外時間比他帶來的減少時間多,那么一味的增加這個loader就沒意義,所以cache-loader最好用在耗時比較大的loader上,配置如下 

  1.  
  2.   rules: [  
  3.     {  
  4.       test: /\.vue$/,  
  5.       use: [  
  6.         'cache-loader',  
  7.         'vue-loader'  
  8.       ],  
  9.       include: path.resolve(__dirname, './src')  
  10.     }  
  11.   ]  
  •  webpack-parallel-uglify-plugin, uglifyjs-webpack-plugin, terser-webpack-plugin

在上面的渲染優(yōu)化中我們已經(jīng)知道,文件越小渲染的速度是越快的。所以我們在配置webpack時候經(jīng)常會用到壓縮,但是壓縮也是需要消耗時間的,所以我們我們經(jīng)常會用到上面三個插件之一來開啟并行壓縮,減少壓縮時間,我們用webpack4推薦使用的terse-webpack-plugin做例子來說明 

  1. optimization: {  
  2.   minimizer: [  
  3.       new TerserPlugin({  
  4.         parallel: true,  
  5.         cache: true  
  6.       })  
  7.     ],  
  •  happypack, parallel-webpack, thread-loader

這幾個loader/plugin和上面一樣也是開啟并行的,只不過是開啟并行構(gòu)建。由于happypack的作者說自己的興趣已經(jīng)不再js上了,所以已經(jīng)沒有維護(hù)了,并推薦如果使用的是webpack4的話,就去使用thread-loader。基本配置如下 

  1.  
  2.    test: /\.js$/,  
  3.    use: [  
  4.      {  
  5.        loader: "thread-loader",  
  6.        options: threadLoaderOptions  
  7.      },  
  8.      "babel-loader",  
  9.    ],  
  10.    exclude: /node_modules/,  
  11.  } 
  •  DllPlugin,webpack.DllReferencePlugin

上面說的幾個并行插件理論上是可以增加構(gòu)建速度,網(wǎng)上很多文章都是這么說的,但是我在實(shí)際的過程中使用,發(fā)現(xiàn)有時候不僅沒提升反而還降低了打包速度,網(wǎng)速查閱給的理由是可能你的電腦核數(shù)本來就低,或者當(dāng)時你CPU運(yùn)行已經(jīng)很高了,再去開啟多進(jìn)程導(dǎo)致構(gòu)建速度降低。

上面說的幾個并行插件可能在某些情況下達(dá)不到你想要的效果,然而在我們團(tuán)隊(duì)優(yōu)化webpack性能經(jīng)驗(yàn)來看,這次所說的兩個插件是很明顯并且每次都能提高打包速度的。原理就是先把第三方依賴先打包一次生成一個js文件,然后真正打包項(xiàng)目代碼時候,會根據(jù)映射文件直接從打包出來的js文件獲取所需要的對象,而不用再去打包第三方文件。只不過這種情況打包配置稍微麻煩點(diǎn),需要寫一個webpack.dll.js。大致如下

webpack.dll.js 

  1. const path = require('path');  
  2. const webpack = require('webpack');  
  3. module.exports = {  
  4.     entry: {  
  5.         library: ["vue", "moment"]  
  6.     },  
  7.     output: {  
  8.         filename: '[name].dll.js',  
  9.         path: path.resolve(__dirname, 'json-dll'),  
  10.         library: '[name]'  
  11.     },  
  12.     plugins: [ 
  13.          new webpack.DllPlugin({  
  14.             path: './json-dll/library.json',  
  15.             name: '[name].json'  
  16.         })  
  17.     ]  

webpack.dev.js 

  1. new AddAssetHtmlWebpack({  
  2.    filepath: path.resolve(__dirname, './json-dll/library.dll.js')  
  3. }),  
  4. ew webpack.DllReferencePlugin({  
  5.     manifest: require("./json-dll/library.json")  
  6.   }) 

其他優(yōu)化配置

這些插件就簡單的介紹下,在我的個人項(xiàng)目中已經(jīng)使用過,自我感覺還可以,具體使用可以查閱npm或者github

  •  webpack-bundle-analyzer

這個插件可以用可視化幫我們分析打包體積,從而來采用合適的優(yōu)化方式去改進(jìn)我們的webpack配置

  •  speed-measure-webpack-plugin

這個插件可以告訴我們打包時候每一個loader或者plugin花費(fèi)了多少時間,從而對耗時比較長的plugin和loader做優(yōu)化

  •  friendly-errors-webpack-plugin

這個插件可以幫我們優(yōu)化打包日志,我們打包時候經(jīng)常看到很長一個日志信息,有的時候是不需要的,也不會去看所以可以用這個插件來簡化

代碼優(yōu)化

這是最后一部分代碼優(yōu)化了,這里的代碼性能優(yōu)化我只說我在工作中感受到的,至于其他的比較小的優(yōu)化點(diǎn)比如createDocumentFragment使用可以查查其他文章

能不操作dom不要操作dom,哪怕有時候需要改設(shè)計(jì)

很多情況下我們都能用css還原設(shè)計(jì)稿,但是有些時候單單從css沒法還原,尤其組件還不是你寫的時候,比如我們團(tuán)隊(duì)用的就是antd,有時候的產(chǎn)品設(shè)計(jì)單從css上沒法實(shí)現(xiàn),只能動用js,刪除,增加節(jié)點(diǎn)在配合樣式才能完成。

由于我們又是一個做大數(shù)據(jù)的公司,這個時候就會出現(xiàn)性能問題,最開始寫代碼時候,產(chǎn)品說什么就是什么,說什么我都會想辦法搞出來,不管用什么方法。后來到客戶現(xiàn)場大數(shù)據(jù)請況下,性能缺點(diǎn)立馬暴露的出來。

所以代碼優(yōu)化的原則之一我認(rèn)為是能不寫的代碼就不寫,當(dāng)然這是要從性能角度出發(fā),通過性能分析給產(chǎn)品說出理由,并且最好還能提供更好的解決方案,這個才是我們需要考慮的。

如果用的是react 一定用寫shouldComponentUpdate這個生命周期函數(shù),不然打印的時候你會發(fā)現(xiàn),你自己都迷糊為什么執(zhí)行了這么多遍

將復(fù)雜的比對,變成簡單比對

這句話是什么意思了?我們就拿shouldComponentUpdate舉例子,用這個函數(shù)沒問題,但是可以做的更好,我們在工作中經(jīng)常這么寫 

  1. shouldComponentUpdate(nextPrpops) {  
  2.   return JSON.stringify(nextPrpops.data) !== JSON.stringify(this.props.data)  

如果這是一個分頁表格,data是每一頁數(shù)據(jù),數(shù)據(jù)改變了重新渲染,在小數(shù)據(jù)場景下這本身是沒有問題。但是如果在大數(shù)據(jù)的場景下可能會有問題,可能有人有疑問,既然做了分頁怎么還會有大數(shù)據(jù)了,因?yàn)槲覀兊漠a(chǎn)品是做大數(shù)據(jù)分析日志的,一頁十條日志,有的日志可能非常的長,也就是說就算是10條數(shù)據(jù)比對起來也是很耗時,所以當(dāng)時想法能不能找到其他的替代變量來表示數(shù)據(jù)變了?比如下面這樣 

  1. shouldComponentUpdate(nextPrpops) {  
  2.   return nextPrpops.data[0].id !== this.props.data[0].id  

第一條的id不一樣就表示數(shù)據(jù)變化了行不行,顯然在某種情況下是存在的,也有人會說可能會出現(xiàn)id一樣,那如果換成下面這種了? 

  1. shouldComponentUpdate(nextPrpops) {  
  2.   return nextPrpops.current !== this.props.current  

將data的比對轉(zhuǎn)換成了current的比對,因?yàn)轫摂?shù)變了,數(shù)據(jù)基本都是變了,對于我們自己日志的展示來說基本不存在兩頁數(shù)據(jù)是一模一樣的,如果有那可能是后臺問題。然后在好好思考這個問題,即使存在了兩頁數(shù)據(jù)一摸一樣,頂多就是這個表格不重新渲染,但是兩頁數(shù)據(jù)一摸一樣不重新渲染是不是也沒有問題,因?yàn)閿?shù)據(jù)是一樣的。或者如果你還是不放心,那下面這種會不會好點(diǎn) 

  1. this.setState({  
  2.   data,  
  3.   requestId: guid()  
  4. })  
  5. shouldComponentUpdate(nextPrpops) {  
  6.   return nextPrpops.requestId !== this.props.requestId  

給一個requestId跟宗data,后面就只比對requestId。上面的寫法可能都有問題,但是主要是想說的是我們在寫代碼時候可以想想是不是可以"將復(fù)雜的比對,變成簡單比對"

學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法,一定會在你的工作中派上用場

我們經(jīng)常會聽到學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法沒有什么大的用處,因?yàn)楣ぷ骰居貌簧稀_@句話我之前覺得沒錯,現(xiàn)在看來錯的很嚴(yán)重。我們所學(xué)的每一樣技能,都會在將來的人生中派上用場。之前寫完代碼就丟了不去優(yōu)化所以我覺得算法沒意義,又難又容易忘記。但現(xiàn)在要求自己做完需求,開啟mock,打開perfermance進(jìn)行大數(shù)據(jù)量的測試,看著那些標(biāo)紅的火焰圖和肉眼可見的卡頓,就明白了算法和數(shù)據(jù)結(jié)構(gòu)的重要性,因?yàn)榇藭r你只能從它身上獲取優(yōu)化,平時你很排斥它,到優(yōu)化的時候你是那么想擁有它。我拿自己之前寫的代碼舉例,由于公司代碼是保密的我就把變量換一下,偽代碼如下 

  1. data.filter(({id}) => {  
  2.   return selectedIds.includes(id);  
  3. }) 

就是這樣幾行代碼,邏輯就是篩選出data里面已經(jīng)被勾選的數(shù)據(jù)。基本上很多人都可能這么寫,因?yàn)槲铱次覀儓F(tuán)隊(duì)里面都是這么寫的。產(chǎn)品當(dāng)時已經(jīng)限制data最多200數(shù)據(jù),所以寫完完全沒壓力,性能沒影響。但是秉著對性能優(yōu)化的原則(主要是被現(xiàn)場環(huán)境搞怕了~~~),我開啟了mock服務(wù),將數(shù)據(jù)調(diào)到了2萬條再去測試,代碼弊端就暴露出來了,界面進(jìn)入卡頓,重新選擇的時候也會卡頓。然后就開始了優(yōu)化,當(dāng)時具體的思路如下

按照現(xiàn)在的代碼來看,這是一個兩層循環(huán)的暴力搜索時間復(fù)雜度為O(n^2)。所以想著能不能降一下復(fù)雜度至少是O(nlogn),看了一下代碼只能從selectedIds.includes(id)這句入手,于是想著可不可以用二分,但是立馬被否定因?yàn)槎质切枰行虻模疫@數(shù)組都是字符串怎么二分。

安靜了一下之后,回想起看過的算法課程和書籍以及做的算法題,改變暴力搜索的方法基本都是

1:上指針

2:數(shù)組升維

3:利用hash表

前兩者被我否定了因?yàn)槲矣X得還沒那么復(fù)雜,于是利用hash表思想解決這個問題,因?yàn)閖s里面有一個天然的hash表結(jié)構(gòu)就是對象。我們知道hash表的查詢是O(1)的,所以我將代碼改寫如下 

  1. const ids = {};  
  2. selectedIds.forEach(id => ids[id] = 1);  
  3. data.filter(({id}) => {  
  4.   return !!ids[id];  
  5. }) 

將從selectedIds查詢變成從ids查詢,這樣時間復(fù)雜度就從O(n^2)變成了O(n)了,這段代碼增加了 

  1. const ids = {};  
  2. selectedIds.forEach(id => ids[id] = 1); 

其實(shí)增加了一個selectedIds遍歷也是一個O(n)的復(fù)雜度,總來說復(fù)雜度是O(2n),但是從時間復(fù)雜度長期期望來看還是一個O(n)的時間復(fù)雜度,只不過額外增加了一個對象,所以這也是一個典型的空間換時間的例子,但是也不要擔(dān)心,ids用完之后垃圾回收機(jī)制會把他回收的。

最后

其實(shí)這篇文章寫出來還是對自己幫助很大,讓自己系統(tǒng)的梳理了一下自己理解的前端優(yōu)化,希望對你們也有幫助。 

 

責(zé)任編輯:龐桂玉 來源: 前端大全
相關(guān)推薦

2015-04-22 12:19:42

JAVAJAVA面試題答案解析

2019-10-21 10:57:56

MySQL算法數(shù)據(jù)庫

2018-03-02 08:50:54

Linux面試題offer技巧

2019-08-13 08:43:07

JavaScript前端面試題

2013-05-29 10:36:08

Android開發(fā)移動開發(fā)字符串反轉(zhuǎn)

2014-07-28 14:00:40

linux面試題

2021-03-19 11:08:27

開發(fā)技能代碼

2016-03-03 10:07:39

ios內(nèi)存管理面試總結(jié)

2024-04-15 08:34:43

2024-04-28 08:23:18

2025-08-22 10:45:57

Go字符串語言

2023-04-27 09:08:19

JavaScript隱式類型轉(zhuǎn)換

2015-07-23 14:13:43

前端開發(fā)面試題

2009-07-07 16:20:31

JSP試題

2015-08-19 09:35:49

Java main面試題

2009-06-22 13:43:00

java算法

2019-12-20 09:31:23

TCPHTTP瀏覽器

2024-07-24 08:38:07

2016-05-05 17:45:43

Spring面試題答案

2020-08-24 07:12:17

前端CRP性能優(yōu)化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

久久视频国产精品免费视频在线| 成人综合婷婷国产精品久久免费| 亚洲欧美999| 天堂在线资源视频| 91精品久久久| 91麻豆免费观看| 国产三级精品网站| 亚洲黄色三级视频| 成人在线免费观看网站| 精品美女一区二区| 午夜精品在线免费观看| 蜜桃传媒在线观看免费进入| 久久久av毛片精品| 成人综合av网| 在线观看视频中文字幕| 亚洲三级电影在线观看| 日韩视频一区在线| 国产全是老熟女太爽了| 天堂精品在线视频| 色中色一区二区| 一卡二卡三卡视频| 老司机在线永久免费观看| 99久久久无码国产精品| 亚洲999一在线观看www| 成年人视频免费| 亚洲国产高清一区二区三区| 日韩在线观看网址| 久久人人爽人人爽人人片| 欧美经典一区| 精品1区2区3区| 欧美亚洲国产成人| ririsao久久精品一区| 亚洲蜜臀av乱码久久精品| 人禽交欧美网站免费| 黑人操亚洲女人| 国产一区91精品张津瑜| 国产精品嫩草影院一区二区| 国产精品视频免费播放| 99精品久久| 欧美情侣性视频| 99久久婷婷国产综合| 久久理论电影| 影音先锋欧美精品| 亚洲区自拍偷拍| 一区二区三区视频免费观看| 亚洲国产精品一区二区三区| 中国男女全黄大片| 麻豆一区在线| 日韩一级片网址| 无套内谢丰满少妇中文字幕 | 精品人妻无码一区二区 | 午夜男人的天堂| 日本超碰一区二区| 欧美成人一区二区三区| 成年人看片网站| 一区二区三区亚洲变态调教大结局| 91精品国产91综合久久蜜臀| 一区二区三区国产好的精华液| 欧美91在线|欧美| 欧美日韩精品一区二区在线播放 | 国产激情视频一区二区在线观看 | 中文字幕第100页| 国产原创一区| 337p亚洲精品色噜噜| 三日本三级少妇三级99| 国语精品视频| 精品国产3级a| 亚洲永久精品ww.7491进入| 奇米亚洲欧美| 日韩最新在线视频| 激情小说中文字幕| 国产亚洲综合精品| 国产成人精品在线| 国产欧美第一页| 福利视频网站一区二区三区| 精品国产91亚洲一区二区三区www| 亚洲欧洲精品视频| 国产蜜臀97一区二区三区| 中文字幕一区二区三区有限公司 | 欧美视频在线不卡| 日韩 国产 一区| youjizz亚洲| 亚洲人永久免费| 午夜成人亚洲理伦片在线观看| 一区二区日韩欧美| 2019日本中文字幕| 免费一级a毛片| 国产麻豆视频一区二区| 九色视频成人porny| 成年午夜在线| 亚洲一区二区三区视频在线| 欧美日韩亚洲一二三| 一级欧美视频| 精品视频在线观看日韩| 亚洲 欧美 国产 另类| 日韩视频一区二区三区在线播放免费观看 | 国产精品国模大尺度私拍| 日本v片在线免费观看| 中文字幕欧美一区| 91精品91久久久中77777老牛| 国产成人精选| 日韩av在线网页| 中文国语毛片高清视频| 国产模特精品视频久久久久| 成人久久久久久| 青青色在线视频| 一区二区三区高清| 亚洲国产精品三区| 少妇久久久久| 久久不射热爱视频精品| 波多野结衣不卡| 粉嫩av亚洲一区二区图片| 水蜜桃一区二区三区| av在线最新| 日韩女优av电影| 国产在线免费av| 久久一日本道色综合久久| 999视频在线免费观看| av在线电影网| 日韩欧美在线视频| 永久免费未满蜜桃| 亚洲国产成人精品女人| 国产精品久久久久免费a∨| 天天操天天舔天天干| 亚洲精品综合在线| 色一情一区二区三区| 欧美理论视频| 热久久这里只有精品| 神马一区二区三区| 亚洲综合激情网| 亚洲综合中文网| 91精品国产福利在线观看麻豆| 国产精品第100页| 青青青草网站免费视频在线观看| 精品av在线播放| 无码一区二区精品| 亚洲国产裸拍裸体视频在线观看乱了中文 | 亚洲欧美日韩国产成人精品影院| 熟妇熟女乱妇乱女网站| 欧美老熟妇一区二区三区| 久久久久久9| 久久精品国产综合精品| 91九色在线播放| 日韩精品一区二区三区老鸭窝| 搜索黄色一级片| 精品一区二区三区免费观看| 亚洲精品国产精品国自产观看| 伊人久久精品一区二区三区| 日韩精品高清在线观看| 国产亚洲免费的视频看| 一二三四视频社区在线| 日韩精品久久久久久久软件91| 色偷偷亚洲男人天堂| 中文字字幕在线观看| 国产精品九色蝌蚪自拍| 91小视频在线播放| 亚洲欧洲日韩| 国产又黄又粗又猛又爽的| 欧洲专线二区三区| 国产成人精品久久| 福利在线午夜| 欧美日韩久久一区二区| 午夜国产小视频| 国产酒店精品激情| 青青青在线观看视频| 精品精品国产毛片在线看| 黑人巨大精品欧美黑白配亚洲| 久久亚裔精品欧美| 成人网ww555视频免费看| 少妇高潮 亚洲精品| 国产免费高清av| 亚洲一区在线观看视频| 制服丝袜第二页| 奇米影视一区二区三区小说| 一区二区在线不卡| 都市激情久久| 国产精品每日更新| 日本xxxx黄色| 欧美在线三级| 国产一区二区免费电影| 在线日韩影院| 久久精彩免费视频| 天堂中文在线8| 欧美狂野另类xxxxoooo| 国产精品成人久久| 国产亚洲短视频| 无人码人妻一区二区三区免费| 亚洲精选成人| 一区二区在线观看网站| 日韩大胆成人| 国产日本欧美一区| 欧美另类老肥妇| 久久国产一区二区三区| 日本黄色一区二区三区| 欧美日韩中文字幕一区二区| 久久免费视频99| 国产三级欧美三级| 色哟哟网站在线观看| 日本最新不卡在线| 无码人妻少妇伦在线电影| 日韩欧美视频| 久久福利电影| 视频二区欧美| 国产精品网址在线| 成人免费无遮挡| 欧美日韩高清区| 一区二区三区视频网站| 日韩精品免费在线视频| 精品人妻久久久久一区二区三区 | 日本男女交配视频| 日韩欧美字幕| 欧美精品一区二区三区在线看午夜| 国产精品1区在线| 国产精品欧美在线| 日韩伦理在线| 欧美激情中文网| 二区在线播放| 最新国产精品拍自在线播放 | 久久免费偷拍视频| 中文字幕1区2区| 韩国一区二区视频| 91小视频网站| 久久伊人亚洲| 91猫先生在线| 亚洲精品四区| 日韩激情视频一区二区| 欧美二区视频| 91xxx视频| 外国成人激情视频| 亚洲精品中文综合第一页| 国产成人1区| 欧美日本亚洲| 九九热爱视频精品视频| 精品久久久久亚洲| 欧美日韩一区二区三区不卡视频| 成人看片视频| japanese色系久久精品| 99porn视频在线| 亚洲一级大片| 国产精品国产亚洲精品看不卡15| 亚洲精品一区二区三区中文字幕| 亚洲综合小说区| 日韩综合一区二区三区| 春色成人在线视频| xxxxxhd亚洲人hd| 国产一区二区免费电影| 西野翔中文久久精品字幕| 久久五月天婷婷| 国产成人精品一区二区免费看京| 欧美日韩综合精品| 欧美日韩伦理| 影音先锋欧美资源| 欧美激情1区2区| 久久人人爽人人爽人人av| 亚洲高清在线| 99热成人精品热久久66| 欧美中文日韩| 91欧美视频在线| 国产乱人伦偷精品视频免下载| 香蕉视频在线观看黄| 播五月开心婷婷综合| 激情综合丁香五月| 日本一区二区三区久久久久久久久不 | 希岛爱理av一区二区三区| 欧美一级特黄aaaaaa在线看片| 韩国一区二区三区在线观看| 日本a视频在线观看| 久久精选视频| 亚洲三级在线观看视频| 国产高清无密码一区二区三区| 最新版天堂资源在线| 久久精品亚洲乱码伦伦中文| 国产精品麻豆免费版现看视频| 亚洲日本丝袜连裤袜办公室| 国产精品美女毛片真酒店| 欧美性xxxx极品hd欧美风情| 精品乱码一区内射人妻无码| 欧美精品粉嫩高潮一区二区| 亚洲乱码在线观看| 亚洲欧美一区二区三区情侣bbw| 日日夜夜精品一区| 久久人人爽人人爽人人片av高清| 激情都市亚洲| 亚洲r级在线观看| 亚洲精品亚洲人成在线观看| 艳色歌舞团一区二区三区| 在线观看日韩av电影| youjizzxxxx18| 丰满亚洲少妇av| 91资源在线播放| 亚洲一二三四在线| 国产一级片一区二区| 亚洲福利视频免费观看| 91se在线| 国产91对白在线播放| 国产电影一区| 欧美一区二视频在线免费观看| 亚洲情侣在线| www日韩在线观看| 国产91精品免费| 免费看的黄色录像| 日本老熟俱乐部h0930| 国产精品888| 高潮毛片无遮挡| 一区二区三区日韩欧美精品| 日韩免费av网站| 精品日韩一区二区三区| 岛国视频免费在线观看| 久久久久久久久久久成人| 外国电影一区二区| 久久精品ww人人做人人爽| 亚洲香蕉av| 欧美黄色一级片视频| aaa国产一区| 免费在线看黄网址| 欧美另类变人与禽xxxxx| 国产资源在线看| 91高清视频免费| 大型av综合网站| 青草全福视在线| 久久丁香综合五月国产三级网站| 一卡二卡三卡四卡| 污片在线观看一区二区| 亚洲第一色网站| 久久久精品日本| 久久精品嫩草影院| 日本一区二区三区www| 国产视频久久| 亚洲 欧美 日韩在线| 亚洲国产裸拍裸体视频在线观看乱了| 国产精品视频一二区| 综合欧美国产视频二区| 国产亚洲一区二区手机在线观看 | 人妻丰满熟妇av无码区hd| 另类少妇人与禽zozz0性伦| 欧美黄页在线免费观看| 亚洲视频电影| 久久99在线观看| 成人18视频免费69| 欧美日韩一二三区| 在线观看免费版| 国产免费一区二区三区在线能观看 | 欧美三级在线免费观看| 日韩一区二区在线观看视频| 国产欧美黑人| 超碰97在线资源| 亚洲片区在线| 亚洲av无码一区二区三区网址| 激情成人在线视频| 美女欧美视频在线观看免费| 国产91在线播放| 欧美综合另类| www,av在线| 亚洲激情中文1区| 人妻中文字幕一区| 欧美怡春院一区二区三区| 国产欧美日韩视频在线| 天天色综合天天色| 综合久久给合久久狠狠狠97色| 精品久久久免费视频| 欧美大片网站在线观看| 欧美18xxxx| 手机在线看福利| 亚洲人成精品久久久久久 | 香蕉久久一区| 超碰10000| 久久在线免费观看| 在线观看毛片av| 欧美黑人一级爽快片淫片高清| 欧美人体视频| 午夜激情福利在线| 亚洲日韩欧美一区二区在线| 天天操天天干天天操| 国产精品美女久久| 欧美精品一卡| 国产女主播喷水高潮网红在线| 在线综合亚洲欧美在线视频| a天堂资源在线| 亚洲黄色一区二区三区| 国产精品538一区二区在线| 亚洲天堂视频网站| 久久深夜福利免费观看| 性欧美lx╳lx╳| 992tv人人草| 色综合久久66| 1024在线播放| 色播亚洲婷婷| 成人午夜电影小说| 一炮成瘾1v1高h| 欧美一区二区三区精品电影| 天天久久综合| 亚洲专区区免费| 欧美一卡二卡在线| 国精产品一区二区三区有限公司 | 久久免费手机视频| 精品欧美乱码久久久久久 | 欧美日韩久久一区二区| 免费在线小视频| 日本福利视频网站| 中文字幕精品一区二区精品绿巨人|