Vite 系列 - 让项目拥有更高的定制化能力

业务背景

随着前端技术的快速发展,现在的前端项目不仅需要满足业务需求,还需要满足许多复杂的环境适配场景,例如:

  • 每个环境的接口请求地址是不同的;
  • 每个环境可能有不同的业务逻辑;
  • ...

这些都可以归纳为 环境变量 的注入或多环境适配问题,今天我们就来聊下如何优雅的 Vite 中解决此问题。

目标

  • 支持多环境适配
  • 支持构建产物与环境无关

如上图所示,在项目启动构建时,通过注入环境变量实现不同环境的差异性配置,构建产物也可通过脚本替换原有环境变量,以达到构建产物与环境无关的目标

多环境适配

环境变量加载

Vite 环境变量和模式

  • 通过 *.loacl 解决本地开发和线上环境变量不一致问题
  • 多环境可通过 mode 解决多环境适配问题
sh 复制代码
.env                # 所有情况下都会加载
.env.local          # 所有情况下都会加载,但会被 git 忽略
.env.[mode]         # 只在指定模式下加载
.env.[mode].local   # 只在指定模式下加载,但会被 git 忽略

加载优先级

  • 指定模式的文件(例如 .env.prod)会比通用形式的优先级更高(例如 .env)
  • Vite 执行时已经存在的环境变量有最高的优先级,不会被 .env 类文件覆盖

多模式文件配置

Vite通过多模式来配置不同启动场景下的特性环境变量,你可以创建自定义的模式文件,如下:

上面的示例项目创建了两种模式分别兼容 devtest环境,每种模式下都可以对设置不同的环境变量

json 复制代码
{
  "name": "vite-meta-env",
  "scripts": {
    "start": "vite",
    "start:dev": "vite --mode dev",
    "start:test": "vite --mode test",
    "build": "tsc && vite build",
    "build:dev": "vite build --mode dev",
    "build:test": "vite build --mode test",
  }
  }

根据 Vite 的约定规则,只有以VITE_开头的变量才会在客户端被获取,获取方式为:import.meta.env.{参数名}。如想添加自己的独特前缀的可通过设置 envPrefix 实现,示例代码如下:

ts 复制代码
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'

const envPrefix = ['VITE_', 'S_'];

export default defineConfig(({ mode }) => {
  // 获取环境变量
  const env = loadEnv(mode, __dirname, envPrefix);

  return {
    envPrefix,
    plugins: [
      react()
    ],
  }
})

构建产物与环境无关

借助 import-meta-env 提供的能力使构建产物与环境无关

安装依赖

sh 复制代码
pnpm i -D @import-meta-env/cli

添加替换入口

html 复制代码
<!-- index.html -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>多环境适配示例</title>
    <!-- 新增 -->
    <script>
      globalThis.import_meta_env = JSON.parse('"import_meta_env_placeholder"')
    </script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

添加 .env.example

明确需要加载的环境变量清单

sh 复制代码
# .env.example
S_API_HOST=https://xx.com

添加替换脚本

json 复制代码
{
  "scripts": {
    "deploy:env": "S_API_HOST=https://test.xx.com import-meta-env -x .env.example -p dist/index.html"
  }
}

添加获取环境变量工具方法

ts 复制代码
// src/utils/env.ts
/**
 * 环境变量表达式是静态转换的,必须使用完整的静态字符串来引用它们。
 * 以下方式获取不到
 *   import.meta.env
 *   import.meta.env['FOO']
 */
const envMap: Record<string, string> = {
  S_API_HOST: import.meta.env.S_API_HOST,
};

export const getEnvValue = (key: string): string => {
  if (import.meta.env.DEV) {
    return envMap[key];
  }

  try {
    return window.import_meta_env[key] || envMap[key];
  } catch (error) {
    return '';
  }
};

结语

本篇文章到这里就结束了,如果文章对你有用,请收藏起来,方便后续查看,如果你有更好的见解,欢迎指正~

本文的代码已整理到 vite-meta-env 仓库中,有需要的童鞋请自取

相关推荐
_.Switch1 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光1 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   1 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   1 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web1 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常1 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇2 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
Jiaberrr2 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
Tiffany_Ho3 小时前
【TypeScript】知识点梳理(三)
前端·typescript
安冬的码畜日常4 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js