你如何处理 next.js 路由中的尾部斜杠?
How can you handle trailing slashes in next.js routes?
我正在尝试设置一个 next.js 应用程序,但我在处理带有尾部斜线的路由时遇到了问题。因此,例如,如果我有这样的页面结构:
pages
- index.js
- blog
- index.js
- [slug].js
然后去 /
给我基础 index.js
,去 /blog
给我 blog/index.js
,去 /blog/my-post
给我 blog/[slug].js
— 到目前为止一切顺利。
但是转到 /blog/
给我一个 404 错误,如果不完全更换 next.js 路由器,似乎根本没有办法处理这个问题——我什至无法重定向 /blog/
到 /blog
。有什么办法解决这个问题,还是我需要一个自定义路由器?有没有办法扩展 next.js 路由器,让我可以处理这些问题,而无需完全替换它?
更新:如果您使用的是 next export
,则可以通过将 exportTrailingSlash
添加到 next.config.js
来解决问题
截至撰写本文时,如果不定义您自己的自定义服务器,似乎无法解决此问题。
上一个回答:
您必须创建一个新文件 blog.js
,如下所示:
与以下server.js
const express = require('express')
const next = require('next')
const PORT = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app
.prepare()
.then(() => {
const server = express()
server.get('/blog', (req, res) => {
const actualPage = '/blog'
// const queryParams = { title: req.params.id }
app.render(req, res, '/blog', {})
})
server.get('/blog/:id', (req, res) => {
const actualPage = '/blog/[id]'
const queryParams = { title: req.params.id }
app.render(req, res, actualPage, queryParams)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(PORT, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${PORT}`)
})
})
.catch(ex => {
console.error(ex.stack)
process.exit(1)
})
node server.js
应该会启动您的服务器,您将拥有所需的映射。
注意,本例中未使用blog/index.js
。
我没有办法解决这个问题。这仍然是一个巨大的问题。但是,我确实有一个非常可怕的技巧,我一直在使用它来解决 Next.js 9.x.x
中的这个问题
在我的 /pages/_error.js
中,我添加了以下代码:
FourOhFour.getInitialProps = ({asPath, res}: any): any => {
if (asPath.endsWith('/')) {
res.writeHead(301, {Location: asPath.substring(0, asPath.length - 1)});
return res.end();
}
return {};
};
这将确保所有以尾部斜杠结尾的路由都通过 301 重定向重定向到非尾部斜杠路径。
您可以将此添加到您的 _app.js
文件
MyApp.getInitialProps = async ctx => {
const pathAndQueryDivided = ctx.ctx.req.url.split('?');
if (pathAndQueryDivided[0].endsWith('/')) {
const urlWithoutEndingSlash = pathAndQueryDivided[0].replace(/\/*$/gim, '');
ctx.ctx.res.writeHead(301, {
Location: urlWithoutEndingSlash + (pathAndQueryDivided.length > 1 ? `?${pathAndQueryDivided[1]}` : ''),
});
ctx.ctx.res.end();
return {};
}
const initialProps = await App.getInitialProps(ctx);
return {
...initialProps,
};
};
- App.getInitialProps 首先在服务器端被调用
- 它将路径和查询参数分开,因为我们只想知道 url 是否以斜线结尾
- 询问 url 是否以斜线结尾
- 它将 url 的最后一个斜线替换为空
- 它会将您重定向到 url 没有斜杠 + 查询参数(如果有的话)
我已经通过为我的生产应用程序使用 nginx 完成了重定向:
rewrite ^(.+)/+$ permanent;
有 Next.js 9.5
及以上的选项。
在 next.config.js
中,添加 trailingSlash
配置:
module.exports = {
trailingSlash: true,
}
我正在尝试设置一个 next.js 应用程序,但我在处理带有尾部斜线的路由时遇到了问题。因此,例如,如果我有这样的页面结构:
pages
- index.js
- blog
- index.js
- [slug].js
然后去 /
给我基础 index.js
,去 /blog
给我 blog/index.js
,去 /blog/my-post
给我 blog/[slug].js
— 到目前为止一切顺利。
但是转到 /blog/
给我一个 404 错误,如果不完全更换 next.js 路由器,似乎根本没有办法处理这个问题——我什至无法重定向 /blog/
到 /blog
。有什么办法解决这个问题,还是我需要一个自定义路由器?有没有办法扩展 next.js 路由器,让我可以处理这些问题,而无需完全替换它?
更新:如果您使用的是 next export
,则可以通过将 exportTrailingSlash
添加到 next.config.js
截至撰写本文时,如果不定义您自己的自定义服务器,似乎无法解决此问题。
上一个回答:
您必须创建一个新文件 blog.js
,如下所示:
与以下server.js
const express = require('express')
const next = require('next')
const PORT = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app
.prepare()
.then(() => {
const server = express()
server.get('/blog', (req, res) => {
const actualPage = '/blog'
// const queryParams = { title: req.params.id }
app.render(req, res, '/blog', {})
})
server.get('/blog/:id', (req, res) => {
const actualPage = '/blog/[id]'
const queryParams = { title: req.params.id }
app.render(req, res, actualPage, queryParams)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(PORT, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${PORT}`)
})
})
.catch(ex => {
console.error(ex.stack)
process.exit(1)
})
node server.js
应该会启动您的服务器,您将拥有所需的映射。
注意,本例中未使用blog/index.js
。
我没有办法解决这个问题。这仍然是一个巨大的问题。但是,我确实有一个非常可怕的技巧,我一直在使用它来解决 Next.js 9.x.x
中的这个问题在我的 /pages/_error.js
中,我添加了以下代码:
FourOhFour.getInitialProps = ({asPath, res}: any): any => {
if (asPath.endsWith('/')) {
res.writeHead(301, {Location: asPath.substring(0, asPath.length - 1)});
return res.end();
}
return {};
};
这将确保所有以尾部斜杠结尾的路由都通过 301 重定向重定向到非尾部斜杠路径。
您可以将此添加到您的 _app.js
文件
MyApp.getInitialProps = async ctx => {
const pathAndQueryDivided = ctx.ctx.req.url.split('?');
if (pathAndQueryDivided[0].endsWith('/')) {
const urlWithoutEndingSlash = pathAndQueryDivided[0].replace(/\/*$/gim, '');
ctx.ctx.res.writeHead(301, {
Location: urlWithoutEndingSlash + (pathAndQueryDivided.length > 1 ? `?${pathAndQueryDivided[1]}` : ''),
});
ctx.ctx.res.end();
return {};
}
const initialProps = await App.getInitialProps(ctx);
return {
...initialProps,
};
};
- App.getInitialProps 首先在服务器端被调用
- 它将路径和查询参数分开,因为我们只想知道 url 是否以斜线结尾
- 询问 url 是否以斜线结尾
- 它将 url 的最后一个斜线替换为空
- 它会将您重定向到 url 没有斜杠 + 查询参数(如果有的话)
我已经通过为我的生产应用程序使用 nginx 完成了重定向:
rewrite ^(.+)/+$ permanent;
有 Next.js 9.5
及以上的选项。
在 next.config.js
中,添加 trailingSlash
配置:
module.exports = {
trailingSlash: true,
}