NextJS导出具有以下结构的静态站点:
|-- index.html
|-- article.html
|-- tag.html
|-- article
| |-- somearticle.html
| \-- anotherarticle.html
\-- tag
|-- tag1.html
\-- tag2.html
我正在使用.htaccess文件隐藏.html扩展名:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
一切正常,除了:
domain/article
的链接,它将显示article.html页面,但是我的地址栏显示domain/article
<-好。domain/article/
(请注意斜杠),其中列出了文章目录的内容<-Bad(与Tag相同)domain/article
会将我带到domain/article/
,而不显示没有扩展名article.html
的{{1}}。所以...
.html
而不是文件会更好吗?)我尝试使用似乎相关的article\index.html
,但这带来了其他问题,例如,在我所有链接的末尾总是带有斜杠:
例如:如果我去exportTrailingSlash
并单击刷新,则(.httaccess?)会在末尾添加一个domain/article/somearticle
,使我/
并不可怕,只是不太干净并且不一致...
编辑: 实际上,这有点可怕,因为有时我们会在结尾加上斜杠,有时我们不在nextjs链接上……必定是某种东西关于我如何使用domain/article/somearticle/
的信息,但我无法弄清楚。
无论如何,我尝试过的<Link />
规则中的每一个都始终成功地删除尾随斜杠...
更多详细信息:
在我的下一个应用中,我有文件夹:
.htaccess
在各个页面中,我使用nextJS Link组件:
/articles/
[slug].js
index.js
答案 0 :(得分:6)
如果您请求/article
并且/article
作为物理目录存在,则Apache的mod_dir(默认情况下)将附加尾部斜杠以“修复” URL。这是通过301永久重定向实现的-因此它将被浏览器缓存。
尽管具有与文件相同的基本名称的物理目录,并使用无扩展名的URL会产生歧义。例如。是/article
访问目录/article/
还是文件/article.html
。无论如何,您似乎都不想允许直接访问目录,因此这似乎可以解决这种歧义。
要防止Apache mod_dir将斜杠附加到目录中,我们需要禁用DirectorySlash
。例如:
DirectorySlash Off
但是如上所述,如果您以前访问过/article
,则到/article/
的重定向将已经被浏览器缓存-因此,您需要先清除浏览器缓存,然后才能生效。
由于要删除文件扩展名,因此还需要确保禁用MultiViews,否则,mod_negotiation将对基础文件发出内部子请求,并可能与mod_rewrite冲突。默认情况下,MultiViews是禁用的,尽管某些共享主机出于某些原因会启用它。从输出中可以看到,它似乎没有启用MultiViews,但是最好确保...
# Ensure that MutliViews is disabled
Options -MultiViews
但是,如果您需要能够访问目录本身,则需要使用内部重写手动附加尾部斜杠。尽管这似乎不是这里的要求。但是,您应该确保禁用目录列表:
# Disable directory listings
Options -Indexes
尝试访问任何目录(最终未映射到文件-参见下文)并且不包含DirectoryIndex
文档,将返回403 Forbidden响应,而不是目录列表。
请注意,在链接到domain/article
的链接,刷新页面和手动键入domain/article
之间,唯一可能出现的区别是浏览器正在缓存 ... 任何中间代理缓存。 (除非您有JavaScript可以拦截锚点上的click事件?!)
您仍然需要将请求从/foo
重写为/foo.html
或将/foo
重写为/foo/index.html
(请参见下文),具体取决于您配置站点的方式。尽管您最好选择其中一个,而不要同时选择两者(就像您可能暗示的那样)。
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}\.html -f RewriteRule ^(.*)$ $1.html
目前还不清楚这对您当前的工作方式如何-除非您看到缓存的响应?当您请求/article
时,第一个条件失败,因为该条件作为物理目录存在并且未处理该规则。即使启用了MultiViews,mod_dir也将具有优先级并附加斜杠。
检查.html
文件是否存在的第二个条件不一定是检查要重写的文件。例如。如果您请求/foo/bar
(其中存在/foo.html
,但是没有物理目录/foo
,则RewriteCond
指令将检查/foo.html
的存在-成功) ,但是请求在内部被重写为/foo/bar.html
(从捕获的RewriteRule
模式)-这导致内部重写循环,并向客户端返回500错误响应。请参见my answer至following ServerFault question,其中会详细介绍此处实际发生的情况。
如果我们假设任何包含看起来像文件扩展名的URL(例如,静态资源.css
,.js
和图像文件)都应被忽略,我们还可以进行进一步的优化,否则我们正在对每个请求执行文件系统检查,这相对昂贵。
因此,为了将/article
格式的请求映射(内部重写)到/article.html
并将/article/somearticle
映射到/article/somearticle.html
像这样:
# Rewrite /foo to /foo.html if it exists
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}.html [L]
在RewriteCond
TestString 中不需要反斜杠转义文字点-此处的点没有特殊含义;它不是正则表达式。
然后,要处理应映射到/foo
的{{1}}格式的请求,您可以执行以下操作:
/foo/index.html
通常,您将允许mod_dir服务# Rewrite /foo to /foo/index.html if it exists
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.html -f
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}/index.html [L]
(例如DirectoryIndex
),但是在目录中省略了斜杠,这可能会出现问题。
将以上几点结合在一起,我们就有:
index.html
这可能会进一步优化,具体取决于您的站点结构以及是否要向# Disable directory indexes and MultiViews
Options -Indexes -MultiViews
# Prevent mod_dir appending a slash to directory requests
DirectorySlash Off
# Rewrite /foo to /foo.html if it exists
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}.html [L]
# Otherwise, rewrite /foo to /foo/index.html if it exists
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.html -f
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}/index.html [L]
文件添加其他指令。例如:
.htaccess
正则表达式。RewriteRule
文件,则重定向到无扩展名URL。如果您同时处理.html
和/foo.html
,则这会变得有些复杂。但这仅在您更改现有URL结构时才真正必要。例如,实现上面的#1和#2,将使指令的编写方式如下:
/foo/index.html
在更改为301(永久)重定向之前,请始终使用302(临时)重定向进行测试,以避免缓存问题。
答案 1 :(得分:0)
- (NextJS在根目录中创建
article\index.html
而不是文件会更好吗?)
是的!接下来为您can do that:
可以将Next.js配置为将页面导出为index.html 文件并且需要尾部斜杠,
/about
变成/about/index.html
并且可以通过/about/
进行路由。这是之前的默认行为 Next.js 9。要返回并添加斜杠,请打开
next.config.js
,然后 启用exportTrailingSlash
配置:
module.exports = { exportTrailingSlash: true, }