在以前的開發中主要用的是vue-cli2,最近空閒時間比較多,接下來有新項目,本着偷懶的本能,本身打算搭建一個基礎包以備後期開發應用,並對其進行性能優化和配置。css
該項目的GitHub:github.com/bayi-lzp/vu… 求星html
master分支爲基礎包,vi_mint_ui分支爲優化後項目,可根據本身須要進行切換。前端
搭建整個過程以下:vue
可用命令行或者ui面板進行建立,具體的建立方式及詳細說明,能夠參考個人另外一篇文章 vue-cli3初始化項目搭建node
npm run serve
複製代碼
用編輯器打開後能夠看到目錄結構。相對於vue-cli2精簡了不少,減小了對webpack的配置。webpack
node_modules 文件夾 項目依賴(對webpack進行了封裝)ios
public 文件夾git
1.favicon.ico 是 網站圖標github
2.index.html 頁面入口文件web
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-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://xxxxx.40:9091/pro/',
authBaseURL: ''
},
// 開發環境
'development': {
baseURL: 'http://xxxx:9091/dev/',
authBaseURL: ''
},
// 測試環境
'test': {
baseURL: 'http://xxxxx:9091/test/',
authBaseURL: ''
}
}
export default modeUrlObj[process.env.NODE_ENV]
複製代碼
"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"
},
複製代碼
import config from '../config/index' // 路徑配置
config.baseURL // 對應環境api
複製代碼
4.運行命令行
npm run dev
// 開發環境
npm run test
// 測試環境
npm run build
// 正式環境打包
npm run build:test
// 測試環境打包
在vue項目中,和後臺交互獲取數據這塊,咱們一般使用的是axios庫,它是基於promise的http庫,可運行在瀏覽器端和node.js中。他有不少優秀的特性,例如攔截請求和響應、取消請求、轉換json、客戶端防護XSRF等。因此咱們的尤大大也是果斷放棄了對其官方庫vue-resource的維護,直接推薦咱們使用axios庫。若是還對axios不瞭解的,能夠移步axios文檔。
npm install axios --save; // 安裝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請求文件。根據具體須要分類。主要是方便團隊開發,容易歸類。能夠參考下面配置。
import request from '@/utils/request'
export default {
// 登陸
login (data) {
return request({
url: '/login',
method: 'post',
data
})
},
// 獲取用戶信息
getUserInfo () {
return request({
url: '/userinfo',
method: 'get'
})
}
}
複製代碼
業務中須要進行請求能夠用import後,進行傳參便可。
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
若是對vuex還不大瞭解的能夠自行閱讀vuex官方文檔。
npm install vuex -S
複製代碼
modules文件主要用法存放分類的文件,能夠進行區分,getters文件是對state進行處理,index.js主要進行一些引入,初始化操做。
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
複製代碼
在項目開發過程當中,咱們常常須要全局樣式引用,例如主題色等,若是每次去寫的化會變得很麻煩。由於咱們應該了sass預語言編譯,因此能夠大膽的應用其特性。例如變量,函數,混入等。可是咱們須要在項目中進行全局的配置纔能有效果。不用在每個頁面都進行引入樣式,就能直接引用。
在assets下新建以下文件,具體的代碼自行進行配置
* common.scss 主要存放公共的樣式
* mixin.scss 存放混入樣式
* reset.scss 存放重置樣式。
* variable.scss 存放變量
複製代碼
新建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>
複製代碼
在本項目中主要用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">
實現方法以下:
npm i amfe-flexible --save
方法一:
在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`等,`*`表示所有
}
}
},
複製代碼
該文件主要是對一些經常使用的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)
}
複製代碼
在前端開發過程當中,避免一些造輪子狀況出現,常常須要一些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)
*/
複製代碼
基本配置
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
輸出才能生效.
經過以上的基本配置,項目已經符合咱們工做須要了,可是在工做過程當中會發現隨着項目的集成度愈來愈高,業務愈來愈多。出現了加載慢和打包文件過大的問題。致使咱們頁面白屏時間過長,用戶體驗不友好。那麼若是你感興趣的話,能夠進行如下的配置,能夠大大大大大的減少體積和加載速度。在master分支是沒有進行優化的,若是須要看優化代碼能夠到另一個分支。因此在頁面引入的代碼都是當前頁面須要的執行代碼,能夠往下面幾個方法進行處理。
js,css代碼的最小化壓縮和分割
js,css代碼公用代碼提取, 按需引入(cdn加載)
圖片文件的壓縮
gzip的壓縮
去除console.log
1.js,css代碼的最小化壓縮和分割
首先,咱們先對js文件進行配置以達到壓縮效果,先看一下沒有配置代碼狀況,整個app.js 的文件是4.5M,可是若是頁面一多,就不僅這個數了。
咱們會經過chainWebpak來處理. 在優化前, 看下相關文件的響應代碼: 看下app.js文件的返回代碼:代碼以下:
在vue.config.js文件中加入,run如下後查看app.js狀況,文件會變小。
module.exports = {
chainWebpack: config => {
config.optimization.minimize(true);
}
}
複製代碼
分割代碼,相應的文件中存入分割後的代碼。
module.exports = {
chainWebpack: config => {
config.optimization.minimize(true);
config.optimization.splitChunks({
chunks: 'all'
})
}
}
複製代碼
加入以上代碼後,分紅了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查找進行引入。
從新運行項目, 看看效果,已經大大的減少了不少:
提取css代碼:
由於js會動態的加載出css,因此js文件包會比較大,那麼須要提取css代碼到文件. 這裏咱們只須要將css配置一下:
module.exports = {
css: {
extract: true
}
}
複製代碼
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一遍,出現了意向不到的結果了。又原來的4.5M轉化爲800k了,重大突破
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分支爲優化後項目,可根據本身須要進行切換。
注:轉載請帶上文章出處,避免帶來沒必要要麻煩。