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,可通过以下配置实现:
- S3桶配置:
- 开启静态网站托管,将索引文档和错误文档都设置为
index.html。
- 开启静态网站托管,将索引文档和错误文档都设置为
- Cloudfront配置:
- 在分发设置的「错误页面」中添加自定义错误响应:
- HTTP错误代码:
403(对应S3的AccessDenied) - 响应页面路径:
/index.html - HTTP响应代码:
200
- HTTP错误代码:
- 重复上述步骤添加
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
相关产品推荐
相关产品推荐

