问题描述
我正在尝试通过执行 来构建 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:
- 使用网址
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 上时,如何使链接与导出的站点一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!