Next.js:当托管在 AWS Cloudfront 上时,如何使链接与导出的站点一起使用? [英] Next.js: How to make links work with exported sites when hosted on 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 之前的默认行为.
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
定义保留为:
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:
- 使用网址
example.com/Pricing/
- 注意末尾的/
- 在其自己的目录中将每个页面生成为
index.html
- 例如/Pricing/index.html
- use the url
example.com/Pricing/
- note the/
on the end - generate each page as
index.html
in it's own directory - e.g./Pricing/index.html
如果在 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 上时,如何使链接与导出的站点一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!