国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

vue-cli3 從搭建到優(yōu)化的詳細(xì)步驟

來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:01:43
文檔

vue-cli3 從搭建到優(yōu)化的詳細(xì)步驟

vue-cli3 從搭建到優(yōu)化的詳細(xì)步驟:前言 github地址: https://github.com/LeeStaySmall/vue-project-demo (完整分支:optimize分支) demo地址: vue-project-demo.eloco.cn 安裝與初始化架構(gòu) 安裝 node >= 8.9 推薦:8.11.0 + 安裝: npm install
推薦度:
導(dǎo)讀vue-cli3 從搭建到優(yōu)化的詳細(xì)步驟:前言 github地址: https://github.com/LeeStaySmall/vue-project-demo (完整分支:optimize分支) demo地址: vue-project-demo.eloco.cn 安裝與初始化架構(gòu) 安裝 node >= 8.9 推薦:8.11.0 + 安裝: npm install

前言

github地址: https://github.com/LeeStaySmall/vue-project-demo (完整分支:optimize分支)

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)庫iconFont

axios封裝api、模塊化vuex

axios篇

項(xiàng)目中安裝 axiosnpm install axios ;

src 目錄下創(chuàng)建 utils/ , 并創(chuàng)建 request.js 用來封裝 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 目錄,用來統(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 框架為例,來深入理解一下這個(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 作為倉庫文件。但在更多實(shí)際場(chǎng)景中,如果引入 vuex ,那么肯定避免不了分模塊,先來看一下默認(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 可以用來存儲(chǔ)應(yīng)用的狀態(tài),比如接下來要講到的全局 loading ,或者控制第三方組件的全局大小,比如 element ui 中的全局組件 size

user module 可以用來存儲(chǔ)當(dāng)前用戶的信息;

當(dāng)然,store 配合本地存儲(chǔ)比較完美,這里采用 js-cookie 。

全局loading、合理利用vue router守衛(wèi)

全局loading

上面說完了 axios、vuex ,現(xiàn)在結(jié)合之前說一下設(shè)置全局 loading 效果。

平常寫代碼每個(gè)請(qǐng)求之前一般都需要設(shè)置 loading ,成功之后結(jié)束 loading 效果,這就迫使我們不得不寫大量重復(fù)代碼,如果不想這樣做,可以結(jié)合 axiosvuex 統(tǒng)一做了。

首先,在說 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

再來修改一下 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)目里出了初始化包括 axiosvuex 、 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)一 installvue 實(shí)例上,并通過 Vue.use() 使用;
  • 對(duì)于一些全局的過濾器,你仍可以放到 utils/filters.js 里,使用 Vue.fileter() 注冊(cè)到全局;
  • 對(duì)于一些全局方法,又不是很長(zhǎng)用到的,可以放到 utils/index.js ,哪里使用哪里 import
  • mixin減少項(xiàng)目冗余代碼

    直接看代碼吧,要寫奔潰了....

    使用cdn減少文件打包的體積

    到此時(shí),看我項(xiàng)目里都用了什么:

    主要就是這些,那么執(zhí)行一下打包命令呢?

    可能這時(shí)候你還覺得沒什么, 單文件最多的還沒超過 800kb 呢...

    我把項(xiàng)目通過 jenkins 部署到服務(wù)器上,看一下訪問:

    可以看到, chunk-vendors 加載了將近12秒,這還是只有框架沒有內(nèi)容的前提下,當(dāng)然你可能說你項(xiàng)目中用不到 vuex 、用不到 js-cookie ,但是隨著項(xiàng)目的迭代維護(hù),最后肯定不比現(xiàn)在小。

    那么,有些文件在生產(chǎn)環(huán)境是不是可以嘗試使用 cdn 呢?

    為了方便對(duì)比,這里保持原代碼不動(dòng)( master 分支),再切出來一個(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 倍!!!

    把這個(gè)分支部署到服務(wù)器,話不多說,對(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

    聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    vue-cli3 從搭建到優(yōu)化的詳細(xì)步驟

    vue-cli3 從搭建到優(yōu)化的詳細(xì)步驟:前言 github地址: https://github.com/LeeStaySmall/vue-project-demo (完整分支:optimize分支) demo地址: vue-project-demo.eloco.cn 安裝與初始化架構(gòu) 安裝 node >= 8.9 推薦:8.11.0 + 安裝: npm install
    推薦度:
    標(biāo)簽: VUE 詳細(xì)的 搭建
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 色精品一区二区三区 | 久久免费国产精品一区二区 | 国产精品一区二区三区四区五区 | 亚洲精品高清在线观看 | 欧美日韩亚洲综合 | 午夜影院欧美 | 国产精品观看 | 日韩一区二区三区视频 | 国产中文字幕在线观看 | 日本黄一级日本黄二级 | 国产精品一区在线观看 | 国产精品欧美一区二区三区不卡 | 在线播放一区 | 国产区免费 | 亚洲国产精品成人综合久久久 | 在线啊v | 亚洲欧美日韩激情在线观看 | 韩国美女vip福利一区 | 免费在线观看一区二区 | 亚洲国产日韩欧美在线as乱码 | 日韩欧美视频一区二区三区 | 成人精品第一区二区三区 | 亚洲精品高清国产一久久 | 高清国产精品久久 | 久久精品一区二区影院 | 岛国一区二区 | 日本黄一级日本黄二级 | 久久久国产一区二区三区 | 亚洲色图欧美一区 | 黑丝草逼 | 日韩综合第一页 | 精品一区二区三区四区五区 | 国偷自产一区二区免费视频 | 亚洲国产精品一区二区三区 | 国产成人亚洲精品影院 | 欧美午夜视频在线观看 | 亚洲欧美色视频 | 国产va免费精品 | 亚洲欧美一区二区三区九九九 | 国产精品123区 | 91精品国产高清久久久久久91 |