如何在基于Node适配器的SvelteKit应用中运行时修改环境变量?
问题核心在于:带VITE_前缀的环境变量是SvelteKit在构建阶段直接嵌入到客户端代码里的,所以构建完成后再修改这些变量根本不会生效。要实现运行时动态配置,得换用非VITE_前缀的环境变量,再通过服务器端逻辑传递给客户端。
下面是具体步骤:
1. 调整环境变量命名
把原来的VITE_BACKEND_URL改成普通的BACKEND_URL,去掉VITE_前缀——这样这个变量就不会在构建时被打包进客户端代码,而是保留在Node.js运行环境里。
2. 在SvelteKit中获取运行时变量
服务器端直接使用
在服务器端代码(比如hooks.server.js、+server.js这类仅在Node端运行的文件)里,可以直接通过process.env.BACKEND_URL读取变量:
// src/hooks.server.js export async function handle({ event, resolve }) { // 直接使用运行时环境变量 event.locals.backendUrl = process.env.BACKEND_URL; return resolve(event); }
传递给客户端
如果客户端代码需要用到这个变量,得通过服务器端load函数或者API端点传递:
方式一:根布局的server load函数
在src/routes/+layout.server.js里定义load函数,把变量注入到页面数据中:
export async function load() { return { backendUrl: process.env.BACKEND_URL }; }
然后在客户端组件里就可以通过data.backendUrl访问:
<!-- src/routes/+page.svelte --> <script> export let data; </script> <p>后端地址:{data.backendUrl}</p>
方式二:创建API端点返回变量
写一个+server.js端点让客户端请求获取变量:
// src/routes/api/env/+server.js import { json } from '@sveltejs/kit'; export function GET() { return json({ backendUrl: process.env.BACKEND_URL }); }
客户端可以在初始化时请求这个端点:
<!-- src/routes/+page.svelte --> <script> let backendUrl; async function loadEnv() { const res = await fetch('/api/env'); const env = await res.json(); backendUrl = env.backendUrl; } loadEnv(); </script> {#if backendUrl} <p>后端地址:{backendUrl}</p> {/if}
3. 修改Dockerfile
不需要--env-file参数,因为docker run -e传递的环境变量会直接进入Node.js的process.env。简化后的Dockerfile:
FROM node:23-alpine AS builder WORKDIR /app COPY . . RUN npm install RUN npm run build --omit=dev FROM node:23-alpine AS runner WORKDIR /app COPY --from=builder /app/build ./build COPY --from=builder /app/package*.json ./ RUN npm install --omit=dev EXPOSE 3000 CMD ["node", "build/index.js"]
(这里用多阶段构建可以减小镜像体积,也可以保持原来的单阶段,只要确保启动时直接运行node build/index.js即可)
4. 运行容器测试
用原来的命令运行,注意变量名改成BACKEND_URL:
docker run -e BACKEND_URL="http://localhost:5062" -p 3000:3000 frontend
这样启动容器时传递的环境变量就会在运行时生效,每次启动都可以动态修改,不需要重新构建镜像。
内容的提问来源于stack exchange,提问作者Sniphs

