在 vite 项目中配置环境变量踩坑记录

接到一个需求,需要在访问路径上增加一层路径

http://localhost:5173/home -> http://localhost:5173/ng/home

一想这不是分分钟完成的事情么?vite 提供的 base 就可以实现

配置完 base 之后,页面中的资源在打包后都加上了 base 中配置的路径

不过仔细一看,我们在 index.html 中有一个自定义的 script 没有加上 base 中配置的路径

因为配置的 base 是无法直接作用到自定义的 script 标签中

html 复制代码
<script>
  var time = new Date().getTime();
  document.write("<script src='/config.js?v=" + time + "'><\/script>");
</script>

为什么我们要单独加载这个配置文件,不用环境变量呢?

因为我们的项目是通过 docker 部署,不同环境有不同的 config,运维给配置了一个映射路径,工作流程就是这样,没法改变

所以我在使用 base 这个参数时需要额外处理这个自定义的 script

稍微思索一下,我觉得 vite 应该提供了环境变量,可以在打包时注入到项目中,然后就去翻文档

果然在翻了两遍文档后发现有一个 BASE_URL 环境变量,文档

%BASE_URL% 在打包时,会被替换成 base 中配置的值,如果没有配置,默认是 /

html 复制代码
<script>
  var time = new Date().getTime();
  document.write("<script src='%BASE_URL%config.js?v=" + time + "'><\/script>");
</script>

访问资源的路径配置好了之后,还存在一个路由权限问题

由于增加了一层路径,所以无法直接使用下面的方式去判断当前用户是否有权限访问

js 复制代码
// before                         // after
navigate("/home")           ->    navigate("/ng/home")

if(pathname === "home"){    ->    if(pathname === "/ng/home"){
  // do something                   // do something
}                                 }

解决这个问题有两种方案:

  1. 使用 BASE_URL,项目中通过 import.meta.env.BASE_URL 获取到 base 中配置的路径
  2. 使用 define 配置,文档

这种方式都可以通过加载 .env 文件来配置

vite 默认不加载 .env 文件,我们将路径配置在 .env 文件中,所以需要用 loadEnv 方法加载项目中的 .env 文件

js 复制代码
const env = loadEnv("development", process.cwd(), "");

但是这里要注意的是传入到 define 时要用 JSON.stringify(),如下:

js 复制代码
defineConfig(({ mode }) => {
  const path = env.VITE_PATH;
  return {
    base: path,
    define: {
      __PATH__: JSON.stringify(path),
    },
  };
});

不能够这样使用:

js 复制代码
defineConfig(({ mode }) => {
  const path = JSON.stringify(env.VITE_PATH); // 这样拿到的 path 是一个字符串,在后面拼接路劲时会出现问题:http://localhost:5173/"ng"/home
  return {
    base: path,
    define: {
      __PATH__: path,
    },
  };
});

如果在读取环境变量时使用了 JSON.stringify(),那么拿到的值就是一个字符串,而不是一个变量,在拼接路径时会出现问题

js 复制代码
http://localhost:5173/"ng"/home

配置完之后,在项目中就可以通过 __PATH__ 来使用环境变量了

js 复制代码
// before                       // after                                     // 打包后
navigate("/home")          ->   navigate(`${__PATH__}home`)            ->    navigate("/ng/home")

if(pathname === "home"){   ->   if(pathname === `${__PATH__}home`){    ->    if(pathname === "/ng/home"){
  // do something                 // do something                             // do something
}                               }                                            }

PS:

  1. 在使用 %BASE_URL% 是需要注意,在默认情况下,它的值是 /
  2. 拼接路径时不需要写 /,应该直接写 config.js,如 %BASE_URL%config.js
  3. vite.config.js 中要将默认情况和 define 统一处理成后面带 /,避免在使用时不统一
相关推荐
马可家的菠萝1 小时前
自动保存已经有了,为什么笔记软件还需要“历史版本”?
前端·后端·架构
半个落月1 小时前
从 "use client" 到 Route Handler:用 Todos 理解 Next.js 水合与全栈请求
前端·react.js·next.js
qq_452396231 小时前
第七篇:《大型前端项目的模块化与目录结构设计》
前端
你脑门上的脚印1 小时前
Vue 项目从零实现语音转文字、文字转语音功能(完整可用 + 踩坑指南)
前端·vue.js
paopaokaka_luck2 小时前
基于springboot3+vue3的车间生产管理系统(Echarts图形化分析、BI报表)
java·前端·spring boot·学习·echarts
程序员鱼皮2 小时前
3 大 DeepSeek Harness 进阶玩法,招多个大肥鱼帮我干活!
前端·后端·ai编程
KoPa2 小时前
HeySmart:大模型开源网关基座-请求生命周期与钩子引擎
前端·后端
七牛开发者2 小时前
Coding Agent 如何跑稳长任务?从上下文管理到运行时状态
前端·javascript·后端
半个落月2 小时前
从 CSR 到 Server Component:吃透 Next.js 16 App Router 路由、布局与 SEO
前端·next.js
七牛开发者3 小时前
拆解 DeepSeek Harness:Profile 与 Bundle 如何装配运行时
前端·javascript·后端