Fetch | Next.js
-
Fetch | Next.js
-
Uso correto é no lado do Cliente
Obtendo o próprio endpoint da API em React Server Components
Como parte da busca de dados, estou buscando os dados de minhas próprias rotas de API ou manipuladores de rotas com um fetchcomponente interno de servidor como este:
export default async function Page() {
const res = await fetch("http://localhost:3000/api/user?uid=123456");
const user = await res.json();
return <div>{user?.name}</div>;
}
Embora isso funcione bem no modo dev, ele falha ao construir. Também tive que usar uma URL absoluta em vez de uma URL relativa mais agradável. Por que isso? Essa é a maneira correta de buscar dados?
Não, esta não é a maneira correta de buscar dados em componentes de servidor. Resumindo, não busque suas próprias rotas de API ou manipuladores de rota (de agora em diante, apenas "manipuladores de rota") em componentes de servidor, em vez disso, apenas chame a lógica do lado do servidor diretamente. Imagine componentes de servidor não como componentes React normais, mas como o bom e velho getStaticPropsand getServerSideProps. Em vez do código acima, você deve fazer algo assim:
import { prisma } from "~/lib/prisma";
export default async function Page() {
const user = await prisma.user.findUnique({ where: { id: 123456 } });
return <div>{user?.name}</div>;
}
Se você precisar buscar localhost:3000em seu próprio aplicativo Next.js (supondo que esse aplicativo Next.js seja executado na porta 3000) e a busca exigir uma URL absoluta, é bem provável que você esteja fazendo algo errado .
Se você se preocupa com autenticação ou coisas semelhantes, cookiese headersfor útil.
Os manipuladores de rota devem ser usados para busca do lado do cliente, interações com outros serviços/aplicativos, etc. Se você perceber que está repetindo código no componente do servidor e no manipulador de rota, você pode extrair o código comum em uma função de utilitário separada (por exemplo, getUser(id: number): User | null) e importá-lo em ambos os lugares.
Claro, isso só se aplica a componentes de servidor. Em componentes de cliente, você pode buscar seus próprios manipuladores de rota normalmente com swror react-query(veja também esta pergunta ). Dito isso, recomendamos que você use ações de servidor para mutações, porque elas se integram muito bem com o roteador React usado pelo appdiretório.
Agora continue lendo para ver por que fetchusar a instrução -ing nos manipuladores de rota em componentes do servidor é uma má ideia.
Por que são necessários URLs absolutos?
fetchno lado do cliente não requer URLs absolutas, porque o navegador sabe a URL da página atual e, portanto, pode entender qual host/domínio usar. Mas, em componentes do servidor, a busca é executada no servidor, o que é como executar um fetchscript Node.js dentro do seu próprio computador. Ele não sabe qual host/domínio usar (você não sabe o domínio do seu computador, sabe?), então você tem que especificá-lo explicitamente.
Por que não funciona durante a construção? Por que funciona no modo dev?
Ele requer que o servidor esteja em execução em (no exemplo acima) localhost:3000. Isso é cumprido durante o modo de desenvolvimento e durante o tempo de execução ( next start), então o fetch funciona bem lá. Mas durante a construção, o servidor não está em execução, então o fetch falha.
Por que a documentação descreve fetchcomponentes internos do servidor então? Para quê?
Para comunicação com um serviço de backend separado ( api.yourapp.com) ou uma API de terceiros ( api.thirdparty.com).
Quais são as desvantagens dessa abordagem?
A desvantagem mais evidente da abordagem é que ela não funciona (veja acima). Mas e se funcionasse , ou se você só a usasse nos cenários limitados em que funciona? Quais são as desvantagens então?
- O fetch não tem acesso a cabeçalhos e cookies automaticamente. Você precisa extrair manualmente as informações relevantes com
headersecookiese passá-las para afetchchamada. - Não é seguro para tipos. Nos exemplos acima, se você usar
fetch, já que o componente do servidor não sabe nada sobre o que seria respondido pelo manipulador de rotas, o tipo tem que seranye você tem que verificar/validar manualmente o tipo da resposta. Mas se você usar algo como Prisma com componentes do servidor diretamente como acima, o tipo fica disponível automaticamente (então você sabe se algo pode sernullou se você não errou de digitaçãouser.nameemuser.nmae). - Se você se auto-hospedar, é mais lento, embora apenas muito, muito ligeiramente. É essencialmente seu servidor buscando dados de si mesmo, enquanto finge ser um servidor separado. A sobrecarga adicionada por essa pretensão é pequena, mas está lá.
- Se você hospedar o aplicativo Next.js no Vercel ou em uma plataforma serverless similar, é provável que ele seja significativamente mais lento. Pelo menos para o caso do Vercel, seus manipuladores de rota e componentes dinâmicos do servidor são implantados no AWS Lambda, o que pode exigir uma inicialização a frio se o lambda não for usado por um tempo. Não sabemos como o Vercel agrupa os manipuladores de rota e os componentes do servidor em diferentes lambdas, mas se seu manipulador de rota precisar de uma inicialização a frio quando você solicitar o componente do servidor, você estará assumindo essa penalidade de inicialização a frio que poderia ter sido evitada se você não tivesse usado um manipulador de rota em primeiro lugar.
- Não traz nenhum benefício. Os componentes do servidor são executados exclusivamente no servidor de qualquer forma, você não precisa se preocupar com vazamento de lógica/variáveis do lado do servidor para o navegador.
- Você estaria atirando no próprio pé e no de outros futuros mantenedores. Isso geralmente é uma má ideia.
Outras anotações
