CloudFoundry部署Svelte项目后静态文件路由失效的排查与解决
问题描述
我有一个Svelte项目,本质是个以内嵌表格展示内外部文件链接的数据库,功能不复杂。参考相关帖子实现了静态文件路由,本地运行完全正常,但部署到CloudFoundry后出现404 / not found错误,且无相关日志输出,代码好像根本没执行。
相关代码与配置
路由代码(/src/routes/[...path]/+server.js)
import path from 'node:path' import fs from 'node:fs/promises' import { error } from '@sveltejs/kit' import { defineConfig } from 'vite'; export const GET = async ({ params }) => { console.log("i've got the params ", params); const workingFolder = import.meta.env.WORKING_DIR; console.log("here is my url ", import.meta.url) const pathName = `${workingFolder}/static${params.path}`; console.log("here is the full path: ", pathName); try { const file = await fs.readFile(pathName); return new Response(file, { headers: { 'Content-Type': getMimeType(pathName), }, }); } catch { throw error(404, 'File not found.'); } } function getMimeType(filePath) { const ext = path.extname(filePath).toLowerCase(); const mimeTypes = { '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript', '.json': 'application/json', '.png': 'image/png', '.jpg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.txt': 'text/plain', }; return mimeTypes[ext] || 'application/octet-stream'; }
本地运行日志
i've got the params { path: '/uploads_folder/cls/20241216-01/9Mb-report.html' } here is my url file:///C:/projects/project_name/src/routes/[...path]/+server.js here is the full path: C:\projects\project_name/static/uploads_folder/cls/20241216-01/9Mb-report.html
Vite配置(vite.config.ts)
export default defineConfig({ plugins: [sveltekit()], test: { include: ['**/*.{test,spec}.{js,ts}'] }, define: { 'import.meta.env.VERSION': JSON.stringify(version), 'import.meta.env.WORKING_DIR': JSON.stringify(process.cwd()), }, server: { fs: { strict: false, }, } });
CloudFoundry部署配置(manifest.yml)
--- applications: - name: mywebsite memory: 1G instances: 1 routes: - route: mywebsite.mycloudfoundry.com stack: cflinuxfs4 buildpacks: - https://github.com/cloudfoundry/nodejs-buildpack services: - serviceOne - database env: PUBLIC_ENVOY_URL: "https://myenvoy.mycloudfoundry.com/" BODY_SIZE_LIMIT: 25M
问题原因与修复方案
核心原因
WORKING_DIR路径硬编码错误:在vite.config.ts中用define注入process.cwd(),会在本地构建时就把Windows路径硬编码到代码里,部署到CloudFoundry后这个路径完全无效;同时生产环境中SvelteKit运行在build目录下,process.cwd()指向的路径和本地不一致。- 路径拼接的跨平台问题:用字符串拼接路径(
${workingFolder}/static${params.path})会导致Windows和Linux路径分隔符冲突,在CloudFoundry的Linux容器中路径格式错误。 - 缺少错误日志:原代码的catch块没有输出错误信息,导致部署后无法排查具体问题。
修复步骤
1. 修正WORKING_DIR的获取方式
去掉vite.config.ts中define里的WORKING_DIR配置,改为在服务器代码中动态获取或通过环境变量传递,同时修复路径拼接方式:
// 移除无用的import { defineConfig } from 'vite'; import path from 'node:path' import fs from 'node:fs/promises' import { error } from '@sveltejs/kit' export const GET = async ({ params }) => { console.log("i've got the params ", params); // 优先用环境变量指定,否则动态获取项目根目录 const workingFolder = process.env.WORKING_DIR || path.join(process.cwd(), '..'); console.log("workingFolder: ", workingFolder); // 用path.join自动处理跨平台路径分隔符 const pathName = path.join(workingFolder, 'static', ...params.path); console.log("here is the full path: ", pathName); try { const file = await fs.readFile(pathName); return new Response(file, { headers: { 'Content-Type': getMimeType(pathName), }, }); } catch (err) { // 增加错误日志,方便部署后排查 console.error("File read error: ", err); throw error(404, 'File not found.'); } } // 保留getMimeType函数不变 function getMimeType(filePath) { const ext = path.extname(filePath).toLowerCase(); const mimeTypes = { '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript', '.json': 'application/json', '.png': 'image/png', '.jpg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.txt': 'text/plain', }; return mimeTypes[ext] || 'application/octet-stream'; }
2. 在manifest.yml中添加环境变量
指定CloudFoundry容器中的项目根目录:
env: # ... 原有环境变量 WORKING_DIR: "/home/vcap/app"
3. 验证静态文件目录的部署情况
确认static/uploads_folder目录在构建后被正确复制到build目录,SvelteKit默认会自动处理,若有自定义构建脚本,需保证静态目录被包含。
4. 检查容器文件权限
通过cf ssh mywebsite进入CloudFoundry容器,执行ls -l /home/vcap/app/static/uploads_folder,确保vcap用户有目录和文件的读取权限。
内容的提问来源于stack exchange,提问作者forkintheass
相关产品推荐
相关产品推荐

