vue-cli3專案搭建配置以及效能優化

巴依發表於2019-03-24

vue-cli3專案搭建配置以及效能優化

在之前的開發中主要用的是vue-cli2,最近空閒時間比較多,接下來有新專案,本著偷懶的本能,自己打算搭建一個基礎包以備後期開發應用,並對其進行效能優化和配置。

該專案的GitHub:github.com/bayi-lzp/vu… 求星

master分支為基礎包,vi_mint_ui分支為優化後專案,可根據自己需要進行切換。

搭建整個過程如下:

  • 初始化專案
  • 修改目錄結構
  • 多環境執行
  • axios封裝
  • 模組化vuex
  • 全域性引用樣式
  • 移動端適配配置
  • 常用util
  • 引入第三方UI框架
  • 配置vue.config.js檔案
  • vue專案框架效能優化(重點) (v1_mint_ui分支)

1.專案初始化

  • 建立專案

可用命令列或者ui皮膚進行建立,具體的建立方式及詳細說明,可以參考我的另一篇文章 vue-cli3初始化專案搭建

  • 執行專案
npm run serve
複製程式碼

vue-cli3專案搭建配置以及效能優化

2.修改目錄結構

用編輯器開啟後可以看到目錄結構。相對於vue-cli2精簡了很多,減少了對webpack的配置。

vue-cli3專案搭建配置以及效能優化

  • node_modules 資料夾 專案依賴(對webpack進行了封裝)

  • public 資料夾

    1.favicon.ico 是 網站圖示

    2.index.html 頁面入口檔案

  • src 資料夾

    main.js 入口js

    assets 存放靜態檔案

    components 存放公用元件

    App.vue 入口vue檔案

  • .eslintrc.js 配置

  • .gitignore 指定檔案無需提交到git上

  • balel.config.js 使用一些預設

  • package.json 專案描述及依賴

  • package-lock.json 版本管理使用的檔案

由於現在的目錄結構不利於後期的開發,現在我們增加部分檔案,待後續可以進行功能擴充套件。在src檔案下:新建api資料夾,config資料夾,router資料夾,utils資料夾,views資料夾,store資料夾。並在其檔案下建子目錄,詳細請參考目錄截圖:

vue-cli3專案搭建配置以及效能優化

2.多環境執行

由於我們的專案需要在不同環境下進行執行(開發,生產,測試等),這避免我們需要多次的去切換請求的地址以及相關的配置,vue-cli2是可以直接在config檔案中進行配置的,但是vue-cli3已經簡化了,官方文件也有進行配置的說明,實現具體有以下2種方法,我比較偏向第二種。

  • 第一種實現方法

1.在根目錄新建2個檔案,分別為.env.development.env.production.env.test。注意檔案是隻有字尾的。

.env.development 模式用於serve,開發環境,就是開始環境的時候會引用這個檔案裡面的配置

.env.production模式用於build,線上環境。

.env.test 測試環境

2.分別在檔案內寫上:

開發環境:

//.env.development 
VUE_APP_BASE_API = '需要請求API'
複製程式碼

線上環境:

//.env.production
VUE_APP_BASE_API = '需要請求API'
複製程式碼

測試環境:

//.env.test
VUE_APP_BASE_API = '需要請求API'
複製程式碼

當需要用到該變數是可以用process.env.VUE_APP_BASE_API進行取值。

3.更改package.json檔案

 "scripts": {
    "dev": "vue-cli-service serve",
    "test": "vue-cli-service serve --mode test",
    "build": "vue-cli-service build",
    "build:test": "vue-cli-service build --mode test",
    "lint": "vue-cli-service lint"
  },
複製程式碼
  • 第二種實現方式

1.在config檔案新建index.js檔案,根據全域性的環境變數來進行判斷,並進行輸出。程式碼如下:

// 一些全域性的config配置
const modeUrlObj = {
  // 生產環境
  'production': {
    baseURL: 'http://172.17.71.40:9091/pro/',
    authBaseURL: ''
  },
  // 開發環境
  'development': {
    baseURL: 'http://172.17.71.40:9091/dev/',
    authBaseURL: ''
  },
  // 測試環境
  'test': {
    baseURL: 'http://172.17.71.40:9091/test/',
    authBaseURL: ''
  }
}
export default modeUrlObj[process.env.NODE_ENV]

複製程式碼
  1. 更改package.json檔案
 "scripts": {
    "dev": "vue-cli-service serve",
    "test": "vue-cli-service serve --mode test",
    "build": "vue-cli-service build",
    "build:test": "vue-cli-service build --mode test",
    "lint": "vue-cli-service lint"
  },
複製程式碼
  1. 引用的方法可以參照如下:
import config from '../config/index' // 路徑配置

config.baseURL  // 對應環境api

複製程式碼

4.執行命令列

npm run dev // 開發環境

npm run test // 測試環境

npm run build // 正式環境打包

npm run build:test // 測試環境打包

2. axios封裝

在vue專案中,和後臺互動獲取資料這塊,我們通常使用的是axios庫,它是基於promise的http庫,可執行在瀏覽器端和node.js中。他有很多優秀的特性,例如攔截請求和響應、取消請求、轉換json、客戶端防禦XSRF等。所以我們的尤大大也是果斷放棄了對其官方庫vue-resource的維護,直接推薦我們使用axios庫。如果還對axios不瞭解的,可以移步axios文件

  • 安裝依賴
npm install axios --save; // 安裝axios
複製程式碼
  • 配置axios

在uitls檔案下新增request.js檔案,在這裡我們對axios進行初始化後,暴露給需要引用的檔案,方便開發。

import axios from 'axios'
import config from '../config/index' // 路徑配置
複製程式碼

建立axios例項,並進行配置

// 建立axios 例項
const service = axios.create({
    baseURL: config.baseURL, // api的base_url
    timeout: 10000 // 請求超時時間
})

複製程式碼

利用axios的請求攔截和響應攔截可以對登入和許可權方面進行控制,具體需求可以自己進行配置。完整程式碼如下:

import axios from 'axios'
import config from '../config/index' // 路徑配置

// 建立axios 例項
const service = axios.create({
    baseURL: config.baseURL, // api的base_url
    timeout: 10000 // 請求超時時間
})

// request 攔截器
service.interceptors.request.use(
    config => {
        // 這裡可以自定義一些config 配置

        return config
    },
    error => {
        //  這裡處理一些請求出錯的情況

        Promise.reject(error)
    }
)

// response 攔截器
service.interceptors.response.use(
    response => {
        const res = response.data
        // 這裡處理一些response 正常放回時的邏輯

        return res
    },
    error => {
        // 這裡處理一些response 出錯時的邏輯

        return Promise.reject(error)
    }
)

export default service

複製程式碼
  • api請求配置

在api檔案下新建分類的api請求檔案。根據具體需要分類。主要是方便團隊開發,容易歸類。可以參考下面配置。

import request from '@/utils/request'

export default {
  // 登入
  login (data) {
    return request({
      url: '/login',
      method: 'post',
      data
    })
  },
  // 獲取使用者資訊
  getUserInfo () {
    return request({
      url: '/userinfo',
      method: 'get'
    })
  }
}
複製程式碼

業務中需要進行請求可以用import後,進行傳參即可。

4.模組化vuex

Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

如果對vuex還不大瞭解的可以自行閱讀vuex官方文件

  • 安裝vuex
npm install vuex -S
複製程式碼
  • 新建目錄

modules檔案主要用法存放分類的檔案,可以進行區分,getters檔案是對state進行處理,index.js主要進行一些引入,初始化操作。

vue-cli3專案搭建配置以及效能優化

  • 書寫vuex配置

index.js檔案

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user' // 引入各個模組的程式碼
import getters from './getters'

Vue.use(Vuex)

const store = new Vuex.Store({
    modules: {
        user
    },
    getters
})

export default store
複製程式碼

getter.js檔案

getter中的配置可根據需求進行增加或者刪除,下面是示例。

const getters = {
  requestLoading: state => state.app.requestLoading,
  size: state => state.app.size,
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name,
  roles: state => state.user.roles
}
export default getters
複製程式碼

moduels/user.js檔案

該檔案為與業務相關,可以跟據具體參見進行增加和刪除命名。每個檔案的基本配置和用法如下:

import { getToken, setToken } from '@/utils/auth'
import api from '@/api/user'

const user = {
  state: {
    token: getToken(),
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
  },

  actions: {
    // 登入
    Login ({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        api.login(userInfo).then(res => {
          if (res.code === 200) {
            setToken(res.data)
            commit('SET_TOKEN', res.data)
          }
          resolve()
        }).catch(err => {
          reject(err)
        })
      })
    }
  }
}

export default user
複製程式碼

5.全域性樣式引用

在專案開發過程中,我們經常需要全域性樣式引用,例如主題色等,如果每次去寫的化會變得很麻煩。因為我們應該了sass預語言編譯,所以可以大膽的應用其特性。例如變數,函式,混入等。但是我們需要在專案中進行全域性的配置才能有效果。不用在每一個頁面都進行引入樣式,就能直接引用。

  • 新建目錄

在assets下新建如下檔案,具體的程式碼自行進行配置

* common.scss 主要存放公共的樣式

* mixin.scss 存放混入樣式

* reset.scss 存放重置樣式。

* variable.scss 存放變數
複製程式碼

vue-cli3專案搭建配置以及效能優化

  • 全域性引入

新建vue.config.js檔案,並寫上以下程式碼

module.exports = {
  css: {
    loaderOptions: {
      // pass options to sass-loader
      sass: {
        // @/ is an alias to src/
        // so this assumes you have a file named `src/variables.scss`
        data: `
               @import "@/assets/css/variable.scss"; 
               @import "@/assets/css/common.scss";
               @import "@/assets/css/mixin.scss";
              `
      }
    }
  },
}
複製程式碼

在app.vue中引入reset.scss檔案,完成後,樣式即可進行全域性呼叫了。

<style lang="scss">
  @import "assets/css/reset";
</style>
複製程式碼

6.移動端適配配置

在本專案中主要用rem來進行頁面的適配操作的,因為rem就可以隨根字型大小改變而改變,從而實現了自適應的功能。但是html的字型是固定的,所以需要監聽頁面大小的變化,我主要用了淘寶的amfe-flexible來進行監聽改變的。將專案中css的px轉成rem單位,免去計算煩惱,我們可以用scss來進行計算或者利用px2rem外掛來進行自動轉化。因為是開發移動端,需把mate換為 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale= 1.0, minimum-scale=1.0"> 實現方法如下:

  • 安裝amfe-flexible

npm i amfe-flexible --save

  • px轉rem

方法一:

在common.scss檔案中,全域性引入scss函式:

/**
  轉化px為rem。$base-font-size = 設計稿尺寸/10
*/
@function px2rem($px, $base-font-size: 37.5) {
  @return ($px/$base-font-size)*1rem
}
複製程式碼

呼叫方式直接: width: px2rem(175);

方法二:

安裝依賴

npm i postcss-pxtorem --save-dev
複製程式碼

package.json內,在postcss內新增:

"postcss": {
   "plugins": {
     "autoprefixer": {},
     "postcss-pxtorem": {
       "rootValue": 75, // 設計稿寬度的1/10,(JSON檔案中不加註釋,此行註釋及下行註釋均刪除)
       "propList":["*"] // 需要做轉化處理的屬性,如`hight`、`width`、`margin`等,`*`表示全部
    }
   }
 },
複製程式碼

7.常用util

該檔案主要是對一些常用的js進行封裝,例如時間格式化,LocalStorage操作等,相對比較常用的方法,這個檔案可以進行儲存,要用到時直接複製過來用即可。下面是我封裝LocalStorage的檔案,可參考以下,其他自行設定

import Cookies from 'js-cookie'

const TokenKey = 'Authorization'
/*
* 設定setLocalStorage
* */
export function setLocalStorage (key, value) {
    window.localStorage.setItem(key, window.JSON.stringify(value))
}
/*
* 獲取getLocalStorage
* */
export function getLocalStorage (key) {
    return window.JSON.parse(window.localStorage.getItem(key) || '[]')
}
/*
* 設定setSessionStorage
* */
export function setSessionStorage (key, value) {
    window.sessionStorage.setItem(key, window.JSON.stringify(value))
}
/*
* 獲取getSessionStorage
* */
export function getSessionStorage (key) {
    return window.JSON.parse(window.sessionStorage.getItem(key) || '[]')
}
/*
* 獲取getToken
* */
export function getToken () {
    return Cookies.get(TokenKey)
}
/*
* 設定setToken
* */
export function setToken (token) {
    return Cookies.set(TokenKey, token)
}
/*
* 移除removeToken
* */
export function removeToken () {
    return Cookies.remove(TokenKey)
}

複製程式碼

8.引入第三方UI框架

在前端開發過程中,避免一些造輪子情況出現,經常需要一些ui框架,可以根據自己需要引入第三方UI框架,自己進行配置,我選擇了mintui來進行引入。採用了按需引入的方式。

  • 安裝依賴

npm i mint-ui -S

  • 配置按需引入

藉助 babel-plugin-component,我們可以只引入需要的元件,以達到減小專案體積的目的。如果全部引入,檔案太大了。

首先,安裝 babel-plugin-component

npm install babel-plugin-component -D 然後,將 .babel.config.js 修改為:

module.exports = {
  presets: [
    '@vue/app'
  ],
   plugins: [
        [
            "component",
            {
                "libraryName": "mint-ui",
                "style": true
            }
        ]
    ]
}
}
複製程式碼

如果你只希望引入部分元件,比如 Button 和 Cell,那麼需要在 main.js 中寫入以下內容:

import Vue from 'vue'
import { Button, Cell } from 'mint-ui'
import App from './App.vue'

Vue.component(Button.name, Button)
Vue.component(Cell.name, Cell)
/* 或寫為
 * Vue.use(Button)
 * Vue.use(Cell)
 */
複製程式碼

9.配置vue.config.js檔案

  • 基本配置

    1.檔案目錄配置別名 我們可以把src配置為@,如果需要就不用到根目錄開始寫了,直接用@/xxx/進行引用。根據自己需要進行配置,在vue.config.js檔案中加入程式碼

     // 配置
    chainWebpack: (config)=>{
    // 配置別名
    config.resolve.alias
        .set('@', resolve('src'))
        .set('assets',resolve('src/assets'))
        .set('components',resolve('src/components'))
        .set('router',resolve('src/router'))
        .set('utils',resolve('src/utils'))
        .set('static',resolve('src/static'))
        .set('store',resolve('src/store'))
        .set('views',resolve('src/views'))
        }
    複製程式碼

    2.跨域配置 在前端請求過程中,如果後臺沒有設定跨域請求的,可以在webpack進行配置。

    devServer: {
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:8080',
        changeOrigin: true
      }
     }
    }
    複製程式碼

    3.其他配置 具體可以參照官網的配置說明,在專案中我用到了

    assetsDir: 'assets',   // 靜態檔案目錄
    publicPath: './',    // 編譯後的地址,可以根據環境進行設定
    lintOnSave: true, // 是否開啟編譯時是否不符合eslint提示
    複製程式碼

    以上的所有程式碼必須寫在module.exports輸出才能生效.

10.專案框架效能優化 (v1_mint_ui分支)

通過以上的基本配置,專案已經符合我們工作需要了,但是在工作過程中會發現隨著專案的整合度越來越高,業務越來越多。出現了載入慢和打包檔案過大的問題。導致我們頁面白屏時間過長,使用者體驗不友好。那麼如果你感興趣的話,可以進行以下的配置,可以大大大大大的減小體積和載入速度。在master分支是沒有進行優化的,如果需要看優化程式碼可以到另外一個分支。所以在頁面引入的程式碼都是當前頁面需要的執行程式碼,可以往下面幾個方法進行處理。

  • js,css程式碼的最小化壓縮和分割

  • js,css程式碼公用程式碼提取, 按需引入(cdn載入)

  • 圖片檔案的壓縮

  • gzip的壓縮

  • 去除console.log

1.js,css程式碼的最小化壓縮和分割

首先,我們先對js檔案進行配置以達到壓縮效果,先看一下沒有配置程式碼情況,整個app.js 的檔案是2.8M(因為是初始專案),但是如果頁面一多,就不只這個數了。

vue-cli3專案搭建配置以及效能優化

我們會通過chainWebpak來處理. 在優化前, 看下相關檔案的響應程式碼: 看下app.js檔案的返回程式碼:程式碼如下:

vue-cli3專案搭建配置以及效能優化

在vue.config.js檔案中加入,run以下後檢視app.js情況,檔案會變小(由於初始專案體積小,看不出多大區別)。

module.exports = {
  chainWebpack: config => {
    config.optimization.minimize(true);
  }
}
複製程式碼

vue-cli3專案搭建配置以及效能優化

分割程式碼,相應的檔案中存入分割後的程式碼。

module.exports = {
    
    chainWebpack: config => {
        config.optimization.minimize(true);
        config.optimization.splitChunks({
          chunks: 'all'
        })
    }
}


複製程式碼

vue-cli3專案搭建配置以及效能優化

加入以上程式碼後,分成了2個檔案,最大的只有2.7M了,這樣可以分成多個進行載入,可以達到最快化,但是一定要平衡檔案大小的和分割出來的檔案數量的平衡, 數量多了, 請求也會變慢的, 影響效能.可以根據專案的進行設定,具體可參考官方文件的詳細說明。

2.js,css程式碼公用程式碼提取, 按需引入(CDN載入)

把公用程式碼提取出來,然後採用使用免費的cdn資源進行載入。在專案中我們主要是引入引入不同的模組庫才會導致檔案較大,那麼是否可以把這些檔案進一步處理,答案是可以的,比如vue, vuex, vue-router, element-ui等公共資源庫。利用webpack我們可以使用externals引數來配置:

在vue.config.js檔案:

module.exports = {
    chainWebpack: config => {
          // 壓縮程式碼
    config.optimization.minimize(true);
    // 分割程式碼
    config.optimization.splitChunks({
      chunks: 'all'
    })
    // 用cdn方式引入
    config.externals({
      'vue': 'Vue',
      'vuex': 'Vuex',
      'vue-router': 'VueRouter',
      'mint-ui': 'MINT',  // 需用MINT
      'axios': 'axios'
    })
    }
}
複製程式碼

index.html加入CDN地址,注意引入的時候要寫在body裡面,否則會報錯。

    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.runtime.min.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
    <script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js"></script>
    <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
    <script src="https://cdn.bootcss.com/mint-ui/2.2.13/index.js"></script>

複製程式碼

mint-ui樣式通過CDN引入。然後商儲mian.js檔案的 import 'mint-ui/lib/style.css' (全域性引入模式才有)

<link href="https://cdn.bootcss.com/mint-ui/2.2.13/style.min.css" rel="stylesheet">
複製程式碼

如果需要引入其他依賴的CDN可以通過BootCDN查詢進行引入。

重新執行專案, 看看效果,已經大大的減小了很多,到了k級別了:

vue-cli3專案搭建配置以及效能優化

提取css程式碼:

因為js會動態的載入出css,所以js檔案包會比較大,那麼需要提取css程式碼到檔案. 這裡我們只需要將css配置一下:


module.exports = {
  css: {
      extract: true
  }
}
複製程式碼

vue-cli3專案搭建配置以及效能優化

3.圖片檔案的壓縮

圖片檔案大於在webpack設定的值時,我們可以對其進行壓縮在進行引入,安利給大家一個壓縮圖片的網站tinypng.com/,它可以批量的壓縮圖片又不會失真,壓縮比相對較大。可以對圖片進行有效壓縮。

4.gzip的壓縮

如果後臺有對前端的程式碼進行gzip壓縮的話,那麼就不需要進行壓縮了,後臺自己配置就可以。如果後臺不具備這種情況那麼我們可以利用compression-webpack-plugin外掛可以幫助我們進行gzip壓縮:

安裝依賴:

npm install --save-dev compression-webpack-plugin
複製程式碼

然後引入相關程式碼:

const CompressionWebpackPlugin = require('compression-webpack-plugin')

const compress = new CompressionWebpackPlugin(
 {
   filename: info => {
     return `${info.path}.gz${info.query}`
   },
   algorithm: 'gzip', 
   threshold: 10240,
   test: new RegExp(
     '\\.(' +
     ['js'].join('|') +
     ')$'
   ),
   minRatio: 0.8,
   deleteOriginalAssets: false
 }
)
module.exports = {
devServer: {

   before(app, server) { 
     app.get(/.*.(js)$/, (req, res, next) => { 
       req.url = req.url + '.gz';
       res.set('Content-Encoding', 'gzip');
       next();
     })
   }
 }
 configureWebpack: {
     plugins: [compress]
 }
複製程式碼

重新run一遍,出現了意向不到的結果了。又原來的2.8M轉化為250+kb了,縮小了11倍以上。重大突破

vue-cli3專案搭建配置以及效能優化

6.去除console.log

正常情況下我們會在開發環境進行console除錯,但是如果不刪除,過多會出現記憶體洩漏的情況,那麼我們可以在正式環境的時候就把它給幹掉,實現方法如下:

方法一:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
    configureWebpack: config => {
        if (IS_PROD) {
            const plugins = [];
            plugins.push(
                new UglifyJsPlugin({
                    uglifyOptions: {
                        compress: {
                            warnings: false,
                            drop_console: true,
                            drop_debugger: false,
                            pure_funcs: ['console.log']//移除console
                        }
                    },
                    sourceMap: false,
                    parallel: true
                })
            );
            config.plugins = [
                ...config.plugins,
                ...plugins
            ];
        }
    }
}
複製程式碼

方法二:使用babel-plugin-transform-remove-console外掛 npm i --save-dev babel-plugin-transform-remove-console 在babel.config.js中配置

const plugins = [];
if(['production', 'prod'].includes(process.env.NODE_ENV)) {  
  plugins.push("transform-remove-console")
}

module.exports = {
  presets: [["@vue/app",{"useBuiltIns": "entry"}]],
  plugins: plugins
};
複製程式碼

經過以上的所有騷操作,整個專案已經差不多完成了,接下來就靠兄弟們去開發業務和優化了。由於本人技術有限,有錯誤地方還望指出來,如果覺得對你有幫助麻煩點一下贊,或者個星,這是對我最大的幫助。後續打算再寫一個專案的開發過程,自己成長也希望大家希望。有什麼問題可以留言幫忙解決。

最後附上該專案的GitHub:github.com/bayi-lzp/vu…

master分支為基礎包,vi_mint_ui分支為優化後專案,可根據自己需要進行切換。

注:轉載請帶上文章出處,避免帶來不必要麻煩。

相關文章