您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)vue-cli3從搭建到優(yōu)化的案例的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
前言
demo地址: vue-project-demo.eloco.cn
安裝與初始化架構(gòu)
安裝
node >= 8.9 推薦:8.11.0 +
安裝: npm install -g @vue/cli
檢查: vue --version
如果已安裝舊版本,需要先 npm uninstall vue-cli -g
卸載掉舊版本。
初始化架構(gòu)
創(chuàng)建: vue create project-name
注:項(xiàng)目名稱不能駝峰命名。
選擇一個(gè)預(yù)設(shè)(這里我選擇更多功能):
選擇需要安裝的(Babel、Router、Vuex、Pre-processors、Linter / Formatter):
是否使用history路由模式(Yes):
選擇css 預(yù)處理器(Sass/SCSS):
選擇eslint 配置(ESLint + Standard config):
選擇什么時(shí)候執(zhí)行eslint校驗(yàn)(Lint on save):
選擇以什么樣的形式配置以上所選的功能(In dedicated config files):
是否將之前的設(shè)置保存為一個(gè)預(yù)設(shè)模板(y):
如果選擇 y 會(huì)讓輸入名稱,以便下次直接使用,否則直接開始初始化項(xiàng)目。
最后,看一下生成的基本架構(gòu)目錄:
在項(xiàng)目中優(yōu)雅的使用svg 首先在 /src/components
創(chuàng)建 SvgIcon.vue
:
在 src/
下創(chuàng)建 icons
文件夾,以及在其下創(chuàng)建 svg
文件夾用于存放svg文件,創(chuàng)建 index.js
作為入口文件:
編寫index.js 的腳本:
import Vue from 'vue' import SvgIcon from '@/components/SvgIcon.vue' // svg組件 // 全局注冊(cè) Vue.component('svg-icon', SvgIcon) const requireAll = requireContext => requireContext.keys().map(requireContext) const req = require.context('./svg', false, /\.svg$/) requireAll(req)
使用 svg-sprite-loader
對(duì)項(xiàng)目中使用的 svg
進(jìn)行處理:
npm install svg-sprite-loader --save-dev
;
修改默認(rèn)的 webpack
配置, 在項(xiàng)目根目錄創(chuàng)建 vue.config.js
,代碼如下;
const path = require('path') function resolve(dir) { return path.join(__dirname, './', dir) } module.exports = { chainWebpack: config => { // svg loader const svgRule = config.module.rule('svg') // 找到svg-loader svgRule.uses.clear() // 清除已有的loader, 如果不這樣做會(huì)添加在此loader之后 svgRule.exclude.add(/node_modules/) // 正則匹配排除node_modules目錄 svgRule // 添加svg新的loader處理 .test(/\.svg$/) .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) // 修改images loader 添加svg處理 const imagesRule = config.module.rule('images') imagesRule.exclude.add(resolve('src/icons')) config.module .rule('images') .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/) } }
最后,在 main.js
中引入 import '@/icons'
即可;
// 使用示例 <svg-icon icon-class="add" />
PS:至于svg ,個(gè)人比較建議使用阿里開源的圖標(biāo)庫(kù)iconFont
axios封裝api、模塊化vuex
axios篇
項(xiàng)目中安裝 axios
: npm install axios
;
在 src
目錄下創(chuàng)建 utils/
, 并創(chuàng)建 request.js
用來(lái)封裝 axios
,上代碼:
import axios from 'axios' // 創(chuàng)建axios 實(shí)例 const service = axios.create({ baseURL: process.env.BASE_API, // api的base_url timeout: 10000 // 請(qǐng)求超時(shí)時(shí)間 }) // request 攔截器 service.interceptors.request.use( config => { // 這里可以自定義一些config 配置 return config }, error => { // 這里處理一些請(qǐng)求出錯(cuò)的情況 console.log(error) Promise.reject(error) } ) // response 攔截器 service.interceptors.response.use( response => { const res = response.data // 這里處理一些response 正常放回時(shí)的邏輯 return res }, error => { // 這里處理一些response 出錯(cuò)時(shí)的邏輯 return Promise.reject(error) } ) export default service
既然要使用 axios
,必不可少的需要配置環(huán)境變量以及需要請(qǐng)求的地址,這里可以簡(jiǎn)單的修改 poackage.json
:
"scripts": { "dev": "vue-cli-service serve --project-mode dev", "test": "vue-cli-service serve --project-mode test", "pro": "vue-cli-service serve --project-mode pro", "pre": "vue-cli-service serve --project-mode pre", "build:dev": "vue-cli-service build --project-mode dev", "build:test": "vue-cli-service build --project-mode test", "build:pro": "vue-cli-service build --project-mode pro", "build:pre": "vue-cli-service build --project-mode pre", "build": "vue-cli-service build", "lint": "vue-cli-service lint" },
同時(shí)修改vue.config.js:
const path = require('path') function resolve(dir) { return path.join(__dirname, './', dir) } module.exports = { chainWebpack: config => { // 這里是對(duì)環(huán)境的配置,不同環(huán)境對(duì)應(yīng)不同的BASE_API,以便axios的請(qǐng)求地址不同 config.plugin('define').tap(args => { const argv = process.argv const mode = argv[argv.indexOf('--project-mode') + 1] args[0]['process.env'].MODE = `"${mode}"` args[0]['process.env'].BASE_API = '"http://47.94.138.75:8000"' return args }) // svg loader const svgRule = config.module.rule('svg') // 找到svg-loader svgRule.uses.clear() // 清除已有的loader, 如果不這樣做會(huì)添加在此loader之后 svgRule.exclude.add(/node_modules/) // 正則匹配排除node_modules目錄 svgRule // 添加svg新的loader處理 .test(/\.svg$/) .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) // 修改images loader 添加svg處理 const imagesRule = config.module.rule('images') imagesRule.exclude.add(resolve('src/icons')) config.module .rule('images') .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/) } }
如何使用? 我比較建議在 src/
下創(chuàng)建 api
目錄,用來(lái)統(tǒng)一管理所有的請(qǐng)求,比如下面這樣: ‘'
這樣的好處是方便管理、后期維護(hù),還可以和后端的微服務(wù)對(duì)應(yīng),建立多文件存放不同模塊的 api
。剩下的就是你使用到哪個(gè)api時(shí),自己引入便可。
拓展:服務(wù)端的cors設(shè)置
牽涉到跨域,這里采用 cors
,很多朋友在面試中經(jīng)常會(huì)被問到cors的實(shí)現(xiàn)原理,這個(gè)網(wǎng)上有很多理論大多是這樣講的:
其實(shí),這樣理解很抽象,服務(wù)器端到底是怎么做驗(yàn)證的?
這里大家可以通俗的理解為后端在接收前端的 request
請(qǐng)求的時(shí)候,會(huì)有一個(gè) request
攔截器,像 axios response
攔截器一樣。下面以 php lumen
框架為例,來(lái)深入理解一下這個(gè)流程:
<?php namespace App\Http\Middleware; use App\Http\Utils\Code; use Closure; use Illuminate\Http\Response; use Illuminate\Support\Facades\Log; class CorsMiddleware { private $headers; /** * 全局 : 解決跨域 * @param $request * @param \Closure $next * @return mixed * @throws \HttpException */ public function handle($request, Closure $next) { //請(qǐng)求參數(shù) Log::info('http request:'.json_encode(["request_all" => $request->all()])); $allowOrigin = [ 'http://47.94.138.75', 'http://localhost', ]; $Origin = $request->header("Origin"); $this->headers = [ 'Access-Control-Allow-Headers' => 'Origin,x-token,Content-Type', 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Credentials' => 'true',//允許客戶端發(fā)送cookie 'Access-Control-Allow-Origin' => $Origin, //'Access-Control-Max-Age' => 120, //該字段可選,間隔2分鐘驗(yàn)證一次是否允許跨域。 ]; //獲取請(qǐng)求方式 if ($request->isMethod('options')) { if (in_array($Origin, $allowOrigin)) { return $this->setCorsHeaders(new Response(json_encode(['code' => Code::SUCCESS, "data" => 'success', "msg" => ""]), Code::SUCCESS)); } else { return new Response(json_encode('fail', 405)); } } $response = $next($request); //返回參數(shù) Log::info('http response:'.json_encode($response)); return $this->setCorsHeaders($response); } /** * @param $response * @return mixed */ public function setCorsHeaders($response) { foreach ($this->headers as $key => $val) { $response->header($key, $val); } return $response; } }
vuex 篇
如果創(chuàng)建項(xiàng)目的時(shí)候,選擇了 vuex
,那么默認(rèn)會(huì)在 src
目錄下有一個(gè) store.js
作為倉(cāng)庫(kù)文件。但在更多實(shí)際場(chǎng)景中,如果引入 vuex
,那么肯定避免不了分模塊,先來(lái)看一下默認(rèn)文件代碼:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { }, mutations: { }, actions: { } })
那么現(xiàn)在改造一下,比如先劃分出 app
、 user
兩個(gè)模塊,可以這樣:
import Vue from 'vue' import Vuex from 'vuex' import app from './store/modules/app' import user from './store/modules/user' import getters from './store/getters' Vue.use(Vuex) const store = new Vuex.Store({ modules: { app, user }, getters }) export default store
在 src/
下創(chuàng)建 store/
目錄:
app module
可以用來(lái)存儲(chǔ)應(yīng)用的狀態(tài),比如接下來(lái)要講到的全局 loading
,或者控制第三方組件的全局大小,比如 element ui
中的全局組件 size
;
user module
可以用來(lái)存儲(chǔ)當(dāng)前用戶的信息;
當(dāng)然,store 配合本地存儲(chǔ)比較完美,這里采用 js-cookie
。
全局loading、合理利用vue router守衛(wèi)
全局loading
上面說(shuō)完了 axios、vuex
,現(xiàn)在結(jié)合之前說(shuō)一下設(shè)置全局 loading
效果。
平常寫代碼每個(gè)請(qǐng)求之前一般都需要設(shè)置 loading
,成功之后結(jié)束 loading
效果,這就迫使我們不得不寫大量重復(fù)代碼,如果不想這樣做,可以結(jié)合 axios
和 vuex
統(tǒng)一做了。
首先,在說(shuō) vuex
的時(shí)候,我在 src/
下創(chuàng)建了一個(gè) store
,現(xiàn)在就在 store/modules/app.js
寫這個(gè) Loading
效果的代碼;
const app = { state: { requestLoading: 0 }, mutations: { SET_LOADING: (state, status) => { // error 的時(shí)候直接重置 if (status === 0) { state.requestLoading = 0 return } state.requestLoading = status ? ++state.requestLoading : --state.requestLoading } }, actions: { SetLoading ({ commit }, status) { commit('SET_LOADING', status) } } } export default app
再來(lái)修改一下 utils/request.js
import axios from 'axios' import store from '@/store' // 創(chuàng)建axios 實(shí)例 const service = axios.create({ baseURL: process.env.BASE_API, // api的base_url timeout: 10000 // 請(qǐng)求超時(shí)時(shí)間 }) // request 攔截器 service.interceptors.request.use( config => { // 這里可以自定義一些config 配置 // loading + 1 store.dispatch('SetLoading', true) return config }, error => { // 這里處理一些請(qǐng)求出錯(cuò)的情況 // loading 清 0 setTimeout(function () { store.dispatch('SetLoading', 0) }, 300) console.log(error) Promise.reject(error) } ) // response 攔截器 service.interceptors.response.use( response => { const res = response.data // 這里處理一些response 正常放回時(shí)的邏輯 // loading - 1 store.dispatch('SetLoading', false) return res }, error => { // 這里處理一些response 出錯(cuò)時(shí)的邏輯 // loading - 1 store.dispatch('SetLoading', false) return Promise.reject(error) } ) export default service
其次,在 src/components/
下創(chuàng)建 RequestLoading.vue
組件:
<template> <transition name="fade-transform" mode="out-in"> <div class="request-loading-component" v-if="requestLoading"> <svg-icon icon-class="loading" /> </div> </transition> </template> <script> import { mapGetters } from 'vuex' export default { name: 'RequestLoading', computed: { ...mapGetters([ 'requestLoading' ]) } } </script> <style lang='scss' scoped> .request-loading-component { position: fixed; left: 0; right: 0; top: 0; bottom: 0; //background-color: rgba(48, 65, 86, 0.2); background-color: transparent; font-size: 150px; display: flex; flex-direction: row; justify-content: center; align-items: center; z-index: 999999; } </style>
最后,在 app.vue
中引入即可。
附: 為了方便演示,項(xiàng)目里出了初始化包括 axios
、 vuex
、 vue-router
, 項(xiàng)目使用了 js-cookie
、 element-ui
等,此步驟之后,會(huì)改造一下 app.vue
;
vue router守衛(wèi)
vue-router 提供了非常方便的鉤子,可以讓我們?cè)谧雎酚商D(zhuǎn)的時(shí)候做一些操作,比如常見的權(quán)限驗(yàn)證。
首先,需要在 src/utils/
下創(chuàng)建 auth.js
,用于存儲(chǔ)token;
import Cookies from 'js-cookie' const TokenKey = 'project-token' export function getToken () { return Cookies.get(TokenKey) } export function setToken (token) { return Cookies.set(TokenKey, token) } export function removeToken () { return Cookies.remove(TokenKey) }
在 src/utils/
下創(chuàng)建 permission.js
:
import router from '@/router' import store from '@/store' import { getToken } from './auth' import NProgress from 'nprogress' // 進(jìn)度條 import 'nprogress/nprogress.css' // 進(jìn)度條樣式 import { Message } from 'element-ui' const whiteList = ['/login'] // 不重定向白名單 router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { if (to.path === '/login') { next({ path: '/' }) NProgress.done() } else { // 實(shí)時(shí)拉取用戶的信息 store.dispatch('GetUserInfo').then(res => { next() }).catch(err => { store.dispatch('FedLogOut').then(() => { Message.error('拉取用戶信息失敗,請(qǐng)重新登錄!' + err) next({ path: '/' }) }) }) } } else { if (whiteList.includes(to.path)) { next() } else { next('/login') NProgress.done() } } }) router.afterEach(() => { NProgress.done() // 結(jié)束Progress })
Nginx try_files 以及 404
nginx
配置如下:
location / { root /www/vue-project-demo/; try_files $uri $uri/ /index.html index.htm; }
try_files
: 可以理解為nginx 不處理你的這些url地址請(qǐng)求; 那么服務(wù)器如果不處理了,前端要自己做一些404 操作,比如下面這樣:
// router.js import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' Vue.use(Router) export default new Router({ mode: 'history', base: process.env.BASE_URL, routes: [ { path: '/404', component: () => import('@/views/404') }, { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ './views/About.vue') }, { path: '*', redirect: '/404' } ] })
然后寫一個(gè)404 的view 就ok 。
常用的utils
到現(xiàn)在為止, utils/
目錄下應(yīng)該有 auth.js 、permission.js、request.js
;
那么對(duì)與一些常用的方法,你可以放到 utils/common.js
里,統(tǒng)一 install
到 vue
實(shí)例上,并通過(guò) Vue.use()
使用;
對(duì)于一些全局的過(guò)濾器,你仍可以放到 utils/filters.js
里,使用 Vue.fileter()
注冊(cè)到全局;
對(duì)于一些全局方法,又不是很長(zhǎng)用到的,可以放到 utils/index.js
,哪里使用哪里 import
mixin減少項(xiàng)目冗余代碼
直接看代碼吧,要寫奔潰了....
使用cdn減少文件打包的體積
到此時(shí),看我項(xiàng)目里都用了什么:
主要就是這些,那么執(zhí)行一下打包命令呢?
可能這時(shí)候你還覺得沒什么, 單文件最多的還沒超過(guò) 800kb
呢...
我把項(xiàng)目通過(guò) jenkins
部署到服務(wù)器上,看一下訪問:
可以看到, chunk-vendors
加載了將近12秒,這還是只有框架沒有內(nèi)容的前提下,當(dāng)然你可能說(shuō)你項(xiàng)目中用不到 vuex
、用不到 js-cookie
,但是隨著項(xiàng)目的迭代維護(hù),最后肯定不比現(xiàn)在小。
那么,有些文件在生產(chǎn)環(huán)境是不是可以嘗試使用 cdn
呢?
為了方便對(duì)比,這里保持原代碼不動(dòng)( master
分支),再切出來(lái)一個(gè)分支改動(dòng)優(yōu)化( optimize
分支), 上代碼:
// vue.config.js 修改 const path = require('path') function resolve(dir) { return path.join(__dirname, './', dir) } // cdn預(yù)加載使用 const externals = { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'axios': 'axios', 'element-ui': 'ELEMENT', 'js-cookie': 'Cookies', 'nprogress': 'NProgress' } const cdn = { // 開發(fā)環(huán)境 dev: { css: [ 'https://unpkg.com/element-ui/lib/theme-chalk/index.css', 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css' ], js: [] }, // 生產(chǎn)環(huán)境 build: { css: [ 'https://unpkg.com/element-ui/lib/theme-chalk/index.css', 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css' ], js: [ 'https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js', 'https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.min.js', 'https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js', 'https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js', 'https://unpkg.com/element-ui/lib/index.js', 'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js', 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js' ] } } module.exports = { chainWebpack: config => { // 這里是對(duì)環(huán)境的配置,不同環(huán)境對(duì)應(yīng)不同的BASE_API,以便axios的請(qǐng)求地址不同 config.plugin('define').tap(args => { const argv = process.argv const mode = argv[argv.indexOf('--project-mode') + 1] args[0]['process.env'].MODE = `"${mode}"` args[0]['process.env'].BASE_API = '"http://47.94.138.75:8000"' return args }) /** * 添加CDN參數(shù)到htmlWebpackPlugin配置中, 詳見public/index.html 修改 */ 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 }) // svg loader const svgRule = config.module.rule('svg') // 找到svg-loader svgRule.uses.clear() // 清除已有的loader, 如果不這樣做會(huì)添加在此loader之后 svgRule.exclude.add(/node_modules/) // 正則匹配排除node_modules目錄 svgRule // 添加svg新的loader處理 .test(/\.svg$/) .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) // 修改images loader 添加svg處理 const imagesRule = config.module.rule('images') imagesRule.exclude.add(resolve('src/icons')) config.module .rule('images') .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/) }, // 修改webpack config, 使其不打包externals下的資源 configureWebpack: config => { const myConfig = {} if (process.env.NODE_ENV === 'production') { // 1. 生產(chǎn)環(huán)境npm包轉(zhuǎn)CDN myConfig.externals = externals } if (process.env.NODE_ENV === 'development') { /** * 關(guān)閉host check,方便使用ngrok之類的內(nèi)網(wǎng)轉(zhuǎn)發(fā)工具 */ myConfig.devServer = { disableHostCheck: true } } // open: true, // hot: true // // https: true, // // proxy: { // // '/proxy': { // // target: 'http://47.94.138.75', // // // changeOrigin: true, // // pathRewrite: { // // '^/proxy': '' // // } // // } // // }, // } return myConfig } }
最后去除 main.js
中引入的 import 'element-ui/lib/theme-chalk/index.css'
OK ,現(xiàn)在執(zhí)行一下 build
:
可以看到,相對(duì)于 793.20KB
, 61.94k
小了將近 13
倍?。。?/p>
把這個(gè)分支部署到服務(wù)器,話不多說(shuō),對(duì)比一下就好:
使用Gzip 加速
引入 compression-webpack-plugin : npm i -D compression-webpack-plugin
https://www.webpackjs.com/plugins/compression-webpack-plugin/
修改 vue.config.js
,老規(guī)矩,上最全的代碼:
const path = require('path') const CompressionWebpackPlugin = require('compression-webpack-plugin') function resolve(dir) { return path.join(__dirname, './', dir) } // cdn預(yù)加載使用 const externals = { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'axios': 'axios', 'element-ui': 'ELEMENT', 'js-cookie': 'Cookies', 'nprogress': 'NProgress' } const cdn = { // 開發(fā)環(huán)境 dev: { css: [ 'https://unpkg.com/element-ui/lib/theme-chalk/index.css', 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css' ], js: [] }, // 生產(chǎn)環(huán)境 build: { css: [ 'https://unpkg.com/element-ui/lib/theme-chalk/index.css', 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css' ], js: [ 'https://cdn.bootcss.com/vue/2.5.21/vue.min.js', 'https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js', 'https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js', 'https://cdn.bootcss.com/axios/0.18.0/axios.min.js', 'https://unpkg.com/element-ui/lib/index.js', 'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js', 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js' ] } } // 是否使用gzip const productionGzip = true // 需要gzip壓縮的文件后綴 const productionGzipExtensions = ['js', 'css'] module.exports = { chainWebpack: config => { // 這里是對(duì)環(huán)境的配置,不同環(huán)境對(duì)應(yīng)不同的BASE_API,以便axios的請(qǐng)求地址不同 config.plugin('define').tap(args => { const argv = process.argv const mode = argv[argv.indexOf('--project-mode') + 1] args[0]['process.env'].MODE = `"${mode}"` args[0]['process.env'].BASE_API = '"http://47.94.138.75:8000"' return args }) /** * 添加CDN參數(shù)到htmlWebpackPlugin配置中, 詳見public/index.html 修改 */ 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 }) // svg loader const svgRule = config.module.rule('svg') // 找到svg-loader svgRule.uses.clear() // 清除已有的loader, 如果不這樣做會(huì)添加在此loader之后 svgRule.exclude.add(/node_modules/) // 正則匹配排除node_modules目錄 svgRule // 添加svg新的loader處理 .test(/\.svg$/) .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) // 修改images loader 添加svg處理 const imagesRule = config.module.rule('images') imagesRule.exclude.add(resolve('src/icons')) config.module .rule('images') .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/) }, // 修改webpack config, 使其不打包externals下的資源 configureWebpack: config => { const myConfig = {} if (process.env.NODE_ENV === 'production') { // 1. 生產(chǎn)環(huán)境npm包轉(zhuǎn)CDN myConfig.externals = externals myConfig.plugins = [] // 2. 構(gòu)建時(shí)開啟gzip,降低服務(wù)器壓縮對(duì)CPU資源的占用,服務(wù)器也要相應(yīng)開啟gzip productionGzip && myConfig.plugins.push( new CompressionWebpackPlugin({ test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 8192, minRatio: 0.8 }) ) } if (process.env.NODE_ENV === 'development') { /** * 關(guān)閉host check,方便使用ngrok之類的內(nèi)網(wǎng)轉(zhuǎn)發(fā)工具 */ myConfig.devServer = { disableHostCheck: true } } // open: true, // hot: true // // https: true, // // proxy: { // // '/proxy': { // // target: 'http://47.94.138.75', // // // changeOrigin: true, // // pathRewrite: { // // '^/proxy': '' // // } // // } // // }, // } return myConfig } }
再次運(yùn)行 build
,我們會(huì)發(fā)現(xiàn) dist/
下所有的 .js
和 .css
都會(huì)多出一個(gè) .js.gz、.css.gz
的文件,這就是我們需要的壓縮文件,可以看到最大的只有 18.05KB
,想想是不是比較激動(dòng)...
當(dāng)然,這玩意還需要服務(wù)端支持,也就是配置 nginx
:
gzip on; gzip_static on; gzip_min_length 1024; gzip_buffers 4 16k; gzip_comp_level 2; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; gzip_vary off; gzip_disable "MSIE [1-6]\.";
配置完重啟 nginx
:
配置成功的話,可以看到加載的是比較小的 Gzip
:
在 response headers
里會(huì)有一個(gè) Content-Encoding:gzip
感謝各位的閱讀!關(guān)于“vue-cli3從搭建到優(yōu)化的案例”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。