你如何处理 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,
}

来源:Trailing Slash