Vite React应用Docker部署到Fly.io时VITE_API_URL变量未定义问题
问题分析
Vite 的 import.meta.env.VITE_* 变量是构建时注入的——也就是说执行 npm run build 时,Vite 会把这些变量替换成具体值打包进静态文件。你用多阶段构建时,如果构建阶段没拿到 VITE_API_URL,打包后的静态文件里这个变量就是 undefined;而开发时 npm run dev 是运行时动态读取环境变量,所以能正常获取。Nginx 只是静态托管已打包的文件,没法再修改文件里的变量值,这就是问题根源。
解决方案
提供两种常用的解决思路,按需选择:
方案一:构建时传入环境变量(适合变量固定场景)
修改多阶段 Dockerfile,在构建阶段通过 ARG 接收环境变量,让 Vite 打包时直接注入正确值:
# 构建阶段 FROM node:18-alpine as builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . # 声明构建参数,接收外部传入的VITE_API_URL ARG VITE_API_URL # 将构建参数转为环境变量,供Vite打包读取 ENV VITE_API_URL=$VITE_API_URL RUN npm run build # 部署阶段 FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
然后修改 fly.toml,配置构建参数自动读取 Fly.io 的环境变量:
[build] builder = "paketobuildpacks/builder:base" [build.args] VITE_API_URL = "${VITE_API_URL}"
这样 Fly.io 构建镜像时,会把你设置的容器环境变量传入构建阶段,Vite 打包后就能得到正确的 API_URL。
方案二:运行时替换静态文件占位符(适合动态修改变量场景)
如果需要在容器启动时动态修改变量(不用重新构建镜像),可以用占位符替换的方式:
- 先修改代码,用固定占位符代替 Vite 环境变量:
// 注意用自定义占位符,不要用Vite的import.meta.env语法 const API_URL = '__API_URL__';
- 修改 Dockerfile,添加启动脚本:
# 构建阶段 FROM node:18-alpine as builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . # 打包时传入占位符 RUN VITE_API_URL=__API_URL__ npm run build # 部署阶段 FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf # 添加启动脚本并赋予执行权限 COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh EXPOSE 80 ENTRYPOINT ["/entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"]
- 编写
entrypoint.sh启动脚本,替换占位符:
#!/bin/sh # 替换静态JS文件中的占位符为Fly.io环境变量值 sed -i "s|__API_URL__|${VITE_API_URL}|g" /usr/share/nginx/html/assets/*.js # 执行原Nginx启动命令 exec "$@"
容器启动时,脚本会自动把静态文件里的 __API_URL__ 替换成你在 Fly.io 设置的环境变量值。
验证注意事项
- 确保 Fly.io 环境变量已正确设置:可以用
fly secrets list查看,或通过fly ssh console进入容器后执行echo $VITE_API_URL验证。 - 方案一修改环境变量后需要重新构建镜像;方案二只需重启容器即可生效。
内容的提问来源于stack exchange,提问作者FlameDra
相关产品推荐
相关产品推荐

