前端優化(webpack, js, html)

HTTP優化

gzip壓縮
資源的壓縮與合併

HTTP協議上的gzip編碼是一種用來改進web應用程序性能的技術,web服務器和客戶端(瀏覽器)必須共同支持gzip。css

瀏覽器請求url,並在request header中設置屬性accept-encoding:gzip。代表瀏覽器支持gzip。html

該不應用 Gzip

壓縮 Gzip,服務端要花時間;解壓 Gzip,瀏覽器要花時間。中間節省出來的傳輸時間,真的那麼可觀嗎?建議較大文件進行gizpvue

webpack4中啓動gzip壓縮
npm i -D compression-webpack-plugin

plugins: [
  new CompressionPlugin({
    filename: "[path].gz[query]",
    algorithm: "gzip",
    test: /\.js$|\.html$|\.css/,
    threshold: 10240, // 只處理比這個值大的資源。按字節計算
    minRatio: 0.8 //     只有壓縮率比這個值小的資源纔會被處理
    deleteOriginalAssets: false, //是否刪除原資源
  }),
];

詳細配置 CompressionWebpackPluginnode

CDN加速
如今大部分雲服務商都是提供cdn服務

image

簡單的來講: 原服務器上數據複製到其餘服務器上,用戶訪問時,那臺服務器近訪問到的就是那臺服務器上的數據。

CDN加速優勢是成本低,速度快。能夠用CDN best的CDN進行加速,免費,可部署私有,公有CDN系統。能夠實現宕機檢測,自動切換ip,分線路,分組解析。也就是CDN加速的主要做用就是保證網站的正常訪問,及加快網站訪問速度和響應速度,防止網站因黑客攻擊,DNS解析劫持故障等致使的網站服務器的宕機情況的出現。webpack

圖片(圖標)方面

使用字體圖標

推薦: Iconfont-阿里巴巴矢量圖標庫web

雪碧圖
將多個圖標集成在一塊兒

雪碧圖製做起來麻煩,我仍是推薦Iconfont的字體圖標啦ajax

圖片使用Base64編碼減小頁面請求數(建議小圖片)

Base64編碼圖片能夠在瀏覽器本身顯示出來vue-router

採用Base64的編碼方式將圖片直接嵌入到網頁中,而不是從外部載入,如<img src="data:image/gif;base64,/9j/2SDFG... >,這樣下載HTML文檔的時間就會增加了。在CSS背景圖中也是能夠這麼作的vuex

使用webpack處理圖片成 base64
npm install --save-dev url-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [{
      test: /\.(png|svg|jpg|gif|jpeg|ico|woff|woff2|eot|ttf|otf)$/,
      use: [{
          loader: "url-loader", // 根據圖片大小,把圖片優化成base64
          options: {
            limit: 10000, //小於10000字節的圖片都進行base64操做
          }
        }
      ]
    }]
  }
};
webpack配置 JPG、PNG、GIF和SVG圖像的壓縮
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        loader: "image-webpack-loader", // 先進行圖片優化
        options: {
          mozjpeg: {
            progressive: true,
            quality: 65,
          },
          optipng: {
            enabled: false,
          },
          pngquant: {
            quality: "65-90",
            speed: 4,
          },
          gifsicle: {
            interlaced: false,
          },
          webp: {
            quality: 75,
          },
        },
      },
    ],
  },
};

html,css優化

<script>標籤和<style>標籤(看註釋)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  /**
  * 放頭部: 頁面先解析<style>後獲得css後解析html
  */
  <style>...<style>
  /**
  * 放頭部: 頁面的解析在遇到js的時候須要運行完js以後才能繼續
  * 缺點:js一旦加載或者運算好久,會致使用戶白屏
  */
  <script>
    for (let i=0; i < 1000000000000000; i++) {
        console.log("年輕人不講碼德! 你就慢慢等吧")
    }
  </script>
</head>
<body>
  <div id="container"></div>
  /**
  * 放尾部: 頁面的解析完畢開始加載js
  * 優勢:用戶無需等待js加載就能夠看到界面
  */
   <script>
    var container = document.getElementById("container")
    console.log('container', container) // '<div id="container"></div>'
  </script>
</body>
  /**
  * 放尾部: 頁面先解析html後獲得解析css
  * 缺點:致使html節點出來沒樣式後纔有
  */
  <style>...<style>
</html>
迴流和重繪
須要瀏覽器渲染機制,該文章就不展開講了
迴流(重排)

迴流又名重排,指幾何屬性需改變的渲染。觸發瀏覽器迴流並從新生成渲染樹npm

重繪

重繪指更改外觀屬性而不影響幾何屬性的渲染。渲染樹的節點發生改變,可是不影響該節點的幾何屬性

  • 幾何屬性:包括佈局、尺寸等可用數學幾何衡量的屬性
佈局:display、float、position、list、table、flex、columns、grid
尺寸:margin、padding、border、width、height
  • 外觀屬性:包括界面、文字等可用狀態向量描述的屬性
界面:appearance、outline、background、mask、box-shadow、box-reflect、filter、opacity、clip
文字:text、font、word

js優化

減小 DOM 操做
  • 減小DOM 更改等操做
// bad
let box = document.getElementById('box')

box.innerHTML = '1'
box.innerHTML += '2'
box.innerHTML += '3'
...

// good
let content = ''
content = '1'
content += '2'
content += '3'

box.innerHTML = content // 一次性插入
  • DocumentFragment

不是真實 DOM 樹,它的變化不會引發 DOM 樹的從新渲染

let box = document.getElementById('box')

let content = document.createDocumentFragment()

let Fdiv = document.createElement('div')

Fdiv.innerHTML = '1'
Fdiv.innerHTML += '2'
Fdiv.innerHTML += '3'

content.appendChild(Fdiv)
// 只產生一次dom操做
box.appendChild(content)
圖片懶加載
<li><img src="img/loading.gif" data-src="img/1.jpg"></li>

最開始每個圖片使用loading.gif,首屏加載的時候能夠節省多張圖片請求

原理:滾動條設置到圖片的時候加載data-src內的正常圖片

具體實現能夠看我以前發的文章實現圖片懶加載

防抖和節流
防抖: 在必定時間內,只能觸發一次
/**
 * @param {Function} func 要執行的回調函數 
 * @param {Number} wait 延時的時間
 * @param {Boolean} immediate 是否當即執行
 * @return null
 */
let timer, flag;
function throttle(func, wait = 500, immediate = true) {
    if (immediate) {
        if (!flag) {
            flag = true;
            // 若是是當即執行,則在wait毫秒內開始時執行
            typeof func === 'function' && func();
            timer = setTimeout(() => {
                flag = false;
            }, wait);
        }
    } else {
        if (!flag) {
            flag = true
            // 若是是非當即執行,則在wait毫秒內的結束處執行
            timer = setTimeout(() => {
                flag = false
                typeof func === 'function' && func();
            }, wait);
        }
        
    }
};
export default throttle
節流: 必定時間內,只有最後一次操做,再過wait毫秒後才執行函數
let timeout = null;
/**
 * @param {Function} func 要執行的回調函數 
 * @param {Number} wait 延時的時間
 * @param {Boolean} immediate 是否當即執行 
 * @return null
 */
function debounce(func, wait = 500, immediate = false) {
    // 清除定時器
    if (timeout !== null) clearTimeout(timeout);
    // 當即執行,此類狀況通常用不到
    if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(function() {
            timeout = null;
        }, wait);
        if (callNow) typeof func === 'function' && func();
    } else {
        // 設置定時器,當最後一次操做後,timeout不會再被清除,因此在延時wait毫秒後執行func回調方法
        timeout = setTimeout(function() {
            typeof func === 'function' && func();
        }, wait);
    }
}

export default debounce

webpack4優化(打包過大等優化)

webpack 設置cdn優化
vuecli生成的項目進行配置

運行yarn build 發現vendors.js之中包含vue,vuex, vue-router
如今咱們能夠經過webpack的externals進行vue,vuex抽離掉使用cdn

# vue.config.js
module.exports = {
  configureWebpack:{
    externals: {
       'vue': 'Vue',
       'vuex': 'Vuex'
    }
  }
}

# store/index.js
import Vuex from "vuex";

// Vue.use(Vuex); 註釋掉
// index.html
<body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.1.3/vuex.min.js"></script>
  </body>
splitChunks(打包分割)

運行yarn build 發現vendors.js之中還有vue-router須要分離
能夠利用webpack中的splitChunks分割出來

splitChunks的配置挺複雜的,須要你們本身學習,我只是提供一個方案
# vue.config.js
module.exports = {
  configureWebpack: {
    optimization: {
      splitChunks: {
        cacheGroups: {
          vendors: {
            test: /node_modules/,
            chunks: "initial",
            minChunks: 1,
            priority: -10,
          },
          router: {
            name: 'chunk-router',
            test: /[\\/]node_modules[\\/]vue-router[\\/]/,
            chunks: "all",
            minChunks: 1,
            priority: -5,
          }
        },
      },
    },
  },
};

相關博文

玩轉CSS的藝術之美

相關文章
相關標籤/搜索