一份關於Vue-Cli5常用配置開發模板,可用作於PC網站開發、移動端網頁,後臺管理系統,開箱即用

vipbic發表於2023-02-23

Vue-cli5

Vue CLI 是一個基於 Vue.js 進行快速開發的完整系統,提供:

  • 透過 @vue/cli 實現的互動式的專案腳手架。
  • 透過 @vue/cli + @vue/cli-service-global 實現的零配置原型開發。
  • 一套完全圖形化的建立和管理 Vue.js 專案的使用者介面

安裝依賴

npm install 

如果本地網路卡頓,使用臨時映象,當命令列視窗關閉即失效

npm --registry http://mirrors.cloud.tencent.com/npm/ install express

開發模式

npm run dev 
or
npm run serve

打包模式

npm run build

自動上傳

需要在gulpfile.js配置伺服器資訊

npm run upload

專案配置功能

  • ✅開啟檔案Gzip壓縮
  • ✅編譯去掉註釋
  • ✅開發服務配置
  • ✅編輯器別名設定
  • ✅配置環境變數
  • ✅多頁面應用配置
  • ✅請求路由動態新增
  • ✅網路請求封裝
  • ✅網路異常重連
  • ✅配置全域性less
  • ✅開啟分析打包日誌
  • ✅打包進度
  • ✅全域性元件通訊
  • ✅注入全域性變數
  • ✅打包CDN替換NPM包
  • ✅複製檔案
  • ✅新增可選鏈運運算元
  • ✅抽離重複檔案合併
  • ✅配置px轉換rem
  • ✅動態修改主題
  • ✅自動上傳伺服器
  • ✅Nginx配置
  • ✅全域性事件通訊

完整配置

Vue-cli5常用配置開發模板

開啟檔案Gzip壓縮

config.plugin('CompressionPlugin')
    .use('compression-webpack-plugin', [{
        filename: '[path][base].gz',
        algorithm: 'gzip',
        test: /\.js$|\.css$|\.html$/,
        threshold: 10240, // 只處理比這個值大的資源。按位元組計算
        minRatio: 0.8 // 只有壓縮率比這個值小的資源才會被處理
    }])

編譯去掉註釋

config.optimization.minimizer[TerserPluginIndex] = new TerserPlugin({
    terserOptions: {
        warnings: false,
        format: {
            comments: false,
        },
        compress: {
            drop_debugger: true, // 註釋console
            drop_console: true,
            pure_funcs: ['console.log'], // 移除console
        },
    },
    extractComments: false, // 是否將註釋提取到一個單獨的檔案中
    parallel: true, // 是否並⾏打包
});

開發服務配置

module.exports = {
    devServer: {
        open: false, // 自動啟動瀏覽器
        host: "0.0.0.0",
        port: 9007, // 埠號
        proxy: {
            "/api": {
                target: "https://www.api.com", // 目標代理介面地址
                pathRewrite: {
                    "^/api": "/"
                }
            }
        },
        hot: true,// 熱更新
        headers: {
            'Access-Control-Allow-Origin': '*', // 微前端應用除錯
        },
    }
}

編輯器別名設定

放置在根目錄下,檔名為jsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "esnext",
        "baseUrl": "./",
        "moduleResolution": "node",
        "paths": {
            "@/*": [
                "src/*"
            ],
            "__ROOT__/*": [
                "*"
            ]
        },
        "lib": [
            "esnext",
            "dom",
            "dom.iterable",
            "scripthost"
        ]
    }
}

配置環境變數

放置在根目錄下,.env.development.env.production.env.test,等等模式檔案

命令切換

vue-cli-service build --mode development
vue-cli-service build --mode production
vue-cli-service build --mode test

配置環境檔案

.env                # 在所有的環境中被載入
.env.local          # 在所有的環境中被載入,但會被 git 忽略
.env.[mode]         # 只在指定的模式中被載入
.env.[mode].local   # 只在指定的模式中被載入,但會被 git 忽略

多頁面應用配置

module.exports = {
    pages: {
        index: {
            // page 的入口
            entry: 'src/index/main.js',
            // 模板來源
            template: 'public/index.html',
            // 在 dist/index.html 的輸出
            filename: 'index.html',
            // 當使用 title 選項時,
            // template 中的 title 標籤需要是 <title><%= htmlWebpackPlugin.options.title %></title>
            title: 'Index Page',
            // 在這個頁面中包含的塊,預設情況下會包含
            // 提取出來的通用 chunk 和 vendor chunk。
            chunks: ['chunk-vendors', 'chunk-common', 'index']
        },
        // 當使用只有入口的字串格式時,
        // 模板會被推導為 `public/subpage.html`
        // 並且如果找不到的話,就回退到 `public/index.html`。
        // 輸出檔名會被推導為 `subpage.html`。
        subpage: 'src/subpage/main.js'
    }
}

網路請求封裝

檔案放置http/request.js
  • 基於axios封裝
  • 網路請求攔擊
  • 網路響應攔截
  • 封裝常用post、get、upload、download、併發請求
const http = axios.create({
    timeout: 1000 * 60,
    withCredentials: true, // 表示跨域請求時是否需要  使用憑證
    headers: {
        "Content-Type": "application/json",
    }
});

網路異常重連

基於axios發生異常重連
config.reconnectCount = config.reconnectCount || 1;
if (config.reconnectCount >= 3) { // 檢查重試次數是否達到最大值
    return Promise.reject(error)
}
const backoff = new Promise(function (resolve) {  // 建立新的Promise來處理
    setTimeout(function () {
        resolve()
    }, 2000)
})
config.reconnectCount += 1  // 增加重試次數
return backoff.then(function () {  // 返回promise,其中呼叫axios來重試請求
    return http(config)
})

配置全域性less

module.exports = {
    css: {
        loaderOptions: {
            less: {
                lessOptions: {
                    javascriptEnabled: true,
                    modifyVars: {}, // 這裡也闊以宣告less變數
                },
                additionalData: ` @import "~@/assets/css/variables.less";`,
            },
        }
    },
}

開啟分析打包日誌

npm i webpack-bundle-analyzer -D
const WebpackBundleanAlyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
plugins.push(new WebpackBundleanAlyzer({analyzerPort: 9601}))

打包進度

npm i webpackbar -D
const WebpackBar = require('webpackbar');
plugins.push(new WebpackBar({name: 'PC', color: '#07c160'}))

全域性元件通訊

npm i mitt -S
import mitt from 'mitt'

app.provide('$mitt', mitt())

注入全域性變數

new webpack.DefinePlugin({
    __APP__: JSON.stringify({
        lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
    })
})
// 在Vue單頁面中
console.log(lastBuildTime) // 2023-02-23 20:22:48

打包CDN替換NPM包

使用vue inspect --plugins檢視html是否在結果陣列中
// 見多頁面應用
Object.keys(pages).forEach(key => {
    config.plugin(`html-${key}`).tap(args => {
        args[0].cdn = isBuild ? cdn.build : cdn.dev;
        return args;
    });
})
// 單頁面應用
config.plugin(`html`).tap(args => {
    args[0].cdn = isBuild ? cdn.build : cdn.dev;
    return args;
});
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>vue-cli5模板</title>
    <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
    <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"/>
    <% } %>
</head>
<body>
<noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
        Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script type="text/javascript" src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
</body>
</html>

複製檔案

npm i copy-webpack-plugin -D
const CopyWebpackPlugin = require('copy-webpack-plugin')
plugins.push(new CopyWebpackPlugin({
    patterns: [
        {from: resolve('./README.md'), to: resolve('./dist')}
    ],
    options: {concurrency: 100}, // 併發數
}))

新增可選鏈運運算元

npm i @babel/plugin-proposal-optional-chaining -D
module.exports = {
    presets: [
        '@vue/cli-plugin-babel/preset'
    ],
    plugins: [
        "@babel/plugin-proposal-optional-chaining" // 新增該外掛
    ]
}

抽離重複檔案合併

config.optimization.splitChunks({
    cacheGroups: {
        styles: {
            name: 'styles',
            test: /\.(s?css|less|sass)$/,
            chunks: 'all',
            priority: 10
        },
        common: {
            name: 'chunk-common',
            chunks: 'all',
            minChunks: 2, // 拆分前必須共享模組的最小 chunks 數。
            maxInitialRequests: 5, // 打包後的入口檔案載入時,還能同時載入js檔案的數量(包括入口檔案)
            minSize: 0, // 生成 chunk 的最小體積
            priority: 1, // 最佳化將優先考慮具有更高 priority(優先順序)的快取組
            reuseExistingChunk: true // 如果當前 chunk 包含已從主 bundle 中拆分出的模組,則它將被重用,而不是生成新的模組
        },
        vendors: {
            name: 'chunk-vendors',
            test: /[\\/]node_modules[\\/]/,
            chunks: 'all',
            priority: 2,
            reuseExistingChunk: true
        },
    }
})

配置px轉換rem

npm i postcss-pxtorem -D
npm i lib-flexible -S
在入口檔案引入
import 'lib-flexible/flexible'
在根目錄新建.postcssrc.js檔案
module.exports = {
    plugins: {
        'postcss-pxtorem': {
            rootValue: 37.5, //換算基數,
            unitPrecision: 3, //允許REM單位增長到的十進位制數字,小數點後保留的位數。
            propList: ['*'],
            exclude: /(node_module)/,  //預設false,可以(reg)利用正規表示式排除某些資料夾的方法,例如/(node_module)/ 。如果想把前端UI框架內的px也轉換成rem,請把此屬性設為預設值
            selectorBlackList: ['.van'], //要忽略並保留為px的選擇器,本專案我是用的vant ui框架,所以忽略他
            mediaQuery: false,  //(布林值)允許在媒體查詢中轉換px。
            minPixelValue: 1 //設定要替換的最小畫素值
        }
    }
}

動態修改主題


<template>
    <a-config-provider>
        <router-view></router-view>
    </a-config-provider>
</template>
<script setup>
import {ConfigProvider} from 'ant-design-vue';

ConfigProvider.config({
    theme: {
        primaryColor: '#25b864',
    },
});
</script>

自動上傳伺服器

執行命令
npm run upload
配置自己的伺服器賬號和密碼
const gulp = require("gulp")
const ftp = require("gulp-ftp");

//伺服器配置資訊
const serverSeting = {
    host: "伺服器域名",
    port: 21, //虛擬主機預設21,伺服器預設22
    user: "使用者名稱",
    pass: "密碼",
    remotePath: "/dist/"
};

//把打包好的檔案上傳到伺服器
gulp.task("server", () => {
    // 遠端目錄
    return gulp.src("/home/usr/www/**/*").pipe(ftp(serverSeting));
});

gulp.task('upload', gulp.series('server'))

Nginx配置

nginx常用的操作命令
#修改配置reload後看服務啟動是否正常
nginx -t;
#過載nginx
nginx reload
#啟動 nginx
start nginx      
#重啟 nginx 
nginx -s reload   
#快速停止 nginx
nginx -s stop     
#完整有序地停止 nginx
nginx -s quit      
這裡列舉一份比較常用的nginx配置,具體的實際,需要看具體
server {
    listen       9999; # 監聽埠
    server_name  localhost; # 域名可以有多個,用空格隔開
    
    location / {
      root   C:\工作\project\client_admin_system\dist;     #站點根目錄,即網頁檔案存放的根目錄, 預設主頁目錄在nginx安裝目錄的html子目錄。
      index  index.html index.htm;    #目錄內的預設開啟檔案,如果沒有匹配到index.html,則搜尋index.htm,依次類推
    }
    
    # 反向代理
    location /api {
        rewrite  ^.+api/?(.*)$ /$1 break;
        proxy_pass  http://192.168.1.100:7001;    #node api server 即需要代理的IP地址
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    #error_page  404              /404.html;    #對錯誤頁面404.html 做了定向配置
    
    # redirect server error pages to the static page /50x.html
    #將伺服器錯誤頁面重定向到靜態頁面/50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   html;
    }
}

UI元件

Ant-Design-Vue

修改css變數

document.documentElement.style.setProperty('--primary-color', 'red');

如果使用Vue-cli3搭建的專案請看
一份完整的Vue-cli3專案基礎配置項

如果使用Vite搭建的專案請看
一份完整的Vite3專案基礎配置項

相關文章