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

BrowserRouter路由异常:CI部署后URL变更但页面不跳转

环境配置

部署环境
托管:通过CloudFront访问的S3存储桶
CI:Github Actions + Terraform
CloudFront自定义404错误页设置为index.html(返回200状态码)
S3错误页设置为index.js
Node版本:16.10.0
React版本:18.2.0
补充:React Router Dom版本6.12.1,使用BrowserRouter组件

问题描述

React应用通过CI构建部署后,React Router仅变更URL但页面不跳转,只有强制刷新才能正常显示目标页面。本地开发、手动构建后通过AWS控制台上传至S3时,路由导航均正常。

CI流程仅执行npm install && npm run build,已确认MIME类型设置正确,但无法定位差异点,卡了好几天,求解决思路。

相关配置

Terraform部署文件资源配置

resource "aws_s3_bucket_object" "app_files" {
  for_each      = fileset("${path.module}/app/build", "**/*.*")
  bucket        = aws_s3_bucket.app_bucket.id
  key           = each.value
  source        = "${path.module}/app/build/${each.value}"
  etag          = filemd5("${path.module}/app/build/${each.value}")
  content_type  = lookup(var.mime_types, split(".", each.value)[length(split(".", each.value)) - 1], "application/octet-stream")
}

CloudFront分发配置

resource "aws_cloudfront_distribution" "app_distribution" {
  origin {
    domain_name = aws_s3_bucket.app_bucket.website_endpoint
    origin_id   = aws_s3_bucket.app_bucket.id

    custom_origin_config {
      http_port = 80
      https_port = 443
      origin_protocol_policy = "http-only"
      origin_ssl_protocols = ["TLSv1.2"]
    }
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"

  aliases = [var.service_domain]

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = aws_s3_bucket.app_bucket.id

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  viewer_certificate {
    acm_certificate_arn = var.main_certificate_arn
    ssl_support_method = "sni-only"
  }

  custom_error_response {
    error_code            = 404
    response_code         = 200
    response_page_path    = "/index.html"
    error_caching_min_ttl = 0
  }
}

路由JSX配置

<Router>
  <Routes>
    <Route // 移除末尾斜杠
      path="*(/+)"
      loader={({ params }) => redirect(params['*'] || '/')}
    />
    {appStore?.auth?.accessToken ? (
      <Route path="" element={<Template />}>
        <Route
          exact
          path="/"
          element={<Navigate to={ROUTES.MY_MIRRORS} />}
        />
        ... 其他应用路由
        <Route
          path="/forbidden"
          element={<Pages.ErrorBoundaryForbidden />}
        />
        <Route path="/404" element={<Pages.ErrorBoundary404 />} />
        <Route
          path="*"
          element={<Navigate replace to={ROUTES.MY_MIRRORS} />}
        />
      </Route>
    ) : (
      <Route path="" element={<UnauthenticatedTemplate />}>
        <Route path="/login" element={<Pages.Login />} />
        <Route path="/register" element={<Pages.NewUser />} />
        <Route path="/contact" element={<Pages.Contact />} />
        <Route path="/privacy-policy" element={<Pages.PrivacyPolicy />} />
        <Route path="/" element={<Pages.Home />} />
        <Route path="*" element={<Navigate replace to="/login" />} />
      </Route>
    )}
  </Routes>
</Router>

导航实现(useNavigate钩子)

import { useNavigate } from 'react-router-dom';
...

const navigate = useNavigate();
...
<Button color="gray" onClick={() => navigate('/contact')}>
  Contact Us
</Button>

补充说明:移除CI构建步骤,改为本地构建后提交build文件夹由CI部署,一切正常。问题可确定出在CI执行构建的环节。

可能的解决方向

  1. 锁定CI环境的依赖版本:本地和CI的npm/yarn版本、依赖包版本可能不一致,导致构建产物差异。可以在CI步骤中指定和本地一致的npm版本,或确保package-lock.json/yarn.lock被正确提交,强制CI安装与本地完全相同的依赖。
  2. 显式设置构建环境变量:在CI构建命令中添加NODE_ENV=production,比如NODE_ENV=production npm run build,避免环境变量差异导致路由逻辑异常。
  3. 检查React Router的base路径:在BrowserRouter中显式设置basename="/",确保路由根路径匹配部署环境,比如:
    <BrowserRouter basename="/">
      {/* 路由内容 */}
    </BrowserRouter>
    
  4. 验证CI构建的工作目录:确保CI执行npm run build的目录与本地一致,避免路径错误导致构建产物异常。
  5. 添加CloudFront缓存失效步骤:CI部署完成后,触发CloudFront缓存失效,确保用户获取到最新的构建产物,排除缓存旧资源导致的路由问题。
  6. 检查环境变量注入:如果应用依赖REACT_APP_*等环境变量,确认CI构建时这些变量已正确注入,避免缺失变量引发路由逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:57:26