问题描述
我正在尝试通过执行Static html export(即next export
)来创建Next.js原型项目,然后将生成的输出复制到AWS S3并通过Cloudfront提供服务。
我在/pages
目录中有以下两个页面:
-
index.tsx
-
Pricing.tsx
然后,从routing doco开始,我从索引页面向定价页面添加了Link
,如下所示:
<Link href="/Pricing">
<a>Pricing</a>
</Link>
这将导致一个类似于example.com/Pricing
的链接(当您将鼠标悬停在该链接上并单击该链接时,该页面的确会更改为定价页面,并且浏览器在其中显示“ example.com/Pricing”。 URL栏)。
问题是,该链接不是真实的-无法将其添加书签或直接通过网址栏导航到该链接。
问题似乎是当我执行next export
时,Next.js为每个页面生成一个.html
文件,但是路由器不使用那些后缀.html
。 / p>
因此,在使用网站时,如果用户尝试为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/
-在末尾注意/
。
如果许多Web服务器使用默认配置,则它们会在URL中看到尾随index.html
字符,从而从该目录提供/
。
如果您已将S3设置为网站,并且 IFF ,则可以通过website endpoint,as opposed to the REST endpoint访问该URL。
因此,您的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提防带有.
个字符的页面。
写了这个问题之后,我找到了一个合理的解决方法-尽管我不确定这是否是正确的答案。
将Link
更改为:
<Link href="/Pricing" as="/Pricing.html">
<a>Pricing</a>
</Link>
这似乎在本地开发人员中以及将Cloudfront服务的站点添加为书签均有效。仍然感觉有些古怪。我也更喜欢那些非.html
的网址。哦,好吧,也许我会改名解决。