一、環境變量配置
官網https://cn.vitejs.dev/guide/env-and-mode.html#intellisense
1. 新建.env
開頭的文件在根目錄
為了防止意外地將一些環境變量泄漏到客戶端,只有以 VITE_
為前綴的變量才會暴露給經過 vite
處理的代碼
.env
所有環境默認加載
.env.development
開發模式默認加載
.env.production
生產模式默認加載
.env.check
自定義環境文件
示例:如.env
文件
# title
VITE_APP_TITLE = vue-guide-project
a. 模式
默認情況下,開發服務器 (dev
命令) 運行在 development
(開發) 模式,而 build
命令則運行在 production
(生產) 模式。
這意味著當執行 vite build
時,它會自動加載 .env.production
中可能存在的環境變量。
在某些情況下,若想在 vite build
時運行不同的模式來渲染不同的標題,可以通過傳遞 --mode
選項標志來覆蓋命令使用的默認模式。例如,如果你想在 staging
(預發布)模式下構建應用:
vite build --mode staging# package.json
{# ..."type": "module","scripts": {"dev": "vite","build": "vite build --mode staging",},
}
還需要新建一個 .env.staging
文件:
# .env.staging
VITE_APP_TITLE = My App (staging)
b. 簡單了解下NODE_ENV
和模式Mode
NODE_ENV
:
定義:技術上講,NODE_ENV
是一個由Node.js
暴露給執行腳本的系統環境變量。
作用:通常用于確定服務器工具、構建腳本和客戶端library
在開發環境(development
)還是生產環境(production
)下的行為。它的值通常為"production
"或"development
",用于區分不同環境下的邏輯行為。- 模式(
Mode
):
定義:模式指項目運行或構建時的一種特定狀態或配置。
作用:在前端框架中,模式用于定義項目在不同階段(如開發、生產、測試)下的行為和配置。它可以包含多個環境變量,并通過特定的文件(如.env.production
、.env.development
等)來管理這些變量。
所以,我們所寫的.env
可以理解為創建的不同的模式變量
2. TypeScript
智能提示,設置全局類型定義
就是在編碼過程中應用這些自定義環境變量的時候,給出的智能提示。
src
目錄下創建一個vite-env.d.ts
或者env.d.ts
文件src
同級別types
目錄下創建文件env.d.ts
/// <reference types="vite/client" />interface ImportMetaEnv {readonly VITE_APP_TITLE: string// 更多環境變量...
}interface ImportMeta {readonly env: ImportMetaEnv
}interface ViteEnv extends ImportMetaEnv {}
- 在
tsconfig.app.json
文件中
專門用于處理項目
src
文件中的TypeScript
配置文件,
include
配置項加入文件:(會提示自定義設置的環境變量)
"include": [// ...// 第一種方式對應配置"vite-env.d.ts", // 或者 "env.d.ts" // 第二種方式對應配置"types/**.d.ts" // 或者直接 "types"
],
效果圖:
- 或者
compilerOptions
中加入types
:(只會提示默認環境變量)
{"compilerOptions": {// ..."types": ["vite/client"]}
}
效果圖:
3. 訪問環境變量
- 客戶端源碼(就是
src
文件)中訪問:import.meta.env.VITE_APP_TITLE
html
中訪問環境變量:%VITE_APP_TITLE%
,如果環境變量不存在,則會將被忽略而不被替換,- 在配置(
src
文件外)文件中訪問環境變量
Vite
默認是不加載.env
文件的,因為這些文件需要在執行完Vite
配置后才能確定加載哪一個,舉個例子,root
和envDir
選項會影響加載行為。不過當你的確需要時,你可以使用Vite
導出的loadEnv
函數來加載指定的.env
文件。
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ command, mode }) => {// command: "build" | "serve" // mode 當前模式// 根據當前工作目錄中的 `mode` 加載 .env 文件// 設置第三個參數為 '' 來加載所有環境變量,而不管是否有 `VITE_` 前綴。const env = loadEnv(mode, process.cwd(), '')return {// vite 配置define: {__APP_ENV__: JSON.stringify(env.APP_ENV),},}
})
輸出:console.log(env)
二、情景配置-根據不同模式使用不同插件
1. 新建build/getEnv.ts
文件處理環境文件變量
loadEnv()
獲取的環境變量env
從輸出的值可以看出,全是字符串,所以我們可以自定義方法去轉換變量類型
/* eslint-disable */
// Read all environment variable configuration files to process.env
export function wrapperEnv(envConf: any): ViteEnv {const ret: any = {}for (const envName of Object.keys(envConf)) {let realName = envConf[envName].replace(/\\n/g, '\n')realName = realName === 'true' ? true : realName === 'false' ? false : realNameif (envName === 'VITE_PORT') {realName = Number(realName)}if (envName === 'VITE_PROXY' && realName) {try {realName = JSON.parse(realName.replace(/'/g, '"'))} catch (error) {realName = ''}}ret[envName] = realName}return ret
}
2. build/plugins/index.ts
新建build/plugins
文件夾處理各種plugins
,將每一個plugin
配置單獨抽離
-
plugins
文件目錄
-
入口文件
build/plugins/index.ts
// 插件配置 入口文件index.ts
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { PluginOption } from 'vite'
import VueDevTools from 'vite-plugin-vue-devtools'import { Px2remPlugin } from './Px2rem' // rem
import { svgLoaderPlugin } from './SvgLoader' // SVG
import { UnocssPlugin } from './Unocss' // unocss
import { VisualizerPlugin } from './Visualizer' // 打包分析
import { ViteCompressionPlugin } from './ViteCompression' // 壓縮gzip
import { ViteImageOptimizerPlugin } from './ViteImageOptimizer' // 圖片壓縮
import { ViteRestartPlugin } from './ViteRestartPlugin' // 修改配置文件自動重啟export const usePlugins = (isBuild: boolean, viteEnv: ViteEnv) => {const { VITE_OPEN_VISUALIZER, VITE_OPEN_SVG_LOADER, VITE_OPEN_PX2REM, VITE_OPEN_COMPRESSION } =viteEnvconst plugins: PluginOption[] = [vue(), vueJsx()]plugins.push(UnocssPlugin())if (VITE_OPEN_PX2REM) plugins.push(Px2remPlugin())if (VITE_OPEN_SVG_LOADER) plugins.push(svgLoaderPlugin())// 開發模式下if (!isBuild) {plugins.push(VueDevTools())plugins.push(ViteRestartPlugin())}if (isBuild) {plugins.push(ViteImageOptimizerPlugin())// 壓縮gzipVITE_OPEN_COMPRESSION && plugins.push(ViteCompressionPlugin())// 打包分析VITE_OPEN_VISUALIZER && plugins.push(VisualizerPlugin())}return plugins
}
- 單個
plugin
示例:
4. tsconfig.node.json
專門用于
Node.js
環境中的TypeScript
配置文件,它定義了用于Node.js
應用程序的TypeScript
編譯器選項
tsconfig.node.json
文件中:
"include": [// ..."build/**/*.ts","types" // 全局類型
],
5. .eslintrc.cjs
中添加:
overrides: [{files: ['*.ts', '*.tsx', '*.vue'],rules: {// 解決 ts 全局類型定義后,eslint報錯的問題'no-undef': 'off'}}
],
// ...
'no-unused-expressions': 'off' // 關閉禁止使用表達式
3. vite.config.ts
中
import { usePlugins } from './build/plugins'
// ...
export default defineConfig(({ command, mode }) => {const isBuild = command === 'build'const root = process.cwd()const env = loadEnv(mode, root)const viteEnv = wrapperEnv(env)return {plugins: usePlugins(isBuild, viteEnv),// ...}
})
三、情景配置-server
和build
配置
build
文件夾中創建server.ts
和build.ts
文件
1. 將build
配置寫入build.ts
文件中
export const useBuild = () => {return {// 10kb以下,轉Base64assetsInlineLimit: 1024 * 10,// chunkSizeWarningLimit: 1500,//配置文件大小提醒限制,默認500rollupOptions: {output: {// 每個node_modules模塊分成一個js文件manualChunks(id: string) {if (id.includes('node_modules')) {return 'vendor'// return id.toString().split('node_modules/.pnpm/')[1].split('/')[0].toString()}return undefined},// 用于從入口點創建的塊的打包輸出格式[name]表示文件名,[hash]表示該文件內容hash值entryFileNames: 'assets/js/[name].[hash].js', // 用于命名代碼拆分時創建的共享塊的輸出命名chunkFileNames: 'assets/js/[name].[hash].js', // 用于輸出靜態資源的命名,[ext]表示文件擴展名assetFileNames: 'assets/[ext]/[name].[hash].[ext]'}}}
}
2. 將server
配置寫入server.ts
文件中
import type { ProxyOptions } from 'vite'type ProxyItem = [string, string]
type ProxyList = ProxyItem[]
type ProxyTargetList = Record<string, ProxyOptions>/*** 創建代理,用于解析 .env.development 代理配置*/
const userProxy = (proxyList: ProxyList = []) => {const ret: ProxyTargetList = {}proxyList.forEach((item) => {const [prefix, target] = itemconst httpsRE = /^https:\/\//const isHttps = httpsRE.test(target)ret[prefix] = {target,changeOrigin: true,ws: true,rewrite: (path: string) => path.replace(new RegExp(`^${prefix}`), ''),// https is require secure=false// Verify SSL certificate...(isHttps ? { secure: false } : {})}})return ret
}/*** server 配置* @returns*/
export const useServer = (viteEnv: ViteEnv) => {const { VITE_PORT, VITE_PROXY } = viteEnvreturn {// 監聽所有公共ip// host: '0.0.0.0',cors: true,port: VITE_PORT,proxy: userProxy(VITE_PROXY)}
}
3. 完整vite.config.ts
文件
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'import { useBuild } from './build/build'
import { wrapperEnv } from './build/getEnv'
import { usePlugins } from './build/plugins'
import { useServer } from './build/server'export default defineConfig(({ command, mode }) => {const isBuild = command === 'build'const root = process.cwd()const env = loadEnv(mode, root)const viteEnv = wrapperEnv(env)return {plugins: usePlugins(isBuild, viteEnv),server: useServer(viteEnv),build: useBuild(),resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},css: {preprocessorOptions: {scss: {additionalData: `@use "./src/styles/variables.scss" as *;@use "./src/styles/mixin.scss" as *;`,javascriptEnabled: true}}}}
})