amazon-web-services - Next.js:当托管在 AWS Cloudfront 上时,如何使链接与导出的站点一起使用?
问题描述
我正在尝试通过执行静态 html 导出(即next export
)然后将生成的输出复制到 AWS S3 并通过 Cloudfront 提供它来获取原型 Next.js 项目。
我在/pages
目录中有以下两个页面:
index.tsx
Pricing.tsx
然后,按照路由文档,我Link
从索引页面向定价页面添加了一个,如下所示:
<Link href="/Pricing">
<a>Pricing</a>
</Link>
这会产生一个看起来像这样的链接example.com/Pricing
(当您将鼠标悬停在该链接上并单击该链接时,该页面确实会更改为定价页面,并且浏览器会在 URL 栏中显示“example.com/Pricing”)。
问题是,该链接不是真实的 - 它不能被添加书签或直接通过 url 栏导航到。
问题似乎是当我做 a 时next export
,Next.js.html
为每个页面生成一个文件,但路由器不使用那些.html
后缀。
因此,在使用网站时,如果用户尝试添加书签example.com/Pricing
;稍后加载该书签将失败,因为 Cloudfront 将返回 404(因为 CF 只知道该.html
文件)。
然后我尝试改变我Link
的样子:
<Link href="/Pricing.html">
<a>Pricing</a>
</Link>
这会导致路由器使用example.com/Pricing.html
并且与 Cloudfront 一起工作正常 - 但它实际上会在本地开发期间导致 404(即使用next dev
)!
我可以尝试的其他解决方法是重命名所有.html
文件并在将它们上传到 S3 之前删除扩展名(并确保它们获得content-type: text/html
标头) - 或者引入 Cloudfront lambda,在.html
请求资源时动态重命名。我真的不想做 lambda 的事情,但上传之前的重命名应该不会太难。
但感觉就像我在这里真的很努力。我在基本层面上做错了吗?Next.js 链接应该如何与静态 html 导出一起使用?
Next.js 版本:9.5.3-canary.23
解决方案
如果您希望您的 URL 是“干净的”并且最终没有,则可以使用替代答案.html
。
要让 Next.js 默认 URL 链接在 S3/Cloudfront 中正常工作,您必须在您的next.config.js
:
module.exports = {
trailingSlash: true,
}
根据文档
将页面导出为 index.html 文件并需要尾部斜杠,/about 变为 /about/index.html 并可通过 /about/ 进行路由。这是 Next.js 9 之前的默认行为。
因此,现在您可以将Link
定义保留为:
<Link href="/Pricing">
<a>Pricing</a>
</Link>
这会导致 Next.js 做两件事:
- 使用 url
example.com/Pricing/
- 注意/
最后 - 在它自己的目录中生成每个页面
index.html
- 例如/Pricing/index.html
许多 HTML 服务器在其默认配置中,如果在 URL 中index.html
看到尾随字符,则会从匹配目录中提供。/
S3 也将执行此操作,如果您将其设置为网站,并且IFF您通过网站端点访问 URL ,而不是 REST 端点。
因此,您的 Cloudfront 分发源必须配置为Origin type = Custom Origin
指向类似的域example.com.s3-website.us-east-1.amazonaws.com
,而不是S3 Origin
.
如果您的 Cloudfront/S3 配置错误,当您点击“斜杠”样式的 URL 时 - 您可能会看到您的浏览器下载binary/octet-stream
包含0 bytes
.
编辑:当心带有.
字符的页面,根据issue 16617。
推荐阅读
- html - Primeng:添加 p-selectButton 后绝对位置不起作用
- python - python中的列表循环
- c++ - 在 C++98 中生成多项式特征
- linux - 查找具有特定扩展名的文件并将权限限制为特定用户
- c++ - 缺少 vtable 错误说我没有定义我的虚拟功能
- ios - 删除内部排列有子视图的堆栈视图的最佳方法是什么?
- angular - Angular 在 TS 中获取 scss 样式
- android - 定义 '[Single:'com.example.handlers.SocketHandler']' 尝试覆盖现有的定义 koin android
- r - Drake 仅在某些情况下缺少来自静态分支的依赖项
- javascript - 如何在函数之间传递变量?