Next.js:托管在 AWS Cloudfront 上时,如何使链接与导出的站点一起使用?

Next.js: How to make links work with exported sites when hosted on AWS Cloudfront?

我正在尝试通过执行 Static html export(即 next export)来获得原型 Next.js 项目,然后将生成的输出复制到 AWS S3 并通过 Cloudfront 提供它.

我在 /pages 目录中有以下两页:

然后,在 routing doco 之后,我从索引页面向定价页面添加了 Link,如下所示:

<Link href="/Pricing">
  <a>Pricing</a>
</Link>

这会导致 link 看起来像 example.com/Pricing(当您将鼠标悬停在它上面并单击 link 时,页面确实会更改为定价页面和浏览器在 URL 栏中显示 example.com/Pricing

问题是,link 不是真实的 - 它不能通过 url 栏直接添加书签或导航到。

问题似乎是当我执行 next export 时,Next.js 为每个页面生成一个 .html 文件,但路由器不使用那些 .html后缀。

因此,在使用网站时,如果用户尝试添加书签 example.com/Pricing;稍后加载该书签将失败,因为 Cloudfront 将 return 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 header)- 或者引入 Cloudfront lambda,它在请求 .html 资源时即时重命名。我真的不想做 lambda 的事情,但是上传前的重命名应该不会太难。

但感觉我真的在这里工作上坡。我在基本层面做错了什么吗? Next.js linking 应该如何使用静态 html 导出?

Next.js版本:9.5.3-canary.23

写完这个问题后,我找到了一个合理的解决方法 - 虽然我不确定它是否是“正确”答案。

Link 更改为:

<Link href="/Pricing" as="/Pricing.html">
  <a>Pricing</a>
</Link>

这似乎适用于本地开发人员和为 Cloudfront 服务的站点添加书签。仍然感觉有点靠不住。我也比较喜欢那些非 .html 的网址。哦,好吧,也许我会改用重命名解决方法。

如果您希望您的 URL 是“干净的”并且末尾没有 .html,则为替代答案。

要使 Next.js 默认 URL 链接与 S3/Cloudfront 正常工作,您必须在 next.config.js:[=31] 中配置“添加尾部斜杠”选项=]

module.exports = {
  trailingSlash: true,
}

根据 documentation

export pages as index.html files and require trailing slashes, /about becomes /about/index.html and is routable via /about/. This was the default behavior prior to 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。

因此您的 Cloudfront 分发来源必须配置为 Origin type = Custom Origin 指向类似 example.com.s3-website.us-east-1.amazonaws.com 的域, 而不是 作为 S3 Origin .

如果您有 Cloudfront/S3 mis-configured,当您点击“尾部斜杠”样式时 URL - 您可能会看到浏览器下载类型为 [=24= 的文件] 包含 0 bytes.


编辑:根据issue 16617.

,注意包含 . 个字符的页面