本文介绍了Next.js:当托管在 AWS Cloudfront 上时,如何使链接与导出的站点一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过执行 来构建 Next.js 项目原型静态 html 导出(即 next export),然后将生成的输出复制到 AWS S3 并通过 Cloudfront 提供服务.

I'm trying to get a prototype Next.js project up by doing a Static html export (i.e. next export) and then copying the generated output to AWS S3 and serving it via Cloudfront.

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

I've got the following two pages in the /pages directory:

  • index.tsx
  • Pricing.tsx

然后,按照 routing doco 我添加了一个 Link 从索引页面到定价页面,如下所示:

Then, following along from the routing doco I added a Link to the pricing page from the index page, like so:

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

这会生成一个类似于 example.com/Pricing 的链接(当您将鼠标悬停在该链接上并单击该链接时,该页面确实会更改为定价页面,并且浏览器会显示 ``URL 栏中的 example.com/Pricing`).

This results in a link that looks like example.com/Pricing (when you hover over it and when you click the link, the page does change to the pricing page and the browser shows ``example.com/Pricing` in the URL bar).

问题是,该链接不是真实的 - 无法通过 url 栏直接添加书签或导航到该链接.

The problem is, that link is not real - it cannot be bookmarked or navigated to directly via the url bar.

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

The problem seems to be that when I do a next export, Next.js generates a .html file for each page, but the router doesn't use those .html suffixes.

所以在使用网站时,如果用户尝试将 example.com/Pricing 加入书签;稍后加载该书签将失败,因为 Cloudfront 将返回 404(因为 CF 只知道 .html 文件).

So when using the site, if the user tries to bookmark example.com/Pricing; loading that bookmark later will fail because Cloudfront will return a 404 (because CF only knows about the .html file).

然后我尝试将我的 Link 更改为:

I then tried changing my Link to look like:

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

这会导致路由器使用 example.com/Pricing.html 并且可以在 Cloudfront 中正常工作 - 但它实际上会在本地开发期间导致 404(即使用 next dev)!

That causes the router to use example.com/Pricing.html and that works fine with Cloudfront - but it actually causes a 404 during local development (i.e. using next dev)!

我可以尝试的其他解决方法是重命名所有 .html 文件并在将它们上传到 S3 之前删除扩展名(并确保它们获得 content-type: text/html 标头) - 或引入 Cloudfront lambda,在请求 .html 资源时动态重命名.我真的不想做 lambda 的事情,但上传前的重命名应该不会太难.

Other workarounds I could try are renaming all the .html files and removing the extension before I upload them to S3 (and make sure they get a content-type: text/html header) - or introducing a Cloudfront lambda that does the renaming on the fly when .html resources are requested. I don't really want to do the lambda thing, but the renaming before uploading shouldn't be too difficult.

但感觉就像我在这里真的很努力.我在基本层面上做错了吗?Next.js 链接应该如何与静态 html 导出一起使用?

But it feels like I'm really working uphill here. Am I doing something wrong at a basic level? How is Next.js linking supposed to work with a static html export?

Next.js 版本:9.5.3-canary.23

Next.js version: 9.5.3-canary.23

推荐答案

如果您希望您的 URL 是干净的",则另一种答案是最后没有 .html.

Alternate answer if you want your URLs to be "clean" and not have .html on the end.

要让 Next.js 默认 URL 链接在 S3/Cloudfront 中正常工作,您必须配置添加尾部斜杠".next.config.js 中的选项:

To get Next.js default URL links working properly with S3/Cloudfront, you must configure the "add a trailing slash" option in your next.config.js:

module.exports = {
  trailingSlash: true,
}

根据 文档

将页面导出为 index.html 文件并需要尾部斜杠,/about 变为/about/index.html 并可通过/about/路由.这是 Next.js 9 之前的默认行为.

所以现在您可以将 Link 定义保留为:

So now you can leave your Link definition as:

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

这导致 Next.js 做两件事:

This causes Next.js to do two things:

如果在 URL 中看到尾随 / 字符,许多 HTML 服务器会在其默认配置中从匹配目录中提供 index.html.

Many HTML servers, in their default configuration, will serve up the index.html from inside the matching directory if they see a trailing / character in the URL.

S3 也会这样做,如果您将其设置为网站并且 IFF 您通过 网站端点,而不是 REST 端点.

S3 will do this also, if you have it set up to serve as a website and IFF you access the URL through the website endpoint, as opposed to the REST endpoint.

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

So your Cloudfront distribution origin must be configured as a Origin type = Custom Origin pointing at a domain something like example.com.s3-website.us-east-1.amazonaws.com, not as an S3 Origin.

如果您的 Cloudfront/S3 配置错误,当您点击尾部斜线"时样式 URL - 您可能会看到您的浏览器下载一个类型为 binary/octet-stream 的文件,其中包含 0 字节.

If you have your Cloudfront/S3 mis-configured, when you hit a "trailing slash" style URL - you will probably see your browser download a file of type binary/octet-stream containing 0 bytes.

编辑:注意带有 . 字符的页面,根据 问题 16617.

Edit: Beware pages with . characters, as per issue 16617.

这篇关于Next.js:当托管在 AWS Cloudfront 上时,如何使链接与导出的站点一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 08:21