前端性能優(yōu)化總結(jié)

gzip壓縮

gzip壓縮效率很高,可以達到70%的壓縮率

//npm i -D compression-webpack-plugin  安裝插件依賴
configureWebpack: config => {
  const CompressionPlugin = require('compression-webpack-plugin')
  config.plugins.push(new CompressionPlugin())
}



去掉console.log

生產(chǎn)環(huán)境中,不需要打印日志。通過對webpack進行配置,打包時自動去掉console.log

//npm i -D terser-webpack-plugin
configureWebpack:config =>{
    const  TerserPlugin = require('terser-webpack-pulugin')
    config.optimzation.minimizer.push(
        new TerserPlugin({
            extractComments:false,
            terserOptions:{compress:{drop_console:true}} //插件配置項 移除console
        })
    )
}



去除SourceMap

代碼壓縮后進行調(diào)bug定位將非常困難,于是引入sourcemap記錄壓縮前后的位置信息記錄,當產(chǎn)生錯誤時直接定位到未壓縮前的位置,將大大的方便我們調(diào)試。

sourcemap附帶了很多信息,如果build需要生成sourcemap,將會大大降低build的速度,還會增加包的體積。

//vue 中
module.exports = {
  productionSourceMap: false,
}

//react中
//打開webpack.config.prod.js
const shouldUseSourceMap = false



CDN

內(nèi)容分發(fā)網(wǎng)絡(luò),它能夠?qū)崟r地根據(jù)網(wǎng)絡(luò)流量和各節(jié)點的連接、負載狀況以及到用戶的距離和響應(yīng)時間等綜合信息將用戶的請求重新導(dǎo)向離用戶最近的服務(wù)節(jié)點上。其目的是使用戶可就近取得所需內(nèi)容,解決 Internet網(wǎng)絡(luò)擁擠的狀況,提高用戶訪問網(wǎng)站的響應(yīng)速度。所以可以通過將資源部署在CDN上來提高響應(yīng)速度,提高用戶體驗
預(yù)渲染

簡單來說,就是將瀏覽器解析JavaScript動態(tài)渲染的工作,在打包階段完成了(只構(gòu)建了靜態(tài)數(shù)據(jù))。換個說法,在構(gòu)建過程中,webpack通過使用prerender-spa-plugin插件生成靜態(tài)結(jié)構(gòu)的html

// 1、安裝prerender-spa-plugin
npm install prerender-spa-plugin --save-dev
 
// 2、安裝vue-meta-info
npm install vue-meta-info --save-dev
 
 
// 3、相關(guān)配置
<!-- webpack.prod.conf.js -->
// 預(yù)渲染配置:在webpack.prod.conf文件中加入
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
 
// 在 plugins 中加入
new PrerenderSPAPlugin({
      // 生成文件的路徑,也可以與webpakc打包的一致。
      // 下面這句話非常重要?。?!
      // 這個目錄只能有一級,如果目錄層次大于一級,在生成的時候不會有任何錯誤提示,在預(yù)渲染的時候只會卡著不動。
      staticDir: path.join(__dirname, '../dist'),
 
      // 對應(yīng)自己的路由文件,比如a有參數(shù),就需要寫成 /a/param1。
      routes: ['/', '/first', '/second', '/third', '/fourth', '/userCenter/userFirst','/userCenter/userSecond','/userCenter/userThird'],
 
      // 這個很重要,如果沒有配置這段,也不會進行預(yù)編譯
      renderer: new Renderer({
        inject: {
          foo: 'bar'
        },
        // headless: false,
        renderAfterDocumentEvent: 'render-event', // 在 main.js 中 document.dispatchEvent(new Event('render-event')),兩者的事件名稱要對應(yīng)上。
        args: ['--no-sandbox', '--disable-setuid-sandbox']
      })
    })
 
// 4、在main.js中
import MetaInfo from 'vue-meta-info'
 
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>',
  // 添加mounted,不然不會執(zhí)行預(yù)編譯
  mounted () {
    document.dispatchEvent(new Event('render-event'))
  }
})



注意:路由模式必須為 history ,如果不設(shè)置 history 模式,也能運行和生成文件,每個 index.html 文件的內(nèi)容都會是一樣的
Service Worker

ServiceWorker 是運行在瀏覽器后臺進程里的一段 JS,它可以做許多事情,比如攔截客戶端的請求、向客戶端發(fā)送消息、向服務(wù)器發(fā)起請求等等,其中最重要的作用之一就是離線資源緩存。

ServiceWorker 擁有對緩存流程豐富靈活的控制能力,當頁面請求到 ServiceWorker 時,ServiceWorker 同時請求緩存和網(wǎng)絡(luò),把緩存的內(nèi)容直接給用戶,而后覆蓋緩存






注意:需要HTTPS才能使用ServiceWorker
HTTP緩存

HTTP緩存一般分為兩類:強緩存(本地緩存)、協(xié)商緩存(304緩存)

普通刷新會啟用協(xié)商緩存

在地址欄輸入網(wǎng)址、通過鏈接引入資源等情況下,瀏覽器才啟用強緩存

強緩存(200)。本地緩存是最快速的一種緩存方式,只要資源還在緩存有效期內(nèi),瀏覽器就會直接在本地讀取,不會請求服務(wù)端。在chrome控制臺的Network選項中可以看到該請求返回200的狀態(tài)碼,并且Size顯示from disk cache或from memory cache。強緩存可以通過設(shè)置兩種 HTTP Header 實現(xiàn):Expires 和 Cache-Control。

協(xié)商緩存(304)。協(xié)商緩存,顧名思義是經(jīng)過瀏覽器與服務(wù)器之間協(xié)商過之后,在決定是否讀取本地緩存,如果服務(wù)器通知瀏覽器可以讀取本地緩存,會返回304狀態(tài)碼,并且協(xié)商過程很簡單,只會發(fā)送頭信息,不會發(fā)送響應(yīng)體。

協(xié)商緩存可以通過設(shè)置兩種 HTTP Header 實現(xiàn):Last-Modified 和 ETag

首先在精確度上,Etag要優(yōu)于Last-Modified

第二在性能上,Etag要遜于Last-Modified,畢竟Last-Modified只需要記錄時間,而Etag需要服務(wù)器通過算法來計算出一個hash值

第三在優(yōu)先級上,服務(wù)器校驗優(yōu)先考慮Etag

緩存優(yōu)先級:Service Worker -> Memory Cache(內(nèi)存緩存) -> Disk Cache(硬盤緩存) -> Push Cache(推送緩存)

Push Cache 只在會話(session)中存在,會話結(jié)束就被釋放,而且緩存時間很短
HTTP2

HTTP2 四個新特性:

    多路復(fù)用,無需多個TCP連接,因為其允許在單一的HTTP2連接上發(fā)起多重請求,因此可以不用依賴建立多個TCP連接。
    二進制分幀,將所有要傳輸?shù)南⒉捎枚M制編碼,并且會將信息分割為更小的消息塊。
    頭部壓縮,用HPACK技術(shù)壓縮頭部,減小報文大小
    服務(wù)端推送,服務(wù)端可以在客戶端發(fā)起請求前發(fā)送數(shù)據(jù),換句話說,服務(wù)端可以對客戶端的一個請求發(fā)送多個相應(yīng),并且資源可以正常緩存。

server {
    listen 443 ssl http2;
}


資源預(yù)加載

提前加載資源,當用戶需要時,可以直接從本地緩存中渲染。
preload

頁面加載的過程中,在瀏覽器開始主體渲染之前加載

//對sty1e.cs5和 index.js進行pre1oad預(yù)加載
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="index.js" as="script">



prefetch

頁面加載完成后,利用空閑時間提前加載

//對資源進行 prefetch預(yù)加載
<link rel="prefetch" href="next.css">
<link rel="prefetch" href="next.js">


dns-prefetch

//對特定域名進行預(yù)解析
//將靜態(tài)資源只放在一個域名下面,可以有效減少dns的請求
<link rel=”dns-prefetch” href=”//fonts.googleapis.com”>


異步無阻塞加載JS

異步加載 js 文件,并且不會阻塞頁面的渲染。

普通的script標簽在開始解析和解析的過程中,會停止解析dom
defer

<script src="d.js" defer></script> <script src="e.js" defer></script>


在其他同步腳本執(zhí)行后,DOMContentLoaded 事件前 依次執(zhí)行 d.js, e.js。
async

<script src="b.js" async></script>
<script src="c.js" async></script>
當腳本下載完后立即執(zhí)行。(兩者執(zhí)行順序不確定,執(zhí)行階段不確定,可能在 DOMContentLoaded 事件前或者后 )

defer和async都不會停止解析dom
webp

webp 是一種新的圖片格式,它的體積只有只有 jpeg的2/3,將圖片資源大量換成 webp 格式可以加快請求的速度

但是webp存在瀏覽器兼容問題,使用前需要判斷瀏覽器是否支持
loading加載

通過添加加載中狀態(tài),可以讓用戶在視覺上不會覺得慢

可以通過骨架屏加載,在感官上內(nèi)容出現(xiàn)的流暢不突兀



歡迎關(guān)注微信公眾號:猴哥說前端