Docker环境下SvelteKit调用Spring Boot后端:解决客户端/服务端渲染差异问题
解决SvelteKit容器中前后端请求地址不一致问题
问题背景
我正在开发一个全栈应用,采用Spring-boot(Kotlin)、SvelteKit(基于Vite)和MongoDB,三者各对应一个Docker容器。后端服务映射到本地6868端口:
- 前端本地通过
npm run dev(执行vite dev --host 0.0.0.0 --port 8080)运行时,能正常通过localhost:6868调用后端。 - 但前端运行在Docker容器内时,
localhost:6868指向容器内部而非宿主主机,请求失败。 - 改成后端容器名
spring-boot:8080后,服务端渲染的初始请求(+page.js中的load函数)成功,但浏览器端发起的后续请求依然报错。
核心矛盾:SvelteKit的load函数会在**服务端(Docker容器内)和客户端(浏览器)**都执行,两者的网络环境不同,请求地址不能共用。
解决方案
1. 动态判断环境切换请求地址
修改$lib/utils.js中的getBaseUrl函数,通过typeof window区分运行环境:
export function getBaseUrl() { // 服务端运行(容器内):用Docker服务名访问后端 if (typeof window === 'undefined') { return 'http://spring-boot:8080'; } // 客户端运行(浏览器):用宿主映射端口访问后端 return 'http://localhost:6868'; }
2. 更新页面请求代码
在/frontend-svelte/routes/+page.js中使用动态生成的Base URL:
import { getBaseUrl } from '$lib/utils.js'; /** @type {import('./$types').PageLoad} */ export async function load({ params }) { console.log("test") const baseUrl = getBaseUrl(); const response = await fetch(`${baseUrl}/api/groups`); console.log("response is: "); console.log(response); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } return response.json() }
3. (可选)用环境变量优化配置(适配多环境)
如果需要区分开发/生产环境,可通过Vite环境变量统一管理:
- 在前端项目根目录创建
.env.development:
# 客户端浏览器使用的API地址 VITE_PUBLIC_API_URL=http://localhost:6868 # 服务端容器内使用的API地址 VITE_SERVER_API_URL=http://spring-boot:8080
- 修改
getBaseUrl函数:
export function getBaseUrl() { if (typeof window === 'undefined') { return import.meta.env.VITE_SERVER_API_URL; } return import.meta.env.VITE_PUBLIC_API_URL; }
原理说明
- 服务端渲染阶段:
load函数在SvelteKit容器内执行,此时没有浏览器window对象,使用Docker服务名spring-boot:8080,容器间可通过Docker网络直接通信。 - 客户端运行阶段:代码在用户浏览器中执行,使用宿主主机的
localhost:6868,访问映射后的后端端口。
内容的提问来源于stack exchange,提问作者Ethan Michel
相关产品推荐
相关产品推荐

