<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題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關鍵字專題關鍵字專題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
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        vue-cli3 從搭建到優化的詳細步驟

        來源:懂視網 責編:小采 時間:2020-11-27 22:01:43
        文檔

        vue-cli3 從搭建到優化的詳細步驟

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

        前言

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

        demo地址: vue-project-demo.eloco.cn

        安裝與初始化架構

        安裝

        node >= 8.9 推薦:8.11.0 +

        安裝: npm install -g @vue/cli

        檢查: vue --version

        如果已安裝舊版本,需要先 npm uninstall vue-cli -g 卸載掉舊版本。

        初始化架構

        創建: vue create project-name

        注:項目名稱不能駝峰命名。

        選擇一個預設(這里我選擇更多功能):

        選擇需要安裝的(Babel、Router、Vuex、Pre-processors、Linter / Formatter):

        是否使用history路由模式(Yes):

        選擇css 預處理器(Sass/SCSS):

        選擇eslint 配置(ESLint + Standard config):

        選擇什么時候執行eslint校驗(Lint on save):

        選擇以什么樣的形式配置以上所選的功能(In dedicated config files):

        是否將之前的設置保存為一個預設模板(y):

        如果選擇 y 會讓輸入名稱,以便下次直接使用,否則直接開始初始化項目。

        最后,看一下生成的基本架構目錄:

        在項目中優雅的使用svg 首先在 /src/components 創建 SvgIcon.vue

        src/ 下創建 icons 文件夾,以及在其下創建 svg 文件夾用于存放svg文件,創建 index.js 作為入口文件:

        編寫index.js 的腳本:

        import Vue from 'vue'
        import SvgIcon from '@/components/SvgIcon.vue' // svg組件
        
        // 全局注冊
        Vue.component('svg-icon', SvgIcon)
        
        const requireAll = requireContext => requireContext.keys().map(requireContext)
        const req = require.context('./svg', false, /\.svg$/)
        requireAll(req)

        使用 svg-sprite-loader 對項目中使用的 svg 進行處理:

        npm install svg-sprite-loader --save-dev

        修改默認的 webpack 配置, 在項目根目錄創建 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, 如果不這樣做會添加在此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 ,個人比較建議使用阿里開源的圖標庫iconFont

        axios封裝api、模塊化vuex

        axios篇

        項目中安裝 axiosnpm install axios

        src 目錄下創建 utils/ , 并創建 request.js 用來封裝 axios ,上代碼:

        import axios from 'axios'
        
        // 創建axios 實例
        const service = axios.create({
         baseURL: process.env.BASE_API, // api的base_url
         timeout: 10000 // 請求超時時間
        })
        
        // request 攔截器
        service.interceptors.request.use(
         config => {
         // 這里可以自定義一些config 配置
        
         return config
         },
         error => {
         // 這里處理一些請求出錯的情況
        
         console.log(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

        既然要使用 axios ,必不可少的需要配置環境變量以及需要請求的地址,這里可以簡單的修改 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"
         },

        同時修改vue.config.js:

        const path = require('path')
        
        function resolve(dir) {
         return path.join(__dirname, './', dir)
        }
        
        module.exports = {
         chainWebpack: config => {
         // 這里是對環境的配置,不同環境對應不同的BASE_API,以便axios的請求地址不同
         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, 如果不這樣做會添加在此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/ 下創建 api 目錄,用來統一管理所有的請求,比如下面這樣: ‘'

        這樣的好處是方便管理、后期維護,還可以和后端的微服務對應,建立多文件存放不同模塊的 api 。剩下的就是你使用到哪個api時,自己引入便可。

        拓展:服務端的cors設置

        牽涉到跨域,這里采用 cors ,很多朋友在面試中經常會被問到cors的實現原理,這個網上有很多理論大多是這樣講的:

        其實,這樣理解很抽象,服務器端到底是怎么做驗證的?

        這里大家可以通俗的理解為后端在接收前端的 request 請求的時候,會有一個 request 攔截器,像 axios response 攔截器一樣。下面以 php lumen 框架為例,來深入理解一下這個流程:

        <?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)
         {
         //請求參數
         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',//允許客戶端發送cookie
         'Access-Control-Allow-Origin' => $Origin,
         //'Access-Control-Max-Age' => 120, //該字段可選,間隔2分鐘驗證一次是否允許跨域。
         ];
         //獲取請求方式
         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);
         //返回參數
         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 篇

        如果創建項目的時候,選擇了 vuex ,那么默認會在 src 目錄下有一個 store.js 作為倉庫文件。但在更多實際場景中,如果引入 vuex ,那么肯定避免不了分模塊,先來看一下默認文件代碼:

        import Vue from 'vue'
        import Vuex from 'vuex'
        
        Vue.use(Vuex)
        
        export default new Vuex.Store({
         state: {
        
         },
         mutations: {
        
         },
         actions: {
        
         }
        })

        那么現在改造一下,比如先劃分出 appuser 兩個模塊,可以這樣:

        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/ 下創建 store/ 目錄:

        app module 可以用來存儲應用的狀態,比如接下來要講到的全局 loading ,或者控制第三方組件的全局大小,比如 element ui 中的全局組件 size

        user module 可以用來存儲當前用戶的信息;

        當然,store 配合本地存儲比較完美,這里采用 js-cookie

        全局loading、合理利用vue router守衛

        全局loading

        上面說完了 axios、vuex ,現在結合之前說一下設置全局 loading 效果。

        平常寫代碼每個請求之前一般都需要設置 loading ,成功之后結束 loading 效果,這就迫使我們不得不寫大量重復代碼,如果不想這樣做,可以結合 axiosvuex 統一做了。

        首先,在說 vuex 的時候,我在 src/ 下創建了一個 store ,現在就在 store/modules/app.js 寫這個 Loading 效果的代碼;

        const app = {
         state: {
         requestLoading: 0
         },
         mutations: {
         SET_LOADING: (state, status) => {
         // error 的時候直接重置
         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'
        
        // 創建axios 實例
        const service = axios.create({
         baseURL: process.env.BASE_API, // api的base_url
         timeout: 10000 // 請求超時時間
        })
        
        // request 攔截器
        service.interceptors.request.use(
         config => {
         // 這里可以自定義一些config 配置
        
         // loading + 1
         store.dispatch('SetLoading', true)
        
         return config
         },
         error => {
         // 這里處理一些請求出錯的情況
        
         // 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 正常放回時的邏輯
        
         // loading - 1
         store.dispatch('SetLoading', false)
        
         return res
         },
         error => {
         // 這里處理一些response 出錯時的邏輯
        
         // loading - 1
         store.dispatch('SetLoading', false)
        
         return Promise.reject(error)
         }
        )
        
        export default service

        其次,在 src/components/ 下創建 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 中引入即可。

        附: 為了方便演示,項目里出了初始化包括 axiosvuexvue-router , 項目使用了 js-cookieelement-ui 等,此步驟之后,會改造一下 app.vue

        vue router守衛

        vue-router 提供了非常方便的鉤子,可以讓我們在做路由跳轉的時候做一些操作,比如常見的權限驗證。

        首先,需要在 src/utils/ 下創建 auth.js ,用于存儲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/ 下創建 permission.js :

        import router from '@/router'
        import store from '@/store'
        import {
         getToken
        } from './auth'
        import NProgress from 'nprogress' // 進度條
        import 'nprogress/nprogress.css' // 進度條樣式
        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 { // 實時拉取用戶的信息
         store.dispatch('GetUserInfo').then(res => {
         next()
         }).catch(err => {
         store.dispatch('FedLogOut').then(() => {
         Message.error('拉取用戶信息失敗,請重新登錄!' + err)
         next({
         path: '/'
         })
         })
         })
         }
         } else {
         if (whiteList.includes(to.path)) {
         next()
         } else {
         next('/login')
         NProgress.done()
         }
         }
        })
        
        router.afterEach(() => {
         NProgress.done() // 結束Progress
        })

        Nginx try_files 以及 404

        nginx 配置如下:

        location / {
         root /www/vue-project-demo/;
         try_files $uri $uri/ /index.html index.htm;
        }

        try_files : 可以理解為nginx 不處理你的這些url地址請求; 那么服務器如果不處理了,前端要自己做一些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' }
         ]
        })

        然后寫一個404 的view 就ok 。

        常用的utils

        到現在為止, utils/ 目錄下應該有 auth.js 、permission.js、request.js

      1. 那么對與一些常用的方法,你可以放到 utils/common.js 里,統一 installvue 實例上,并通過 Vue.use() 使用;
      2. 對于一些全局的過濾器,你仍可以放到 utils/filters.js 里,使用 Vue.fileter() 注冊到全局;
      3. 對于一些全局方法,又不是很長用到的,可以放到 utils/index.js ,哪里使用哪里 import
      4. mixin減少項目冗余代碼

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

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

        到此時,看我項目里都用了什么:

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

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

        我把項目通過 jenkins 部署到服務器上,看一下訪問:

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

        那么,有些文件在生產環境是不是可以嘗試使用 cdn 呢?

        為了方便對比,這里保持原代碼不動( master 分支),再切出來一個分支改動優化( optimize 分支), 上代碼:

        // vue.config.js 修改
        const path = require('path')
        
        function resolve(dir) {
         return path.join(__dirname, './', dir)
        }
        
        // cdn預加載使用
        const externals = {
         'vue': 'Vue',
         'vue-router': 'VueRouter',
         'vuex': 'Vuex',
         'axios': 'axios',
         'element-ui': 'ELEMENT',
         'js-cookie': 'Cookies',
         'nprogress': 'NProgress'
        }
        
        const cdn = {
         // 開發環境
         dev: {
         css: [
         'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
         'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
         ],
         js: []
         },
         // 生產環境
         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 => {
         // 這里是對環境的配置,不同環境對應不同的BASE_API,以便axios的請求地址不同
         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參數到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, 如果不這樣做會添加在此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. 生產環境npm包轉CDN
         myConfig.externals = externals
         }
         if (process.env.NODE_ENV === 'development') {
         /**
         * 關閉host check,方便使用ngrok之類的內網轉發工具
         */
         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 ,現在執行一下 build

        可以看到,相對于 793.20KB61.94k 小了將近 13 倍!!!

        把這個分支部署到服務器,話不多說,對比一下就好:

        使用Gzip 加速

        引入 compression-webpack-plugin : npm i -D compression-webpack-plugin https://www.webpackjs.com/plugins/compression-webpack-plugin/

        修改 vue.config.js ,老規矩,上最全的代碼:

        const path = require('path')
        const CompressionWebpackPlugin = require('compression-webpack-plugin')
        
        function resolve(dir) {
         return path.join(__dirname, './', dir)
        }
        
        // cdn預加載使用
        const externals = {
         'vue': 'Vue',
         'vue-router': 'VueRouter',
         'vuex': 'Vuex',
         'axios': 'axios',
         'element-ui': 'ELEMENT',
         'js-cookie': 'Cookies',
         'nprogress': 'NProgress'
        }
        
        const cdn = {
         // 開發環境
         dev: {
         css: [
         'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
         'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
         ],
         js: []
         },
         // 生產環境
         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 => {
         // 這里是對環境的配置,不同環境對應不同的BASE_API,以便axios的請求地址不同
         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參數到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, 如果不這樣做會添加在此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. 生產環境npm包轉CDN
         myConfig.externals = externals
        
         myConfig.plugins = []
         // 2. 構建時開啟gzip,降低服務器壓縮對CPU資源的占用,服務器也要相應開啟gzip
         productionGzip && myConfig.plugins.push(
         new CompressionWebpackPlugin({
         test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
         threshold: 8192,
         minRatio: 0.8
         })
         )
         }
         if (process.env.NODE_ENV === 'development') {
         /**
         * 關閉host check,方便使用ngrok之類的內網轉發工具
         */
         myConfig.devServer = {
         disableHostCheck: true
         }
         }
         // open: true,
         // hot: true
         // // https: true,
         // // proxy: {
         // // '/proxy': {
         // // target: 'http://47.94.138.75',
         // // // changeOrigin: true,
         // // pathRewrite: {
         // // '^/proxy': ''
         // // }
         // // }
         // // },
         // }
         return myConfig
         }
        }

        再次運行 build ,我們會發現 dist/ 下所有的 .js.css 都會多出一個 .js.gz、.css.gz 的文件,這就是我們需要的壓縮文件,可以看到最大的只有 18.05KB ,想想是不是比較激動...

        當然,這玩意還需要服務端支持,也就是配置 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 里會有一個 Content-Encoding:gzip

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        vue-cli3 從搭建到優化的詳細步驟

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

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 一级黄色片免费观看| 亚洲 欧洲 视频 伦小说| 免费乱理伦在线播放| 全亚洲最新黄色特级网站 | 成年网在线观看免费观看网址| 成人精品视频99在线观看免费| 国产免费久久久久久无码| 最近最新高清免费中文字幕| 久久精品a一国产成人免费网站| 国产黄色片在线免费观看| 中文字幕在线亚洲精品| 亚洲国产午夜精品理论片| 亚洲国产精品ⅴa在线观看| 一二三区免费视频| 成人午夜亚洲精品无码网站| 日批视频网址免费观看| 成人无遮挡毛片免费看| 久久精品国产99精品国产亚洲性色| 亚洲成a人片77777群色| eeuss影院www天堂免费| 成人性生免费视频| 亚洲国产成人无码AV在线| 亚洲人成无码久久电影网站| 亚洲精品国产手机| 国产又黄又爽胸又大免费视频| 亚洲日韩在线观看| 久久伊人免费视频| 亚洲男人第一无码aⅴ网站| 亚洲精品无AMM毛片| 亚洲成a人片在线观看久| 亚洲乱码无人区卡1卡2卡3| 在线视频免费观看爽爽爽| 亚洲区小说区激情区图片区| 日本中文字幕免费看| 最近免费中文字幕4| 污污视频免费观看网站| 亚洲AV午夜福利精品一区二区| 成年网站免费视频A在线双飞| 亚洲精品中文字幕乱码影院| 天堂在线免费观看中文版| 亚洲人成电影网站色www|