Next.js静态站部署S3+CloudFront:非首页刷新跳转首页问题
解决Next.js 12.3静态站部署S3+CloudFront的路由刷新异常问题
以下是针对你遇到的路由问题的具体解决步骤:
1. 确认Next.js静态导出配置与产物结构
首先确保你的Next.js配置完全正确,并且导出的静态文件结构符合要求:
- 在
next.config.js中添加以下配置:
module.exports = { trailingSlash: true, output: 'export', // Next.js 12+ 静态导出必须配置此项 }
- 执行导出命令:
npm run build && next export - 检查生成的
out目录,确保每个子路由都有对应的文件夹和index.html,比如:out/index.html(首页)out/search/advSearch/index.html(高级搜索页)out/search/results/index.html(结果页)
2. 配置S3存储桶静态网站托管
S3默认不会自动将/advSearch这类路径映射到/advSearch/index.html,需要调整静态网站托管设置:
- 启用S3静态网站托管,将索引文档和错误文档都设置为
index.html - 添加路由重定向规则,将不带末尾斜杠的路径重定向到带斜杠的版本(让S3加载对应文件夹下的index.html):
在S3控制台的「静态网站托管」页面,找到「路由规则」,添加以下XML规则:
<RoutingRules> <RoutingRule> <Condition> <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals> <KeyPrefixEquals></KeyPrefixEquals> </Condition> <Redirect> <ReplaceKeyPrefixWith>$1/</ReplaceKeyPrefixWith> <HttpRedirectCode>301</HttpRedirectCode> </Redirect> </RoutingRule> </RoutingRules>
3. 配置CloudFront路径重写(关键)
CloudFront默认不会处理路径到index.html的映射,需要通过Lambda@Edge实现路径重写:
- 创建一个Lambda@Edge函数(需在us-east-1区域创建),代码如下:
exports.handler = async (event) => { const request = event.Records[0].cf.request; const uri = request.uri; // 处理不带扩展名且不以斜杠结尾的路径,添加斜杠 if (!uri.includes('.') && !uri.endsWith('/')) { request.uri = uri + '/'; } // 处理以斜杠结尾的路径,自动追加index.html if (uri.endsWith('/')) { request.uri = uri + 'index.html'; } return request; };
- 将该函数关联到CloudFront分发的Viewer Request事件上
- 确保CloudFront的源指向S3静态网站托管域名(而非S3 REST API域名),这样S3的索引文档规则才会生效
4. 清除CloudFront缓存
修改配置后必须清除CloudFront缓存,否则旧缓存会导致问题持续:
- 在CloudFront控制台找到你的分发,进入「无效化」标签
- 创建无效化请求,路径填
/*,提交后等待缓存清除完成
完成以上步骤后,直接访问MySearchApp.cloudfront.net/advSearch或刷新子页面,就能正确加载对应的index.html了。
内容的提问来源于stack exchange,提问作者Vin
相关产品推荐
相关产品推荐

