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

Nuxt 3静态应用部署AWS Cloudfront后子路由刷新遇AccessDenied问题求助

Nuxt 3 SPA部署到AWS S3+Cloudfront刷新子路由出现AccessDenied的解决方案

问题背景

我有一个Nuxt 3(v3.11.2)应用,设置ssr: false后执行nuxi generate生成静态文件,上传到AWS S3存储桶,通过Cloudfront和Route53提供服务。配置了Cloudfront的Lambda@Edge触发器处理路由重写,但直接访问主域名正常,进入子目录路由(如/something/:id)后刷新页面会收到Cloudfront返回的AccessDenied错误。不想使用哈希模式(会影响SEO),寻求可行解决方案。

原Lambda@Edge重写代码:

function handler(event) {
    var request = event.request;
    var uri = request.uri;
    
    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    } 
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }

    return request;
}

问题原因

原Lambda逻辑会把无后缀的路由(如/something/123)重写为/something/123/index.html,但S3桶中不存在这个文件——Nuxt生成的SPA静态文件只有根目录的index.html和各类静态资源(js、css、assets等),因此触发AccessDenied错误。SPA应用需要所有前端路由都指向根目录的index.html,由Nuxt前端路由系统处理路径匹配。

解决方案

方案1:修正Lambda@Edge重写逻辑

修改Lambda函数,将所有非静态资源的请求直接重写到根index.html,同时保留静态资源的正常访问:

function handler(event) {
  const request = event.request;
  const uri = request.uri;

  // 定义静态资源后缀列表,根据项目实际情况调整
  const staticExtensions = ['.js', '.css', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff', '.woff2', '.ttf', '.eot'];
  const isStaticResource = staticExtensions.some(ext => uri.endsWith(ext));

  if (!isStaticResource) {
    // 所有非静态资源请求都指向根index.html
    request.uri = '/index.html';
  }

  return request;
}
  • 注意:需根据项目实际的静态资源类型调整staticExtensions数组,确保所有静态资源能正常访问。
  • 更新Lambda@Edge后,需手动使Cloudfront分发失效,确保新规则生效。

方案2:S3静态网站托管+Cloudfront错误页面配置

若不想使用Lambda@Edge,可通过以下配置实现:

  1. S3桶配置:
    • 开启静态网站托管,将索引文档和错误文档都设置为index.html。
  2. Cloudfront配置:
    • 在分发设置的「错误页面」中添加自定义错误响应:
      • HTTP错误代码:403(对应S3的AccessDenied)
      • 响应页面路径:/index.html
      • HTTP响应代码:200
    • 重复上述步骤添加404错误的自定义响应,同样指向/index.html并返回200状态码。
    • 确保Cloudfront的源指向S3的静态网站托管端点(而非S3桶的REST API端点)。

确保Nuxt配置正确

保持ssr: false,无需开启哈希模式,使用默认的history模式即可:

export default defineNuxtConfig({
  ssr: false,
  // 若不需要预渲染任何路由,可保留此钩子;不影响核心问题
  hooks: {
    'prerender:routes': ({ routes }) => {
      routes.clear()
    },
  },
  // 移除hashMode配置,保持history模式
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 09:10:17