You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因与修复方案

核心原因

  1. WORKING_DIR路径硬编码错误:在vite.config.ts中用define注入process.cwd(),会在本地构建时就把Windows路径硬编码到代码里,部署到CloudFoundry后这个路径完全无效;同时生产环境中SvelteKit运行在build目录下,process.cwd()指向的路径和本地不一致。
  2. 路径拼接的跨平台问题:用字符串拼接路径(${workingFolder}/static${params.path})会导致Windows和Linux路径分隔符冲突,在CloudFoundry的Linux容器中路径格式错误。
  3. 缺少错误日志:原代码的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:37:12