Next.js: 自定义路由 `post/`id` 在最终渲染页面之前闪烁 404。

创建于 2017-08-22  ·  47评论  ·  资料来源: vercel/next.js

我目前遇到我的post/:id路由问题,在成功渲染我的组件之前,接下来会闪烁404页面。 起初,我认为这是与 redux 相关的问题,因为我的post/id页面正在将应用程序状态检查为filter应使用浅层路由显示的任何组件。

在 slack 频道中讨论了这个之后,我添加了另一个 API 调用来检索每篇博文,但很快发现我仍然遇到了同样的问题。 我知道这至少发生在另一位开发人员身上,所以我想知道是否有人可以指出我正确的方向? 我正在尝试完成我接下来建立的这个个人投资组合。

在下面,您可以确切地看到正在发生的事情。 除了在渲染特定帖子时闪烁的 404 之外,一切看起来都是 A1。

next.js blog post err

我获得的好处是巨大的,但是有一些像这样的小问题让我有点困惑🤔。 无论如何,如果我可以提供任何其他信息,请告诉我。 谢谢😄

最有用的评论

所以一劳永逸地回答这个问题:

href => pages目录内的路径 + 查询字符串
as => 在浏览器 url 栏中呈现

例子:

您有一个名为/products/:id的网址

  1. 您创建了pages/product.js
export default class extends React.Component {
  static async getInitialProps({query}) {
    console.log('SLUG', query.slug)
    return {}
  }
  render() {
    return <h1>The product page</h1>
  }
}
  1. 您将路由添加到 express 或任何其他服务器,这适用于 SSR。 这将做的是将 url /products/:id路由到pages/product.js并在 getInitialProps 中提供id作为query的一部分:
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. 对于客户端路由,您使用next/link像这样:
<Link href="/product?slug=something" as="/products/something"> 

您必须明确提供hrefas是 Next.js 不知道客户端的任何其他页面。 我们不会将所有页面的清单发送到客户端,后续路由会延迟加载,这是可扩展的。

有一个社区包通过发送所有路由的预定义清单来抽象提供hrefas ,请注意,我们建议不要发送所有可能路由的完整清单,因为不要这样做更具可扩展性

https://github.com/fridays/next-routes

另请注意,渲染 404 不再是 Next.js 的默认行为。 相反,我们重新加载区域功能的页面。

所有47条评论

同样的问题 +1

您如何将链接组件呈现到该网址? 您使用的是<Link href="/post/1">还是<Link href="/post?id=1" as="/post/1">

目前,我正在使用<Link prefetch href={ /blog/${x.id} } /> 。 我过去试过<Link prefetch href={ /blog/${x.id} } as={ /blog/${x.id} } />并再次插入。 仍然有同样的问题。

您的hrefas道具不应该相同, href是真正的网址,如果您有pages/blog.js并接收 id 作为查询,则href应该是/blog?id=${x.id}并且as在这种情况下是您漂亮的自定义网址/blog/${x.id}

@sergiodxa我只是把这段代码放在适当的位置。

<Link href={`/blog?id=${x.id}`} as={`blog/${x.id}`}>
    <a>Read Post</a>
 </Link>

现在它在每次点击时重新呈现/blog页面,同时将id到 URL。

url error gif

@tgrecojs希望这个代码片段有帮助

    const href = `/journal?home=${this.state.article.path[0]}&articlePath=${this.state.article.path[1]}&file=${this.state.article.path[2]}`
    const as = `/journal/${this.state.article.path[0]}/${this.state.article.path[1]}/${this.state.article.path[2]}`

将呈现为https://www.someURL.com/journal/articlePath/morePath/evenMorePath

我了解路径的工作方式@ugiacoman这不是我的问题。 如果您可以在我的初始报告中看到,我已成功导航到每篇博客文章,但问题在于奇怪的404错误。

@tgrecojs我做了一个示例 repo https://github.com/sergiodxa/next-custom-query (部署:https: //next-custom-query.now.sh/blog ),在那里你可以看到如何使用无需重新加载的自定义 url 和使用next/link组件的 404,如上所述。

@sergiodxa我很感激! 我刚刚检查了一下,并向谷歌博客 API 添加了一些异步调用,这就是我目前正在 ping 的内容。 在下面,您可以看到它如何导航到路线,但没有正确加载数据。

删除了 gif

现在这个问题与我在第一条评论中显示的内容略有不同。 当我第一次遇到这个问题时,我认为这是因为我使用的是 redux 并且应用程序状态没有传递到post/id页面。 这导致我为每个帖子集成了一个新的 API 调用,就像我集成到您创建的应用程序中一样,但是我仍然发现我遇到了同样的问题。

我在 fork 你的 repo 时遇到了一些麻烦😬,所以你可以在这里找到我的代码 -> https://github.com/tgrecojs/next-custom-query-async 。 让我知道你的想法! 😄

看起来你得到了 400,当 fork 你的项目时,我得到了同样的错误和一个 usageLimits 错误消息。 这可能就是您收到该错误的原因。

好的。 明天我会进一步调查,但我想指出我在打开问题时发布的视频没有在/blog/:id路由上发出 API 请求。 相反,它从我的 redux 商店中过滤了在/blog路由转换中收集的帖子,所以这不是我遇到这个问题的原因。 我只实现了第二个 API 调用(在blog/:id ),因为我认为它与我的 redux-store 有关系,但发现自己收到了相同的错误,但这不是我代码中的当前实现。

一旦我意识到它抛出了同样的错误,我就切换回只使用一个 API 调用(在/blog ),然后通过 id 过滤必要的博客文章。

@sergiodxa我可以确认这不是使用限制。 你会看到id并不总是被正确地传递到/blog/:id路由......我附上了我收到的400错误。 您会看到id未定义,并且(在这种情况下)这似乎是我收到错误的原因。

我在下面添加了另一个视频。 关于为什么它可能会以这种方式行事的任何想法? 我还没有更改此存储库中的<Link />标签,但仍然存在问题 😬 。

next-custom-query err

再次,我想指出,上面的视频显示了我在您创建的示例存储库中重现错误 - https://github.com/sergiodxa/next-custom-query

我也在没有任何自定义路由的情况下收到 404 闪烁。 只是一个名为orders.jspages/ ,代码如下:

import { Component } from 'react';

class Orders extends Component {
  render() {
    return (
      <div>
        <h2>My Orders</h2>
      </div>
    )
  }
}

export default Orders;

看起来是个很关键的问题😅

我试图复制它,因为 URL 末尾的斜杠,如果你去/orders你看不到 404 但如果你去/orders/然后你看到那个404 在内容之前闪烁,这在开发和生产模式下都会发生。

啊这是一个已知问题。 https://github.com/zeit/next.js/issues/1189

我的问题不是由于尾随斜杠引起的,所以一定有别的东西,对吧?

我对代码进行了一些更改,并部署了 2 个不同的版本,一个使用prefetch ,一个不使用。 我想指出的是,这两个应用程序现在都无法成功加载post/:id路由。

使用预取 - https://tgrecojs-hltqztsjpx.now.sh/

有人注意到,当我在链接中使用prefetch时,它现在在呈现每个博客文章的链接时会抛出一个Page Does Not Exist Error 。 您可以在下面看到我的控制台的屏幕截图。

screen shot 2017-08-26 at 1 06 25 pm

没有预取 - https://tgrecojs-qzpspdjrin.now.sh/

当我不使用预取时,上面显示的错误不再存在,但它不会呈现应用程序。 当我最初发布此问题时,我的组件正在为每个post/:id组件初始化我的博客。 我已经删除了,因为现在个人帖子永远不会呈现。

如果我可以提供更多信息来帮助诊断此问题,请告诉我。 🤔

@tgrecojs我有几乎完全相同的问题。 prefetch没有解决我的问题。

我得到的行为如下:

  • 用户点击链接
  • 出现 404 错误
  • 页面重新加载 (??)
  • 重新加载后,显示正确的页面

我希望这可以帮助调试问题!

额外信息:节点v6.10.3 ,Chrome Version 60.0.3112.90

编辑:部署应用程序,以便你们可以测试它https://datahub.now.sh/ ,它是具有此行为的链接 /@[username]

@Theo- 下一个/链接中的 href 是user?id=1 ,你可以试试/user?id=1吗? 我认为 404 是因为 Next.js 试图访问/current/path/user?id=1而不是/user?id=1 ,但是当页面重新加载时,由于服务器渲染它工作正常。

@sergiodxa做到了。 谢谢!

@tgrecojs我有相同的闪烁 404 行为。 在我的例子中,我有一个环境变量的链接,它在客户端上不起作用,因此 404 但在服务器上,它起作用了。 用https://medium.com/the-tech-bench/next-js-environment-variables-d2f6ea1a1dca解决了这个问题

@andreaskeller嗯,好的,我去看看。 谢谢这个!!! 当应用程序是服务器渲染时,我目前只使用我的 .env 变量。 我有一个更高阶的组件,它使用 dotenv 来检查它是 CSR 还是 SSR,如果是 SSR,则我会调度记录博客文章所需的函数。

是的,我已经让我的变量工作正常。 我正在使用 HOC 渲染我的/blog路由,该 HOC 获取我的BLOGGER_API_KEY所以它在这些示例中工作......我的/post/:id s 子页面没有使用任何环境变量。

要做更多的挖掘,希望我能找到它的底部!

似乎这里的大多数问题都已解决。 我也会处理这个问题https://github.com/zeit/next.js/issues/1189

我现在关闭这个。 但是,如果我们需要在核心中做一些事情,请告诉我。

@sergiodxa根据我们昨晚的谈话,我创建了显示我的问题的 lil 准系统应用程序。 如果您对此有任何疑问,请告诉我! 我很乐意向您介绍正在发生的一切! 😄

它不是固定的。

我有同样的问题,但没有任何自定义路线。 我有 /pages/pipeline.tsx 和 /pipeline url 工作得很好,而 /pipeline/ 闪烁 404 然后尝试加载我的页面而不调用“getInitialProps”(因为它在服务器上是 404!)。

@ex3ndr不确定这是否能解决问题,但我遇到了类似的问题,这解决了它。
https://github.com/zeit/next.js#disabling -file-system-routing

接下来的机会是尝试在自定义路由被命中之前关闭文件系统。

@moaxaca我已经解决了同样的问题,因为我需要拥有自己的自定义路由 - 我只是完全禁用了 next 的路由。

我也看到这个问题。 @moaxaca的解决方案对我不起作用。 所做的是使用任何Link组件,而是选择使用 next-routes 的pushRoute方法。

基本示例:

import { connect } from 'react-redux'
import { Router } from '../routes'

// ----

export default class Link extends React.Component {

  handleClick(evt, url) {
    evt.preventDefault()    
    Router.pushRoute(url)
  }

  render() {
    const { url, title } = this.props

    return (
      <a href={ url} onClick={ (evt) => this.handleClick(evt, url) }>{title}</a>
    )
  }

}

这似乎解决了,我没有看到错误闪烁。 但是感觉有点快。

保存问题

我之前遇到过同样的问题,我能够解决它。 我正在使用快速服务器设置。 我发现404页面在加载到正确页面之前闪烁的原因是因为我的页面slug与我的组件名称不匹配。

当我有这个代码时,404 闪烁:

server.get('/search', (req, res) => {
    const actualPage = '/search_results'
    const queryParams = { filters: req.query }
    app.render(req, res, actualPage, queryParams)
  })

请注意, /search和我的actualPage值是不同的。

当我重命名我的组件和actualPage值与我的页面 slug 相同时,404 闪烁消失了search 。 请参阅下面的工作代码:

server.get('/search', (req, res) => {
    const actualPage = '/search'
    const queryParams = { filters: req.query }
    app.render(req, res, actualPage, queryParams)
  })

现在两者都在使用/search

对不起我的英国人。

检查您的next.config.js useFileSystemPublicRoutes财产可能是个好主意。 如果为 false,则意味着您必须自己在 server.js 中定义所有路由处理程序。

这为我修复了闪烁的 404:

关联

<Link href="/somepage?id=value" as="/somepage/value">

服务器端

server.get("/somepage/:id", (req, res) => {
  return app.render(req, res, "/maps", { id: req.params.id })
})

页面访问参数

const { id } = this.props.url.query

所以一劳永逸地回答这个问题:

href => pages目录内的路径 + 查询字符串
as => 在浏览器 url 栏中呈现

例子:

您有一个名为/products/:id的网址

  1. 您创建了pages/product.js
export default class extends React.Component {
  static async getInitialProps({query}) {
    console.log('SLUG', query.slug)
    return {}
  }
  render() {
    return <h1>The product page</h1>
  }
}
  1. 您将路由添加到 express 或任何其他服务器,这适用于 SSR。 这将做的是将 url /products/:id路由到pages/product.js并在 getInitialProps 中提供id作为query的一部分:
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. 对于客户端路由,您使用next/link像这样:
<Link href="/product?slug=something" as="/products/something"> 

您必须明确提供hrefas是 Next.js 不知道客户端的任何其他页面。 我们不会将所有页面的清单发送到客户端,后续路由会延迟加载,这是可扩展的。

有一个社区包通过发送所有路由的预定义清单来抽象提供hrefas ,请注意,我们建议不要发送所有可能路由的完整清单,因为不要这样做更具可扩展性

https://github.com/fridays/next-routes

另请注意,渲染 404 不再是 Next.js 的默认行为。 相反,我们重新加载区域功能的页面。

谢谢蒂姆,完全清楚的解释!

@timneutkens
如果链接的 href 和 as。 我传递了不同的值。 我怎么能得到href的价值和as的价值。
我测试我演示。 我认为 req.params.slug 将是as的价值。 那我怎么能得到href的价值。

@timneutkens你救了我我不知道我的问题有多少小时的痛苦搜索:D

您如何将链接组件呈现到该网址? 您使用的是<Link href="/post/1">还是<Link href="/post?id=1" as="/post/1">

你应该把它放在文档中。 :喜悦:

@sergiodxa

所以一劳永逸地回答这个问题:

href => pages目录内的路径 + 查询字符串
as => 在浏览器 url 栏中呈现

例子:

您有一个名为/products/:id的网址

  1. 您创建了pages/product.js
export default class extends React.Component {
  static async getInitialProps({query}) {
    console.log('SLUG', query.slug)
    return {}
  }
  render() {
    return <h1>The product page</h1>
  }
}
  1. 您将路由添加到 express 或任何其他服务器,这是 _only_ 用于 SSR。 这将做的是将 url /products/:id路由到pages/product.js并在 getInitialProps 中提供id作为query的一部分:
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. 对于客户端路由,您使用next/link像这样:
<Link href="/product?slug=something" as="/products/something"> 

您必须明确提供hrefas是 Next.js 不知道客户端的任何其他页面。 我们不会将所有页面的清单发送到客户端,后续路由会延迟加载,这是可扩展的。

有一个社区包通过发送所有路由的预定义清单来抽象提供hrefas ,请注意,我们建议不要发送所有可能路由的完整清单,因为不要这样做更具可扩展性

https://github.com/fridays/next-routes

另请注意,渲染 404 不再是 Next.js 的默认行为。 相反,我们重新加载区域功能的页面。

如果我只有一个列表标题数组,我可以做什么:
[ home: '/home', about:'/about', post: 'post/:post_id?' ]
接下来我只得到as's值,但是href怎么样? 感谢:D

如果您使用router.push()而不是<Link>怎么办,您如何获得相同的结果?

@justinmchase我刚刚遇到了同样的问题。 如果您还没有,请查看Next Router文档。

您可以将其用作Router.push(url, as, options)

Router.push('/post/[pid]', '/post/abc')

@timneutkens我想在 ZEIT.now 上托管我的 next.js 应用程序,但它没有运行快速服务器的选项。 我现在是否丢失了漂亮的网址并且只能执行param=value&param=value还是有其他方法? 塞尔吉奥发布的例子看起来并不乐观

我尝试了动态路由,但现在我的单页应用程序已损坏,链接如下:

<Link href={`/integration?slug=${slug}`} as={`/integration/${slug}`}>

现在导致整页重新加载,因为http://localhost :8080/_next/static/development/pages/integration.js 返回 404 not found。

@timneutkens我想在 ZEIT.now 上托管我的 next.js 应用程序,但它没有运行快速服务器的选项。 我现在是否丢失了漂亮的网址并且只能执行param=value&param=value还是有其他方法? 塞尔吉奥发布的例子看起来并不乐观

动态路由不需要自定义服务器,请参阅https://nextjs.org/docs/routing/dynamic-routes

@timneutkens感谢您的快速回复,我尝试了动态路由,但会破坏单页应用程序(请参阅更新)。 在开发模式下在我的 package.json 脚本中使用next在本地运行。

通过使用带有代码的pages/integration/index.js和带有以下代码的pages/integration/[slug].js了这个问题:

import ProductDetailPage from './index'
export default ProductDetailPage

执行您概述的正确方法是创建pages/integration/[slug].js

并以这种方式链接到它:

<Link href={`/integration/[slug]`} as={`/integration/${slug}`}>

嗨,我能问一下为什么当我打电话给这个时吗

Router.push( '/about?id=1234','/about')

无法检索 ID,我使用的页面是 [...index].js,这是一个多动态捕获所有页面,但如果我指向其他非动态页面,它可以正常工作,例如 car.js推送到 Vehicle.js..
有没有更好的方法,我可以推送到我的动态捕获所有页面,然后屏蔽 ID 并仍然能够检索它..?

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

irrigator picture irrigator  ·  3评论

rauchg picture rauchg  ·  3评论

olifante picture olifante  ·  3评论

knipferrc picture knipferrc  ·  3评论

kenji4569 picture kenji4569  ·  3评论