vue-小愛ADMIN系列文章(二):微信微博等分享,國際化,前端效能優化,nginx伺服器部署
最近在做我的小愛ADMIN後臺管理系統,結合當前市場後臺管理系統對相關功能的需求,我又開始新增了一些新的功能和元件,如分享功能元件,專案國際化功能;專案完成後,部署在nginx伺服器,發現首次訪問的速度特別慢,嚴重的影響了使用者體驗,因此,我又開始進行了一系列的前端效能優化;以及將優化後的專案部署到nginx伺服器二級子目錄的注意細節。
- 效果演示地址
- github地址
分享功能
背景說明
用微信,微博等做網站的第三方登入及用微信和支付寶進行支付,都需要註冊開發者賬號和新增網站應用,比較麻煩。另外,註冊的資訊如果在前端頁面裡面進行公開,缺乏安全性。第三方分享功能不需要註冊開發者賬號和新增網站應用,使用者資訊相對保密,使用方法也相對簡單。
前端ui呈現和分享渠道
封裝了8個常用的分享元件,包含仿簡書網站的底部和側欄分享元件、仿掘金網站分享元件、仿新浪網站分享元件和其他一些網站橫向排列的分享元件。包含的分享渠道有:微信、微博、qq、qq空間、豆瓣等。
分享元件的封裝和分享方法的集合
分享效果如圖:
分享元件的封裝:share/index.vue
<template> <div class="shareContainer" ref="shareContainer"> <el-row :gutter="20"> <el-col :span="6"> <heng-share @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></heng-share> </el-col> <el-col :span="6"> <invite-share @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></invite-share> </el-col> <el-col :span="6"> <jianshu-share @shareToWeixin="shareToWeixin" @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></jianshu-share> </el-col> <el-col :span="6"> <jianshu-left-share @shareToWeixin="shareToWeixin" @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></jianshu-left-share> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="6"> <info-share @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></info-share> </el-col> <el-col :span="6"> <juejin-share @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></juejin-share> </el-col> <el-col :span="6"> <sina-share @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></sina-share> </el-col> <el-col :span="6"> <yan-share @shareToQQ="shareToQQ" @shareToQQzone="shareToQQzone" @shareToWeibo="shareToWeibo" @shareToDouban="shareToDouban"></yan-share> </el-col> </el-row> <wx-code-modal v-if="wxModal.show" :wxModal="wxModal" @hideWxCodeModal="hideWxCodeModal"></wx-code-modal> </div> </template>
分享方法的集合:utils/share.js
import { weibo,qq,qqZone,douban,shareUrl,shareTitle } from "@/utils/env"; import * as mutils from "@/utils/mUtils"; function getParamsUrl(obj){ let paramsUrl = ''; for(let key in obj){ paramsUrl += key+'='+obj[key]+'&' } return paramsUrl; } export function shareConfig(type,obj){ let baseUrl = ''; if(mutils.isEmpty(obj)){ obj = {}; } switch(type){ case 'weibo': const weiboData = { 'url':shareUrl, // 內容連結,預設當前頁面location 'title':shareTitle, // 可選引數, 預設當前頁title 'pic':obj.pic || weibo.pic, // 分享圖片的路徑(可選),多張圖片通過"||"分開。 'count':'y', /**是否顯示分享數,y|n(可選)*/ 'searchPic':true // 是否要自動抓取頁面上的圖片。true|falsetrue:自動抓取,false:不自動抓取。 } baseUrl = weibo.weiboUrl+'?appkey='+weibo.weiboAppkey+getParamsUrl(weiboData); window.open(baseUrl,'_blank'); break; case 'qq': const qqData = { 'url':shareUrl, 'title':shareTitle, 'pics':obj.pic || qq.pic, //QZone介面暫不支援傳送多張圖片的能力,若傳入多張圖片,則會自動選入第一張圖片作為預覽圖。 'source':obj.source || qq.source, // 分享來源 'desc':obj.desc || qq.desc, 'summary':obj.summary || qq.summary, } baseUrl = qq.baseUrl+'?'+getParamsUrl(qqData) window.open(baseUrl,'_blank'); break; case 'qqZone': const qqZoneData = { 'url':shareUrl, 'title':shareTitle, 'pics':obj.pic || (qqZone.pic).split(','), 'sharesource':obj.sharesource || qqZone.sharesource, // 分享來源 'desc':obj.desc || qqZone.desc, 'summary':obj.summary || qqZone.summary, } baseUrl = qqZone.baseUrl+'?'+getParamsUrl(qqZoneData) window.open(baseUrl,'_blank'); break; case 'douban': const doubanData = { 'href':shareUrl, 'name':shareTitle, 'image':obj.pic || douban.pic, } baseUrl = douban.baseUrl+'?'+getParamsUrl(doubanData) window.open(baseUrl,'_blank'); break; } }
微博分享後的效果,如圖:
qq分享後的效果,如圖:
Vue專案實現國際化(i18n)
背景說明
由於本專案需要多語言的支援,我們需要做國際化。我們使用 vue-i18n 來實現多語言的介面。
使用步驟
1.安裝vue-i18n
npm install vue-i18n --save
關於語言包,我們有幾種方式:一種是每個語言包一個獨立的js放到專案裡;或者將語言的對照寫在 .vue 檔案裡, 或者載入遠端的JSON語言包
我們的後臺介面需要支援的語言通常不多,更新也不會非常的頻繁,所以我們將語言包放在專案裡,規劃專案目錄,增加 lang 目錄來存放語言對照。
2.新建lang資料夾,用於儲存語言包並匯出
中文語言包配置:src/lang/zh.js
const zh = {
// layout
commons: {
xiaoai: '小愛',
admin: '管理員',
editor: '趙曉編',
quit: '退出',
hi: '您好',
index: '首頁',
userManage: '使用者管理',
share: '分享功能',
infoManage: '資訊管理',
infoShow: '個人資訊',
infoShow1: '個人資訊子選單1',
infoShow2: '個人資訊子選單2',
infoShow3: '個人資訊子選單3',
infoShow4: '個人資訊子選單4',
infoShow5: '個人資訊子選單5',
infoModify: '修改資訊',
infoModify1:'修改資訊子選單1',
infoModify2:'修改資訊子選單2',
infoModify3:'修改資訊子選單3',
fundManage: '資金管理',
fundList: '資金流水',
chinaTabsList: '區域投資',
fundData: '資金資料',
fundPosition: '投資分佈',
typePosition: '專案分佈',
incomePayPosition: '收支分佈',
permission: '許可權設定',
pagePer: '頁面許可權',
directivePer: '按鈕許可權',
errorPage: '錯誤頁面',
page401:'401',
page404:'404',
wechatNumber: '微訊號'
},
index:{
yearLoss:'年度總盈虧',
yearProfit:'年度收益率',
potentialInvestor:'潛在投資人',
intentionInvestor:'意向投資人',
waitExamineInvestor:'待審投資人',
examiningInvestor:'稽核中投資人',
tenMillion:'千萬元',
person:'人'
}
}
export default zh;
英文語言包配置:src/lang/en.js
const zh = {
// layout
commons: {
xiaoai: 'Ai.',
admin: 'Admin',
editor: 'Editor',
quit: 'Sign Out',
hi: 'Hi',
index: 'Dashboard',
userManage: 'Users',
share: 'Share',
infoManage: 'Infos',
infoShow: 'InfoShow',
infoShow1: 'InfoShow1',
infoShow2: 'InfoShow2',
infoShow3: 'InfoShow3',
infoShow4: 'InfoShow4',
infoShow5: 'InfoShow5',
infoModify: 'InfoModify',
infoModify1:'InfoModify1',
infoModify2:'InfoModify2',
infoModify3:'InfoModify3',
fundManage: 'Money',
fundList: 'MoneyList',
chinaTabsList: 'AreaList',
fundData: 'FundData',
fundPosition: 'FundPosition',
typePosition: 'TypePosition',
incomePayPosition: 'IncomePayPosition',
permission: 'Permission',
pagePer: 'PagePermission',
directivePer: 'DirectivePermission',
errorPage: 'ErrorPage',
page401:'401',
page404:'404',
wechatNumber: 'wechat'
},
index:{
yearLoss:'Year Loss',
yearProfit:'Year Profit',
potentialInvestor:'Potential Investor',
intentionInvestor:'Intention Investor',
waitExamineInvestor:'Wait Examine Investor',
examiningInvestor:'Examining Investor',
tenMillion:'Ten Million',
person:'P'
}
}
export default zh;
匯出配置:src/lang/index.js
// 引入i18n國際化外掛
import { getToken} from '@/utils/auth'
import Vue from 'vue'
import VueI18n from 'vue-i18n'
process.env.NODE_ENV === "development" ? Vue.use(VueI18n) : null;
import enLocale from './en'
import zhLocale from './zh'
// 註冊i18n例項並引入語言檔案,檔案格式等下解析
const i18n = new VueI18n({
locale: getToken('lang') || 'en',
messages: {
zh: {
...zhLocale
},
en: {
...enLocale
},
}
});
export default i18n;
注意: locale: getToken('lang') || 'en',主要用來儲存已經點選過的語言項,以便在專案重新整理的時候,還能夠拿到cookie中儲存的語言類別。
3.在專案入口檔案main.js中引入i18n
// i18n國際化
import i18n from "@/lang";
new Vue({
router,
store,
i18n, // 便於可以直接在元件中通過this.$i18n使用,也可以按需引用
render: h => h(App),
}).$mount('#app')
4.頁面元件中使用方法$t()
<div class='welcome'>
<span class="name">{{$t('commons.hi')}},</span>
<span class='name avatarname'> {{ $t(`commons.${name}`)}}</span>
</div>
注意:$t('commons.hi'),這是直接匯入的方法;$t(commons.${name}
),這是匯入變數的方法。
5.點選切換語言方法
效果如圖:
<el-submenu index="1" popper-class="langItem">
<template slot="title">
<img :src="langLogo" class='langAvatar' alt="">
</template>
<el-menu-item index="1-1" @click="changeLocale('zh')">
<img :src="chinaImg" class='langAvatar' alt="">
<span class="intro">中文</span>
</el-menu-item>
<el-menu-item index="1-2" @click="changeLocale('en')">
<img :src="americaImg" class='langAvatar' alt="">
<span class="intro">EngList</span>
</el-menu-item>
</el-submenu>
// 切換語言
changeLocale(type){
setToken('lang',type);
this.$i18n.locale = type;
if(type === 'en'){
this.langLogo = this.americaImg;
}else{
this.langLogo = this.chinaImg;
}
setToken('langLogo',this.langLogo);
}
基於cli3.0的vue專案的效能優化
詳細效能優化配置,請參考:vue.config.js
vue-cli 3.0 build包太大導致首屏載入過長,嚴重的影響了使用者體驗。因此,我們需要從以下方面提供相應的解決方案。
1.productionSourceMap:false
可以使得打包過後的檔案不包含未壓縮的.map檔案,減少壓縮後代碼體積。
2.專案中引入圖片壓縮(圖片線上免費壓縮網站 https://www.yasuotu.com/)或者將圖片放到cdn上面進行引用。
3.路由懶載入
原因:“懶載入也叫延遲載入,即在需要的時候進行載入,隨用隨載。在單頁應用中,如果沒有應用懶載入,運用webpack打包後的檔案將會異常的大,造成進入首頁時,需要載入的內容過多,延時過長,不利於使用者體驗,而運用懶載入則可以將頁面進行劃分,需要的時候載入頁面,可以有效的分擔首頁所承擔的載入壓力,減少首頁載入用時。”
方法一:resolve
vue-router配置路由 , 使用vue的非同步元件技術 , 可以實現按需載入 .
但是,這種情況下一個元件生成一個js檔案
程式碼如下:
{
path: '/login',
name: 'login',
component:function(resolve){
require(['@/page/login.vue'],resolve)
}
}
方法二:官網方法 import()
程式碼如下:
{
path: '/login',
name: 'login',
component:() => import('@/page/login')
}
方法三:webpack的require,ensure()
這種情況下,多個路由指定相同的chunkName,會合並打包成一個js檔案。
程式碼如下:
path: '/login',
name: 'login',
component: r => require.ensure([], () => r(require('@/page/login')), 'demo')
4. 伺服器開啟Gzip(compression-webpack-plugin)
const CompressionPlugin = require("compression-webpack-plugin"); // gzip壓縮,優化http請求,提高載入速度
configureWebpack:config => {
// 為生產環境修改配置...
if (process.env.NODE_ENV === 'production') {
// 開啟gzip壓縮
config.plugins.push(new CompressionPlugin({
algorithm: 'gzip',
test: new RegExp("\\.(" + ["js", "css"].join("|") + ")$"), // 匹配副檔名
// threshold: 10240, // 對超過10k的資料進行壓縮
threshold: 5120, // 對超過5k的資料進行壓縮
minRatio: 0.8,
cache: true, // 是否需要快取
deleteOriginalAssets:false // true刪除原始檔(不建議);false不刪除原始檔
}))
}
}
注意:使用compression-webpack-plugin開啟伺服器Gzip,所以也需要在服務端進行配置,以便能夠解析gzip檔案;nginx端配置如下:
gzip on;
gzip_comp_level 4;
gzip_buffers 4 16k;
gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1k;
gzip_http_version 1.1;
5. 生成環境剔除debuger和console(TerserPlugin/UglifyJsPlugin)
const TerserPlugin = require('terser-webpack-plugin')
configureWebpack:config => {
// 為生產環境修改配置...
if (process.env.NODE_ENV === 'production') {
// 去除console來減少檔案大小,效果同'UglifyJsPlugin'
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true, // Must be set to true if using source-maps in production
terserOptions: {
compress: {
warnings: false,
drop_console: true,
drop_debugger: true,
pure_funcs: ['console.log']
}
}
})
}
}
6. 啟用CDN加速(configureWebpack,config.externals)
背景:在Vue專案中,引入到工程中的所有js、css檔案,編譯時都會被打包進vendor.js,瀏覽器在載入該檔案之後才能開始顯示首屏。若是引入的庫眾多,那麼vendor.js檔案體積將會相當的大,影響首開的體驗。
解決方法:將引用的外部js、css檔案剝離開來,不編譯到vendor.js中,而是用資源的形式引用,這樣瀏覽器可以使用多個執行緒非同步將vendor.js、外部的js等載入下來,達到加速首開的目的。
外部的庫檔案,可以使用CDN資源,或者別的伺服器資源等。
步驟:
(1).配置要忽略的生產環境下被打包的檔案
// 忽略生產環境打包的檔案
config.externals = {
"vue": "Vue",
"vue-router": "VueRouter",
"vuex": "Vuex",
"vue-i18n": "VueI18n",
"axios": "axios",
'element-ui': 'ELEMENT',
'echarts':'echarts',
'mockjs':'Mock',
'nprogress':'NProgress',
'js-cookie':'Cookies'
}
(2).定義不同環境下的cdn資料
具體cdn資料,請參考:https://www.bootcdn.cn/
const cdn = {
// 開發環境
dev: {
css: [],
js: []
},
// 生產環境
build: {
css: [
'https://cdn.bootcss.com/element-ui/2.11.1/theme-chalk/index.css',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
],
js: [
'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
'https://cdn.bootcss.com/vue-router/3.1.2/vue-router.min.js',
'https://cdn.bootcss.com/vuex/2.3.1/vuex.min.js',
'https://cdn.bootcss.com/axios/0.19.0/axios.min.js',
'https://cdn.bootcss.com/vue-i18n/8.13.0/vue-i18n.min.js',
'https://cdn.bootcss.com/element-ui/2.11.1/index.js',
'https://cdn.bootcss.com/echarts/3.8.5/echarts.min.js',
'https://cdn.bootcss.com/Mock.js/1.0.1-beta3/mock-min.js',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js',
'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js'
]
}
}
(3).新增CDN引數到htmlWebpackPlugin配置中
config
.plugin('html')
.tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].cdn = cdn.build
}
if (process.env.NODE_ENV === 'development') {
args[0].cdn = cdn.dev
}
return args
})
(4).更改專案Router,Vuex,nprogress,mock,VueI18n等引入方式
意思是隻在開發環境引入相關的包,生產環境用cdn外鏈。
process.env.NODE_ENV === "development" ? Vue.use(Router) : null;// router/index.js
process.env.NODE_ENV === "development" ? Vue.use(Vuex) : null;// store/index.js
process.env.NODE_ENV === "development" && import('nprogress/nprogress.css') // src/permission.js
process.env.NODE_ENV === "development" ? Vue.use(Mock) : null;//mockjs/index.js
process.env.NODE_ENV === "development" ? Vue.use(VueI18n) : null;//lang/index.js
效果如圖:
注意:使用cdn外鏈,減少打包檔案體積;更多適用於在生產環境,而在開發環境,我們還可以繼續用以前的npm包。
7.首屏加個loading小菊花動畫;
效能優化前後的資料對比:
優化前:
優化後:
nginx伺服器部署
專案開發完成後,我們將進行伺服器的部署;部署分為:部署在跟目錄和部署在子目錄,這兩種情況,前端publicPath配置也是不一樣的,否則,伺服器資源會顯示404,無法載入。
注意:本專案伺服器為 windows系統,所以以下配置為windows系統配置;如果你是linux系統伺服器,請參考linux伺服器部署配置。
準備工作:
下載nginx伺服器;
下載網址:請參考;選擇該穩定版本下載;下載完成後,將該檔案上傳到你的伺服器目錄並解壓。如圖:
執行npm run build.將打包後的專案檔案dist,複製到你的伺服器目錄(我的dist檔案目標為:C:\ownprogram\vue\vue-touzi,我的nginx檔案所在目標為:C:\ownprogram\nginx-1.8.1);接下來,開始對nginx-1.8.1/config/nginx.config檔案進行配置。
部署在跟目錄
本專案部署的跟目錄為:C:\ownprogram\vue\vue-touzi\dist,預設為80埠;
vue.config.js中publicPath配置,如下:
module.exports = {
publicPath: process.env.NODE_ENV === "production" ? "./" : "/"
}
nginx.config,如下:
http {
include mime.types;
default_type application/octet-stream;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
gzip on;
gzip_comp_level 4;
gzip_buffers 4 16k;
gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1k;
gzip_http_version 1.1;
server {
listen 80;
server_name localhost;
charset utf-8;
#access_log logs/host.access.log main;
location / {
root C:\ownprogram\vue\vue-touzi\dist\;
index index.html index.htm;
try_files $uri $uri/ /permission/index.html;
proxy_set_header Accept-Encoding 'gzip';
}
location /permission {
alias C:\ownprogram\vue\vue-touzi\dist\permission;
index index.html;
try_files $uri $uri/ /permission/index.html;
proxy_set_header Accept-Encoding 'gzip';
}
}
部署在子目錄
因為本專案C:\ownprogram\vue\vue-touzi\dist\預設為跟目錄,屬於dist/permission及為二級子目錄;
router/index.js配置,如下:
//註冊路由
export default new Router({
mode:'history', // 預設為'hash'模式
base: '/permission/', // 新增跟目錄,對應伺服器部署子目錄
routes: constantRouterMap
})
vue.config.js中publicPath配置,如下:
module.exports = {
publicPath: process.env.NODE_ENV === "production" ? "/permission/" : "/"
}
nginx.config,新增location配置,如下:
location /permission {
alias C:\ownprogram\vue\vue-touzi\dist\permission;
index index.html;
try_files $uri $uri/ /permission/index.html;
proxy_set_header Accept-Encoding 'gzip';
}
配置完成後,儲存檔案;重啟nginx即可進行正常訪問;
nginx常用命令如下
- 啟動服務:start nginx
- 配置檔案修改重啟服務:nginx -s reload
- 快速停止或關閉Nginx:nginx -s stop
- 正常停止或關閉Nginx:nginx -s quit
- 檢視Nginx的版本號:nginx -V
- 檢視windows工作管理員下Nginx的程序命令:tasklist /fi "imagename eq nginx.exe"
專案說明
小愛ADMIN是完全開源免費的管理系統整合方案,可以直接應用於相關後臺管理系統模板;很多重點地方都做了詳細的註釋和解釋。如果你也一樣喜歡前端開發,歡迎加入我們的討論/學習群,群內可以提問答疑,分享學習資料; 歡迎加入答疑qq群。
技術答疑