自定义VITE插件,生成可修改配置项,用于不同项目部署

背景

我们做产品开发,经常遇见部署不同的项目,尤其是部署项目后后期免不了也要修改配置项,如果我们都写入环境变量中,每次都需要 前端 npm run build:XXX发版

此文章基于vite ,就是解决这个痛点的,方法如下 1:我们根据不同的项目,创建不同的打包命令,在package.json中增加不同项目的打包命令 如下

js 复制代码
"scripts": {
    "dev": "vite",
    "start": "vite --mode zhongyuan",
    "build:130": "vite build --mode 130",
    "build:182": "vite build --mode 182",
    "build:zhongyuan": "vite build --mode zhongyuan",
    "build:deyang": "vite build --mode deyang",
    "build:sjz": "vite build --mode sjz",
  },

"build:130""build:182" 等 就是不同项目的环境变量

2: 根目录创建 对应的环境变量配置文件 如 .env.130 .env.182, 如下

3: vite打包生成 setting.json,默认值就是上述的环境变量

4: 在页面初始化(我得是在axios实例中,get请求这个setting.json,修改全局配置)

为了实现上述功能需要以下步骤来实现

创建vite插件,生成 setting.json

基于你已经在package.json中增加不同项目的打包命令,也创建了不同的.env环境配置

创建 global-api.ts 用于获取全环境配置

js 复制代码
// 定义 Indexable 类型
type Indexable<T> = {
  [key: string]: T;
};

// 定义 GlobalAPI 对象
const GlobalAPI: Indexable<any> = {
  config: {}, // 用于存储环境变量
};

const devConfig: Indexable<any> = {};
for (const key in import.meta.env) {
  if (key.startsWith("VITE_")) {
    devConfig[key] = import.meta.env[key];
  }
}
GlobalAPI.config = devConfig;

export { GlobalAPI };

其他组件使用 GlobalAPI

js 复制代码
import { GlobalAPI } from "@/constants"; // 换成你得暴露地址
document.title = GlobalAPI?.config?.VITE_SYSTEM_TITLE || "政务知识助手";

创建 vite-plugin-generate-settings.js vite插件

js 复制代码
// vite-plugin-generate-settings.js
import fs from 'fs';
import path from 'path';
import { loadEnv } from 'vite';

/**
 * @param {object} options
 * @param {string} options.mode - Vite build mode
 * @param {string} options.envDir - Directory where .env files are located
 * @param {string | string[]} [options.prefixes=['VITE_']] - Prefixes to filter
 * @returns {import('vite').Plugin}
 */
function generateSettingsPlugin(options) { // 接收一个 options 对象
  const { mode, envDir, prefixes = ['VITE_'] } = options; // 解构参数

  if (!mode || !envDir) {
     // 在配置阶段就进行检查,确保必要参数已提供
     throw new Error('[Generate Settings] Missing required options: mode and envDir');
  }

  let viteConfig;
  let settings = {};

  return {
    name: 'vite-plugin-generate-settings',
    apply: 'build',

    configResolved(resolvedConfig) {
      viteConfig = resolvedConfig;
      // 使用传入的 mode 和 envDir
      const env = loadEnv(mode, envDir, '');

      settings = {};
      const VITE_PREFIXES = Array.isArray(prefixes) ? prefixes : [prefixes];

      for (const envKey in env) {
        if (VITE_PREFIXES.some(prefix => envKey.startsWith(prefix))) {
          settings[envKey] = env[envKey];
        }
      }
       console.log('\n[Generate Settings] Filtered settings:', settings);
    },

    writeBundle(options) {
       // ... (writeBundle 逻辑保持不变)
       if (!viteConfig) {
         console.error('[Generate Settings] Vite config not resolved.');
         return;
       }
       if (Object.keys(settings).length === 0) {
         console.warn('[Generate Settings] No variables starting with VITE_ found. settings.json will be empty or not generated.');
       }

      const outDir = options.dir || viteConfig.build.outDir || 'dist';
      const filePath = path.resolve(outDir, 'setting.json');

      try {
        if (!fs.existsSync(outDir)) {
          fs.mkdirSync(outDir, { recursive: true });
        }
        fs.writeFileSync(filePath, JSON.stringify(settings, null, 2));
        console.log(`\n[Generate Settings] Successfully generated setting.json at: ${filePath}`);
      } catch (error) {
        console.error(`[Generate Settings] Error writing setting.json: ${error}`);
      }
    }
  };
}

export default generateSettingsPlugin;

此插件的作用就是,获取当前的环境变量已 VITE_开头的,并且生成对用的 setting.json

vite.config.ts 引用此插件

js 复制代码
export default defineConfig(({ command, mode }) => {
  const root = process.cwd();
  return {
    plugins: [
      generateSettingsPlugin({
        mode: mode,               // 传递当前的 mode
        envDir: root,             // 显式传递 env 文件目录 (通常是项目根目录)
     })
    ],
  }
})
...你的其余配置

执行 npm run build:xxx

执行 npm run build:xxx 默认会在dist文件目录中生成, setting.json

js 复制代码
{
  "VITE_SYSTEM_TITLE1": "系统名称1",
  "VITE_SYSTEM_TITLE2": "系统名称2",
  "VITE_SYSTEM_TITLE3": "系统名称3",
  "VITE_SYSTEM_TITLE4": "系统名称4",
}

初始化的时候重新获取 setting.json更改配置 (我的是在axios中)

鉴于我们全局有请求接口,如获取用户信息的,我们在axios中,重新设置配置项

js 复制代码
class Request<R = any, D = any> {

constructor(config: InstanceRequestConfig<D, R>) {
    this.config = config;
    // 在此动态获取及配置
    if (config?.serverConfig && typeof config?.serverConfig === 'object') {
      const xhr = new XMLHttpRequest();
      // 此处注意路径
      xhr.open('get', `/setting.json`, false);
      xhr.onreadystatechange = () => {
        if (xhr.status === 200 && xhr.readyState === 4) {
          const responseJson = JSON.parse(xhr.responseText);
          Object.assign(GlobalAPI?.config, responseJson);
        }
      };
      xhr.send();
    }
    this.instance = axios.create(config);
    this.registerInterceptors();
    config.generateRequestKey &&
      (this.generateRequestKey = config.generateRequestKey);
  }

}


// 应用class

const request = new Request<Service.RequestResult>({
  timeout: 300000, // 超时五分钟
  baseURL: import.meta.env.VITE_BASE_API,
  withCredentials: false,
  // 取消重复请求
  cancelDuplicateRequest: false,
  
  // 开发环境不设置仅用默认值   生产环境设置动态设置
  serverConfig: import.meta.env.DEV ? undefined: GlobalAPI.config,
  
  })

部署成功后,修改 setting.json,此时我们动态修改一个数据,刷新页面 页面的 GlobalAPI已经生效

总结

以上是适用于多个项目部署 以及部署后有修改配置需求的, 当然你也可以不自定义插件,将 setting.json存放于服务器的任何一个目录,动态请求即可,

注意: 请求setting.json的时机,对于静态的 import 极大概率在你获取到配置项之前就生效了,有好的交换setting.json时机,也可以在评论告知下,仅供参考

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax