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

将React应用部署到S3后React Router子路由无法渲染(已解决403/404)

排查React Router子路由在CloudFront+S3部署后无法渲染的问题

1. 修复React Router嵌套路由配置错误

你的路由定义存在嵌套路径冲突:

export const AppRoutes: RouteObject[] = [
    {
        element: <App />,
        path: '/',
        children: [{
            path: 'preview',
            children: [{
                path: '/preview/:postId', // 错误:绝对路径会忽略父路由层级
                element: < BlogPreviewForm />
            }]

        }]
    }
]

嵌套路由的path如果以/开头(绝对路径),会直接覆盖父路由的层级,导致路由匹配逻辑混乱。修改为相对路径即可:

// 方案1:直接作为根路由的子路由
export const AppRoutes: RouteObject[] = [
    {
        element: <App />,
        path: '/',
        children: [
            {
                path: 'preview/:postId',
                element: <BlogPreviewForm />
            }
        ]
    }
]

// 方案2:保持嵌套结构,使用相对路径
export const AppRoutes: RouteObject[] = [
    {
        element: <App />,
        path: '/',
        children: [{
            path: 'preview',
            children: [{
                path: ':postId', // 相对父路由,完整路径为/preview/:postId
                element: < BlogPreviewForm />
            }]
        }]
    }
]

2. 验证CloudFront错误页面配置

确保CloudFront的错误页面规则是返回index.html并返回200状态码,而非3xx重定向:

  • 进入CloudFront控制台 → 目标分发 →「错误页面」标签
  • 添加403、404错误规则:
    • HTTP错误代码:选择403/404
    • 响应页面路径:填写/index.html
    • HTTP响应代码:设置为200
      如果用重定向(301/302),浏览器会直接跳转到根路由,丢失原路径信息,React Router无法解析子路由。

3. 确认CloudFront源指向S3静态网站托管端点

不要使用S3桶的REST API端点(如bucket-name.s3.amazonaws.com)作为CloudFront源,必须使用S3静态网站托管专属端点(如bucket-name.s3-website-region.amazonaws.com):

  • 进入S3控制台 → 目标桶 →「静态网站托管」标签,复制端点URL
  • 在CloudFront分发的源设置中,将域名替换为该静态网站端点,协议选择HTTP(CloudFront会处理HTTPS层的转发)

4. 检查React构建的静态资源路径

在项目根目录的package.json中添加"homepage": "./",确保构建后的静态资源(JS、CSS等)使用相对路径:

{
  "name": "your-react-app",
  "homepage": "./",
  // 其他配置...
}

如果不设置该字段,React会生成绝对路径的资源引用(如/static/js/main.xxx.js),直接访问子路由时,浏览器会错误请求/preview/static/js/main.xxx.js,导致资源加载失败,页面无内容。

5. 修正Lambda@Edge URL重写逻辑(若使用)

如果用Lambda@Edge做URL重写,需确保只对非静态资源请求重写到index.html,保留静态资源的正常访问:

exports.handler = async (event) => {
    const request = event.Records[0].cf.request;
    const uri = request.uri;

    // 仅对无文件扩展名的路径(非静态资源)重写
    if (!uri.includes('.') && uri !== '/') {
        request.uri = '/index.html';
    }

    return request;
};

注意:部署Lambda@Edge后需等待CloudFront缓存刷新生效,可手动触发缓存失效加速更新。

6. 禁用index.html的缓存

在CloudFront中为/index.html配置单独的缓存策略,避免页面被缓存导致路由配置无法更新:

  • 创建新缓存策略:设置TTL为0,允许查询字符串,禁用缓存
  • 在CloudFront分发的「行为」标签中,添加路径/index.html,关联该缓存策略

内容的提问来源于stack exchange,提问作者gfree

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:20:42