如何顯著的提高前端加載性能

本文代碼基於vue項目,代碼源自vue不一樣環境打包命令配置,但優化方案適用於全部現代化前端框架javascript

關於前端性能優化是個歷史很是很是悠久的話題,百度搜一下前端性能優化,基本上都是在教咱們如何提高執行性能,好比說盡可能的減小DOM操做,js文件放在html的最底部,第三方文件使用CDN方式加載。但在如今Vue、react等現代化框架大行其道的時代下,咱們第三方庫基本上都是npm install XXXX安裝到項目內了,這就使得咱們的項目愈來愈大,哪怕使用Webpack壓縮打包後,也會有十幾兆的大小(實際大小根據來講,不作優化的狀況下,項目越大,使用的第三方庫越多,打包後的項目也越大),但咱們服務器的帶寬卻不必定很是大,尤爲是像Vue、React這樣的單頁面應用(本文討論的以頁面應用爲主,它們雖然能夠配置多頁面,但做者對多頁面不熟悉,本文不作討論),若是咱們的第三方庫在都掛載到全局,就會形成主包文件很是大,首頁加載超級慢。css

因此咱們本文就開始嘗試將項目體積減少,提高首屏加載速度。html

一,使用CDN加載第三方庫

在現代化框架中咱們使用第三方UI基本都是使用npm install的方式,在vue中若是一個UI庫中的組件咱們大量使用,咱們會將其在main.js中全局引用,這樣使用是沒有問題的,但當項目進行打包的時候,UI庫也會被打包進項目,使得項目包變得很是大,以iView來講,當咱們不使用iView的時候咱們的項目包打包出來是這個樣子的。前端

我項目是在本地部的因此加載速度可參考性不大,但咱們應該能夠理解你的資源越大加載速度就越慢。vue

而後咱們安裝使用iView以後看一下有什麼變化;java

首先能夠看到打包的時候先給咱們報了警告,告訴咱們文件過大可能影響性能。而後打包後的文件體積明顯變得更大了,加載速度也更慢了,若是你本身作實驗,你會發現打包速度也變慢了,並且這只是咱們在全局只使用了iView,實際開發中咱們可能還會使用moment、axios、jscookies、echarts等各類各樣的可能須要在全局使用的第三方工具,那麼項目愈來愈大,不作其餘處理的狀況下,性能只會愈來愈差,很明顯的感覺就是首頁渲染超級慢。react

因此咱們開始進行優化,減少咱們項目體積,提升資源加載速度。webpack

1-一、經過CDN引入iView

首先因爲咱們的項目是單頁面應用,因此咱們在項目的html文件內經過CDN引入iView-UI庫。iView的CDN傳送門ios

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- S 引入iView樣式-->
    <link rel="stylesheet" href="//unpkg.com/iview/dist/styles/iview.css">
    <!-- E 引入iView樣式-->
    <title>myproject</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but myproject doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- S 引入VueJs和iView腳本-->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="//unpkg.com/iview/dist/iview.min.js"></script>
    <!-- E 引入VueJs和iView腳本-->
  </body>
</html>
複製代碼

看到這裏,可能你會想,不是引入iview嗎,爲何把vue也用cdn的方式引入了?這個答案呢,你猜下,而後對比下去掉vue和加上vue有什麼區別,而後再思考下,我想你能夠猜到答案。git

1-二、配置CDN使用

在項目根目錄下新建一個vue.config.js文件,這個文件vue給咱們提供的,咱們能夠在文件內定義一些webpack配置,代碼以下vue.config.js配置指南

module.exports = {
  configureWebpack: {
    externals: {
      iview: 'iview', // '包名':'全局變量' 
   },
  }
}
複製代碼

若是是vue-cli 2.X建立的項目,能夠在/build/webpack.base.conf.js文件內這麼寫入;webpackConfig對象是vue幫你已經定義好了,你只須要加入externals配置就行,千萬別去又建個webpackConfig對象。

const webpackConfig = {
  externals: {
      iview: 'iview', // '包名':'全局變量' 
   },
}
複製代碼

若是是其餘項目,而且使用了webpack,那麼請找到項目的webpack配置文件,而後在配置對象內加入如下代碼。webpack關於externals配置項的文檔

externals: {
  iview: 'iview', // '包名':'全局變量' 
}
複製代碼

1-三、使用

main.js內這麼引用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import iView from 'iview';

Vue.config.productionTip = false
Vue.use(iView);

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
複製代碼

而後你就能夠在項目中正常使用,使用方式和npm install安裝的沒有任何區別,請放心使用。

1-四、對比

而後咱們繼續進行打個包,而後部署,對比npm install安裝在項目內有什麼區別;

而後咱們發現,咦!!!打包後的文件確實變小了,可是怎麼加載速度還變慢了,尤爲是iview相關的,加載速度超級慢啊,iview.min.js竟然花費了1.14秒才加載完成。

這裏就直接說答案了,因爲iview的CDN是unpkg,若是在大陸訪問的話,訪問的節點是香港,因此呢,咱們更換下iview的cdn地址,實際開發中各家公司應該是有本身的CDN的,因此能夠直接把第三方資源放在自家CDN上,我這裏換成了jsDelivr,而後對比一下;

能夠明顯看到這加載速度直接快了一半還多啊。

1-5 總結

因此咱們就能夠在實際項目開發過程直接使用這種方式來使用第三方資源,速度提高是能夠用眼睛看到的,唰!唰!唰!另外咱們在1-1中已經經過CDN的方式引用vue了,那咱們可不能夠在項目內npm uninstall vue移除vue,而後採用CDN方式使用呢,試一下唄!!

二,使用CDN加載項目靜態資源

咱們進行項目開發的時候不可避免地會使用到圖片,字體等文件,當咱們進行項目打包的時候,或者被打包成base64或者打包進靜態資源目錄,不可避免都在項目內,最後都上傳到服務器上了,這樣圖片加載的時候,確定會影響其餘資源加載速度,形成首頁渲染速度變慢;固然咱們也能夠把圖片資源上傳到CDN上,而後複製下地址在項目中使用,可是這樣咱們每使用一張就須要上傳一次,嚴重影響開發效率;

可是咱們若是能夠在項目開發的時候從項目內加載圖片,而後打包的時候從CDN上來加載圖片,這樣不就能夠解決問題了。

1-1 首先圖片打包進項目

強烈建議在服務器做此操做對比,我這裏是在本地用PHPStudy模擬起的服務,資源因爲在本地,因此會發現從CDN加載資源沒有從本地快;在實際開發中,因爲服務器性能帶寬等各類因素影響,因此從CDN加載資源會很是明顯的帶來性能提高

咱們先來看一下咱們不使用CDN,把圖片放在項目內,會有多大的影響。我在項目內引入20張圖片,每一個頁面加載幾張,先來截個圖看看。

首先是我這幾個圖片就比較大,因此打的包也就很大,實際項目中通常不會有一個圖片八九兆的狀況,但若是項目中用到的圖片資源多,那麼包也會比較大。

1-2 圖片經過CDN方式加載

咱們但願開發環境用本地圖片,生產環境用CDN資源,那麼咱們這裏就須要用到Webpack的一個loader,url-loader,這是webpack推薦的一個loader,在vue、react等各類框架中也是使用頻率很是高的一個loader,若是不許備很深刻研究的話,看Webpack提供的這個文檔就夠了。

  1. 首先在vue.config.js中加入以下配置
module.exports = {
  configureWebpack: {
    externals: {
      iview: 'iview', // '包名':'全局變量' 
    },
  },
  // 這裏是新加的
  chainWebpack: config => {
    config.module
      .rule('images')
      .use('url-loader')
        .options({
          limit: 10240,
          publicPath: process.env.NODE_ENV === 'development' ? '' : 'http://static.jindll.com/img',
          outputPath: 'img',
          name: '[name].[ext]',
        })
        .end()
  }
}
複製代碼
  1. 而後你就能夠在項目正常使用你的圖片了,不管是../的相對路徑仍是@/XXX均可以,開發環境都是用的是本地的圖片資源,其餘環境(測試環境或者生產環境或者預發佈環境等等),圖片路徑會被替換成publicPath所設置的路徑加上你的圖片名字,以我上面的配置來講,假如我在項目中使用了@/assets/img/logo.png圖片,那麼打包以後路徑就會是http://static.jindll.com/img/logo.png還有一個須要說,你打包以後圖片不會自動就上傳到CDN上,打包以後,在生成的dist文件夾下,會有一個img文件夾,這個文件夾內的圖片就是你項目所使用的圖片,而後將這個文件夾內的圖片自行上傳到CDN上就行,可是CDN的圖片路徑前綴必定要和publicPath設置的路徑保持一致;爲何打包以後圖片會被放進img文件夾,這個是由於咱們經過outputPath屬性設置的輸出路徑,若是你想改爲其餘的名稱都隨意;

  2. 對之上的配置作下解釋,我以前有說過咱們須要使用url-loader可是我並無npm install安裝url-loader,這是由於vue-cli內部使用了url-loader,因此咱們能夠經過vue-cli提供的chainWebpack屬性對內部的webpack配置作修改;vue-cli對chainWebpack這個配置解釋的並很少,但告訴了咱們chainWebpack接收一個基於 webpack-chain 的 ChainableConfig實例,因此更多的使用或者api咱們其實能夠查看webpack-chain官方文檔

    根據webpack-chain文檔rule方法表示的是這個規則的名字,也就是任意的字符串,Vue-Cli內部對其定義的名字是images(僅針對url-loader),咱們這裏是修改內部配置,因此用這個名字來取對應的配置來作修改;use方法表示要使用的loader名字(若是使用plugin就是plugin名字),limit表示只有文件大於這個值的時候纔會被打包進img文件夾,小於這個值文件將被處理成base64,name表示的是文件名字,它的值我設置的是[name].[ext],表示的是打包的文件名就用原名稱,後綴也不改變,這個是佔位符,其餘的佔位符能夠看file-loader文檔url-loader和file-loader做用相同,配置url-loader比file-loader多了limit配置,file-loader至關於打包的時候將文件進行移動,url-loader是將文件處理成base64,其餘基本沒有區別了

  3. 補充內容,在使用使用CDN加載第三方庫中,我使用了configureWebpack配置,在使用CDN加載項目靜態資源中我使用了chainWebpack配置,在Vue項目中,若是咱們想要對webpack作修改,那麼這兩個配置就是很重要的配置,它們均可以幫助咱們完成webpack修改;那這兩個有什麼區別呢?

    • configureWebpack能夠接受一個對象,在這個對象內部咱們能夠寫原生的webpack配置;簡單說它就是加新的配置,但不能改已有的配置,但使用方便;
    • chainWebpack是一個函數,咱們能夠在這個函數中對Vue-Cli內部的webpack配置作修改;簡單說它就是改已有的配置,也能夠加新的配置,但須要看下webpack-chain文檔才能夠更好的使用

3、減小在全局掛載內容

這部份內容以後會在其餘文章作更多描述

再經過CDN加載第三方庫和靜態資源經過CDN加載以後,咱們項目體積已經能夠大幅度的減少了,但在實際項目開發中,因爲業務須要咱們本身會寫很是多的工具函數,好比後端返回的是state碼,而不是翻譯好的文字,咱們須要封裝一些方法來對這些狀態碼作處理,但這些工具函數的使用頻率可能並非很是高,有可能僅在項目的這個功能模塊內用,其餘功能模塊並不使用;或者身份證校驗等這些相似的方法,他們的使用頻率可能也就五六各地方會用,但在我所遇到的項目中,很是多的開發人員是單獨創建一個文件,文件內封裝這些方法,最後將這個文件掛載到全局使用;這樣會出現的問題就是,當項目打包的時候,這些方法會被打進主包內(vue項目是app.hash.js),這會增大主包的體積,無形中就形成了首屏渲染速度變慢;

因此對於這種場景,建議就是若是某幾個方法僅在某一個功能模塊中使用,那就給這個功能模塊單獨建個tool.js,而後在須要的地方引入具體的方法就好。

減小在全局掛載內容這部分暫時沒有代碼,這部分的內容以後也會在其餘文章重點描述。

4、其餘

。。。。。。。。。。。。。。。。。。。想到再更。。。。。。。。。。。。。。。。。

相關文章
相關標籤/搜索