Next.js: Rota personalizada `post /` id` piscando 404 antes de finalmente renderizar a página.

Criado em 22 ago. 2017  ·  47Comentários  ·  Fonte: vercel/next.js

No momento, estou tendo um problema com minhas post/:id rotas onde em seguida pisca a página 404 antes de renderizar com sucesso meu componente. A princípio, achei que fosse um problema relacionado ao redux, pois minhas páginas post/id estão verificando o estado do aplicativo para filter qualquer componente que seja mostrado usando o roteamento superficial.

Depois de discutir isso no canal do slack, adicionei outra chamada de API que recuperaria cada postagem do blog, mas rapidamente descobri que ainda encontrava o mesmo problema. Eu sei que isso aconteceu com pelo menos um outro desenvolvedor, então estou me perguntando se alguém pode me indicar a direção certa. Estou tentando terminar este portfólio pessoal que construí a seguir.

Abaixo, você pode ver exatamente o que está acontecendo. Tudo parece A1, exceto o 404 que pisca sempre que uma postagem específica é renderizada.

next.js blog post err

Os benefícios que ganhei são tremendos, no entanto, houve alguns problemas menores como este que me deixaram um pouco confuso 🤔. De qualquer forma, deixe-me saber se posso fornecer alguma informação adicional. Obrigado 😄

Comentários muito úteis

Então, para responder a esta de uma vez por todas:

href => caminho dentro do diretório pages + a querystring
as => renderizado na barra de url do navegador

Exemplo:

Você tem um url chamado /products/:id

  1. Você criou 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. Você adiciona a rota para expressar ou qualquer outro servidor, isso é apenas para SSR. O que isso fará é rotear o url /products/:id para pages/product.js e fornecer id como parte de query em getInitialProps:
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. Para roteamento do lado do cliente, você usa next/link assim:
<Link href="/product?slug=something" as="/products/something"> 

O motivo pelo qual você deve fornecer explicitamente href e as é que Next.js não tem conhecimento de nenhuma outra página no lado do cliente. Não enviamos um manifesto de todas as páginas para o lado do cliente e as rotas subsequentes são carregadas lentamente, o que é escalonável.

Há um pacote de comunidade que abstrai o fornecimento de href e as enviando um manifesto predefinido de todas as rotas, observe que recomendamos não enviar um manifesto completo de todas as rotas possíveis, pois não fazemos isso é mais escalável

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

Além disso, observe que a renderização 404 não é mais o comportamento padrão do Next.js. Em vez disso, recarregamos a página do recurso Zonas.

Todos 47 comentários

Mesmo problema +1

Como você está renderizando o componente Link para esse url? Você está usando <Link href="/post/1"> ou <Link href="/post?id=1" as="/post/1"> ?

Atualmente, estou usando <Link prefetch href={ /blog/${x.id} } /> . Tentei <Link prefetch href={ /blog/${x.id} } as={ /blog/${x.id} } /> no passado e apenas conectei novamente. Ainda tendo o mesmo problema.

Seus href e as props não devem ser os mesmos, href é o url real, se você tiver pages/blog.js e receber o id como uma consulta, então href deve ser /blog?id=${x.id} e as é o seu URL personalizado bonito neste caso /blog/${x.id} .

@sergiodxa Acabei de colocar esse código no lugar.

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

Agora ele está renderizando novamente a página /blog a cada clique, enquanto adiciona id ao URL.

url error gif

@tgrecojs Espero que este trecho de código ajude

    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]}`

Seria renderizado como https://www.someURL.com/journal/articlePath/morePath/evenMorePath

Eu entendo como funciona o caminho @ugiacoman, esse não é o meu problema. Se você pode ver no meu relatório inicial, estou navegando com sucesso para cada postagem do blog, mas o problema é aquele erro estranho 404 .

@tgrecojs Fiz um repo de exemplo https://github.com/sergiodxa/next-custom-query (implantado: https://next-custom-query.now.sh/blog), aí você pode ver como usar o URLs personalizados sem recarregar e um 404 usando o componente next/link conforme descrito acima.

@sergiodxa Agradeço isso! Acabei de conferir e adicionei algumas chamadas assíncronas à API do Google Blogger, que é o que estou fazendo ping no momento. Abaixo, você pode ver como ele está navegando para a rota, mas não está carregando os dados corretamente.

Gif removido

Agora, este problema é uma reprodução ligeiramente diferente deste problema do que o que é mostrado em meu primeiro comentário. Quando me deparei com esse problema pela primeira vez, pensei que era porque estava usando redux e que o estado do aplicativo não estava carregando nas páginas post/id . Isso me levou a integrar uma nova chamada de API para cada postagem, assim como integrei no aplicativo que você criou, porém ainda achei que tinha o mesmo problema.

Eu estava tendo alguns problemas para bifurcar seu repositório, então você pode encontrar meu código aqui -> https://github.com/tgrecojs/next-custom-query-async . Deixe-me saber seus pensamentos! 😄

Parece que você está recebendo um 400, ao bifurcar seu projeto, recebo o mesmo erro com uma mensagem de erro usageLimits. Provavelmente é por isso que você está recebendo esse erro.

OK. Vou investigar um pouco mais amanhã, mas quero salientar que o vídeo que postei ao abrir o problema não está fazendo uma solicitação de API na rota /blog/:id . Em vez disso, ele está filtrando as postagens da minha loja redux que são coletadas na transição da rota /blog , de modo que essa não pode ser a razão pela qual cheguei a esse problema. Eu apenas implementei a segunda chamada de API (feita dentro de blog/:id ) porque pensei que tinha algo a ver com minha loja redux, mas recebi o mesmo erro, mas essa não é a implementação atual em meu código.

Assim que percebi que gerava o mesmo bug, voltei a usar apenas uma chamada de API (Dentro de /blog ) e, em seguida, filtrando a postagem de blog necessária por id.

@sergiodxa Posso confirmar que não se trata de limites de uso. Você verá que id nem sempre está sendo passado corretamente para a rota /blog/:id ... Anexei o erro 400 que estou recebendo. Você verá que id é indefinido e (neste caso) parece ser o motivo pelo qual estou recebendo o erro.

Eu incluí outro vídeo abaixo. Alguma ideia de por que ele pode estar se comportando dessa maneira? Eu não mudei as tags <Link /> dentro deste repositório, mas ainda estou tendo o problema 😬.

next-custom-query err

Mais uma vez, quero ressaltar que o vídeo acima mostra minha reprodução do erro dentro do repositório de exemplo que você criou - https://github.com/sergiodxa/next-custom-query .

Também estou recebendo o 404 piscando sem nenhuma rota personalizada. Apenas um arquivo chamado orders.js em pages/ com este código:

import { Component } from 'react';

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

export default Orders;

Parece um problema bastante crítico 😅

Tentei replicá-lo e é porque a barra final no final do URL, se você for para /orders você não verá o 404, mas se for para /orders/ , você verá que 404 piscando antes do conteúdo, isso acontece no modo de desenvolvimento e produção.

Ah, este é um problema conhecido. https://github.com/zeit/next.js/issues/1189

Meu problema não surgiu devido a uma barra final, então deve haver outra coisa, certo?

Fiz algumas alterações no meu código e implantei 2 versões diferentes, uma usando prefetch e outra que não. Quero observar que nenhum dos aplicativos agora é capaz de carregar com êxito uma rota post/:id .

Com pré-busca - https://tgrecojs-hltqztsjpx.now.sh/

Um notou que quando eu uso prefetch no link, agora ele lança um Page Does Not Exist Error ao renderizar os links para cada postagem do blog. Você pode ver uma captura de tela do meu console abaixo.

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

Sem Prefetch- https://tgrecojs-qzpspdjrin.now.sh/

Quando não uso a pré-busca, o erro mostrado acima não existe mais, mas não renderiza o aplicativo. Quando eu inicialmente postei este problema, meu componente estava inicializando meu blog para cada componente post/:id . Desde então, removi que, desde agora, as mensagens individuais nunca são renderizadas.

Avise-me se puder fornecer mais informações que possam ajudar a diagnosticar esse problema. 🤔

@tgrecojs Tenho quase exatamente o mesmo problema. prefetch não resolveu meu problema.

O comportamento que obtenho é o seguinte:

  • O usuário clica no link
  • Um erro 404 aparece
  • A página recarrega (??)
  • Depois de recarregar, a página correta é exibida

Espero que isso ajude a depurar o problema!

Informação extra: Nó v6.10.3 , Chrome Version 60.0.3112.90

EDITAR: Implantei o aplicativo para que vocês possam testá-lo https://datahub.now.sh/ , é o link / @ [nome de usuário] que tem esse comportamento

@ Theo- o href no próximo / link é user?id=1 , você pode tentar /user?id=1 vez disso? Acho que o 404 é porque Next.js está tentando chegar a /current/path/user?id=1 vez de /user?id=1 , mas quando a página recarrega funciona bem por causa da renderização do servidor.

@sergiodxa foi isso. Obrigado!

@tgrecojs Eu tive o mesmo comportamento 404 de flash. No meu caso, eu tinha um link com uma variável de ambiente que não funcionava no cliente, portanto o 404 mas no servidor funcionava. Resolvido com https://medium.com/the-tech-bench/next-js-environment-variables-d2f6ea1a1dca.

@andreaskeller hmmm ok vou dar uma olhada. obrigado isso !!! No momento, estou usando SOMENTE minhas variáveis ​​.env quando o aplicativo é renderizado pelo servidor. Eu tenho um componente de ordem superior que usa o dotenv para verificar se é CSR ou SSR, se for SSR, despacho a função necessária para registrar as postagens do blog.

sim, eu já tenho minhas variáveis ​​funcionando bem. Estou processando minha rota /blog usando um HOC que obtém minha BLOGGER_API_KEY então está funcionando nesses exemplos .... minhas /post/:id s páginas filhas não estão usando nenhuma variáveis ​​env.

vou fazer mais escavações, espero poder chegar ao fundo disso!

Parece que a maioria dos problemas aqui foram corrigidos. Também vou trabalhar neste problema https://github.com/zeit/next.js/issues/1189

Estou fechando isso agora. Mas se precisarmos fazer algo no núcleo, me avise.

@sergiodxa de acordo com nossa conversa na noite passada, eu criei o aplicativo lil barebones mostrando meu problema. Entre em contato se tiver alguma dúvida. Eu ficaria mais do que feliz em informá-lo sobre tudo o que está acontecendo com ele! 😄

Não está consertado.

eu tenho o mesmo problema, mas sem rotas personalizadas. Eu tenho /pages/pipeline.tsx e / pipeline url funcionam bem enquanto / pipeline / pisca 404 e, em seguida, tenta carregar minha página sem chamar "getInitialProps" chamado (já que era 404 no servidor!).

@ ex3ndr Não tenho certeza se isso resolverá o problema, mas eu tive um problema semelhante e isso o curou.
https://github.com/zeit/next.js#disabling -file-system-routing

O próximo passo é tentar retirar o fileSystem antes que sua rota personalizada seja atingida.

@moaxaca Eu resolvi da mesma maneira, já que precisava ter meu próprio roteamento personalizado - apenas desativei o próximo.

Também estou vendo esse problema. A solução da @moaxaca não funcionou para mim. O que fez foi usar qualquer componente Link , mas em vez disso, optou por usar o método pushRoute próximas rotas.

Exemplo básico:

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>
    )
  }

}

Isso parece resolver e eu não vejo o erro piscando. Mas parece um pouco rápido.

salvar problema

Eu tive o mesmo problema antes e fui capaz de resolvê-lo. Estou usando uma configuração de servidor expresso. Descobri que a razão pela qual a página 404 pisca antes de carregar na página certa é porque meu slug de página não corresponde ao nome do meu componente.

Quando eu tenho esse código, o 404 pisca:

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

Observe que os valores /search e meus actualPage são diferentes.

Os flashes 404 desaparecem quando eu renomeio meu componente e os valores de actualPage para serem os mesmos do slug de minha página, que é search . Veja o código de trabalho abaixo:

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

Agora, ambos estão usando /search .

Desculpe pelos meus ingleses.

pode ser uma boa ideia verificar sua propriedade next.config.js useFileSystemPublicRoutes . Se for falso, isso significa que você mesmo deve definir todos os manipuladores de rota em server.js.

Isso corrige o 404 piscante para mim:

Ligação

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

Lado do servidor

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

Parâmetro de acesso na página

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

Então, para responder a esta de uma vez por todas:

href => caminho dentro do diretório pages + a querystring
as => renderizado na barra de url do navegador

Exemplo:

Você tem um url chamado /products/:id

  1. Você criou 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. Você adiciona a rota para expressar ou qualquer outro servidor, isso é apenas para SSR. O que isso fará é rotear o url /products/:id para pages/product.js e fornecer id como parte de query em getInitialProps:
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. Para roteamento do lado do cliente, você usa next/link assim:
<Link href="/product?slug=something" as="/products/something"> 

O motivo pelo qual você deve fornecer explicitamente href e as é que Next.js não tem conhecimento de nenhuma outra página no lado do cliente. Não enviamos um manifesto de todas as páginas para o lado do cliente e as rotas subsequentes são carregadas lentamente, o que é escalonável.

Há um pacote de comunidade que abstrai o fornecimento de href e as enviando um manifesto predefinido de todas as rotas, observe que recomendamos não enviar um manifesto completo de todas as rotas possíveis, pois não fazemos isso é mais escalável

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

Além disso, observe que a renderização 404 não é mais o comportamento padrão do Next.js. Em vez disso, recarregamos a página do recurso Zonas.

Obrigado Tim, explicação totalmente clara!

@timneutkens
Se o link é href e como. Eu passo o valor diferente. Como poderia obter o href e o valor de as .
Eu testo minha demonstração. Acho que req.params.slug será o as . Então, como eu poderia obter o href .

@timneutkens Você me salvou, não sei quantas horas de pesquisa dolorosa pelo meu problema: D

Como você está renderizando o componente Link para esse url? Você está usando <Link href="/post/1"> ou <Link href="/post?id=1" as="/post/1"> ?

Você deve colocar isso no doc. :alegria:

@sergiodxa

Então, para responder a esta de uma vez por todas:

href => caminho dentro do diretório pages + a querystring
as => renderizado na barra de url do navegador

Exemplo:

Você tem um url chamado /products/:id

  1. Você criou 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. Você adiciona a rota para expressar ou qualquer outro servidor, isto é _somente_ para SSR. O que isso fará é rotear o url /products/:id para pages/product.js e fornecer id como parte de query em getInitialProps:
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. Para roteamento do lado do cliente, você usa next/link assim:
<Link href="/product?slug=something" as="/products/something"> 

O motivo pelo qual você deve fornecer explicitamente href e as é que Next.js não tem conhecimento de nenhuma outra página no lado do cliente. Não enviamos um manifesto de todas as páginas para o lado do cliente e as rotas subsequentes são carregadas lentamente, o que é escalonável.

Há um pacote de comunidade que abstrai o fornecimento de href e as enviando um manifesto predefinido de todas as rotas, observe que recomendamos não enviar um manifesto completo de todas as rotas possíveis, pois não fazemos isso é mais escalável

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

Além disso, observe que a renderização 404 não é mais o comportamento padrão do Next.js. Em vez disso, recarregamos a página do recurso Zonas.

o que posso fazer se tiver apenas uma matriz de cabeçalhos de lista como:
[ home: '/home', about:'/about', post: 'post/:post_id?' ] .
No próximo, recebo apenas as's value, mas que tal href ? Obrigado: D

E se você estiver usando router.push() vez de <Link> como pode obter os mesmos resultados?

@justinmchase Acabei de ter o mesmo problema. Verifique a documentação do Next Router , caso ainda não o tenha feito.

Você pode usá-lo como Router.push(url, as, options) :

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

@timneutkens Eu gostaria de hospedar meu aplicativo next.js em ZEIT.now, mas ele não tem a opção de executar um servidor expresso. Perco meus lindos urls agora e só posso fazer param=value&param=value ou há outra maneira? O exemplo que Sergio postou não parece promissor

Tentei rotas dinâmicas, mas agora meu aplicativo de página única está quebrado e links como:

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

agora causa uma recarga de página inteira porque http: // localhost : 8080 / _next / static / development / pages / integration.js retorna um 404 não encontrado.

@timneutkens Eu gostaria de hospedar meu aplicativo next.js em ZEIT.now, mas ele não tem a opção de executar um servidor expresso. Perco meus lindos urls agora e só posso fazer param=value&param=value ou há outra maneira? O exemplo que Sergio postou não parece promissor

Você não precisa de um servidor personalizado para rotas dinâmicas, consulte https://nextjs.org/docs/routing/dynamic-routes

@timneutkens Obrigado por sua resposta rápida, eu tentei rotas dinâmicas, mas vou quebrar o aplicativo de página única (ver atualização). Executando localmente com next em meu script package.json no modo dev.

Resolvido tendo pages/integration/index.js com o código e pages/integration/[slug].js com:

import ProductDetailPage from './index'
export default ProductDetailPage

A maneira correta de fazer o que você descreveu é criar pages/integration/[slug].js

E vincule-o desta forma:

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

Olá, posso perguntar por que quando ligo para este

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

o id não pode ser recuperado, e a página que estou usando é [... index] .js que é uma página multi-dinâmica "pega-tudo", mas se eu direcionar para outra página que não seja dinâmica, ela pode funcionar corretamente. exemplo car.js push to Vehicle.js ..
Existe uma maneira melhor de enviar para minha página de captura dinâmica e, em seguida, mascarar o id e ainda ser capaz de recuperá-lo ..?

Esta página foi útil?
0 / 5 - 0 avaliações