Next.js: Melhorias de geração estática / SSG

Criado em 25 nov. 2019  ·  250Comentários  ·  Fonte: vercel/next.js

Resumo

Permita que Next.js se torne totalmente híbrido, fornecendo métodos para fazer geração estática e renderização do lado do servidor por página.

  • Dois novos métodos de busca de dados por página

    • getStaticProps - Aceite a geração estática (SSG) no momento next build .

    • getServerSideProps - Opte pela renderização do lado do servidor (SSR), que renderiza sob demanda.

  • Um novo método para gerar estaticamente (SSG) um conjunto de rotas de fontes dinâmicas

    • getStaticPaths - Lista de retorno de parâmetros para rotas dinâmicas para fazer geração estática (SSG)

Este RFC discute exclusivamente adições de API. Todas as novas funcionalidades são totalmente compatíveis com as versões anteriores e podem ser adotadas de forma incremental. Este RFC não apresenta depreciações.

Fundo

Ao criar sites ou aplicativos da web, você geralmente deve escolher entre 2 estratégias: geração estática (SSG) ou renderização do lado do servidor (SSR).

Em vez disso, o Next.js permite que você crie aplicativos híbridos que permitem escolher por página qual estratégia é usada. Começando com Next.js 9, as páginas sem getInitialProps são estaticamente otimizadas e geradas como .html arquivos em next build .

No entanto, você pode querer fazer a busca de dados enquanto gera páginas estáticas para seu caso de uso específico.

Por exemplo, para gerar páginas de marketing estaticamente a partir de um CMS ou de uma seção de blog do site.

O uso de getInitialProps optaria pelo SSR nesse caso.

Next.js atualmente possui um comando next export , que torna o aplicativo totalmente SSG, perdendo a natureza híbrida do Next.js.

Se você usar next export com getInitialProps há outro problema que surge. getInitialProps é chamado no momento da compilação (o que é ótimo), mas quando você usa next/link para mover entre as páginas getInitialProps é chamado do lado do cliente, em vez de usar o next export resultado.

Isso também significa que a fonte de dados (ponto de extremidade CMS / API) é chamada diretamente nas transições do lado do cliente; se sua fonte de dados estiver inativa, as transições do lado do cliente serão interrompidas durante a movimentação entre as páginas.

Colaboramos com usuários pesados ​​de SSG e next export em Next.js como HashiCorp (obrigado @jescalan) e investigamos exaustivamente as restrições certas para a introdução de dois novos métodos de busca de dados: getStaticProps e getServerSideProps . Mas também uma maneira de fornecer parâmetros para gerar páginas estáticas para rotas dinâmicas: getStaticPaths (substituição de exportPathMap que é por página).

Esses novos métodos têm muitas vantagens sobre o modelo getInitialProps , pois há uma distinção clara entre o que se tornará SSG e SSR.

  • getStaticProps marca a página a ser gerada estaticamente no momento da compilação (ao executar next build )
  • getStaticPaths permite retornar uma lista de parâmetros para gerar em tempo de construção para rotas dinâmicas
  • getServerSideProps marca a página a ser renderizada do lado do servidor em cada solicitação e é a mais semelhante ao comportamento atual de getInitialProps ao usar um servidor.

A separação desses métodos também nos permite fornecer o objeto de contexto correto que pode ser digitado usando o TypeScript. Quando você opta por uma estratégia de renderização específica, obtém os valores corretos, atualmente com getInitialProps você deve adivinhar o que está disponível em SSG vs SSR ao usar TypeScript.

Além disso, ao tornar esses métodos explícitos, isso nos permitirá documentar as diferentes compensações com mais clareza.

Implementação

Observe que todos esses métodos são de nível superior no arquivo de componente da página e não podem ser aninhados, semelhante a getInitialProps .

getStaticProps

Usar getStaticProps significa que a página será renderizada estaticamente no momento da construção (SSG).

Este novo método permitirá que você faça a busca de dados para uma página que será gerada estaticamente em um arquivo .html no momento next build .

Next.js também irá gerar automaticamente um arquivo JSON que contém o resultado de getStaticProps no momento next build . Isso está sendo usado para roteamento do lado do cliente.

Ao rotear do lado do cliente por next/link ou next/router , Next.js buscará esse arquivo JSON para obter os adereços necessários para renderizar a página do lado do cliente.

As propriedades são retornadas com uma chave props para que outras opções possam ser introduzidas no futuro.

// pages/index.js

// getStaticProps is only called server-side
// In theory you could do direct database queries
export async function getStaticProps(context) {
  return {
    // Unlike `getInitialProps` the props are returned under a props key
    // The reasoning behind this is that there's potentially more options
    // that will be introduced in the future.
    // For example to allow you to further control behavior per-page.
    props: {}
  };
}

O context conterá:

  • params - Os parâmetros quando em uma rota dinâmica.

getStaticPaths

Esta é uma extensão do uso de getStaticProps para rotas dinâmicas.

getStaticPaths substitui a necessidade de ter um exportPathMap e funciona por página.

Já que você pode querer gerar estaticamente uma lista de urls que têm um parâmetro dinâmico, como no exemplo abaixo de slug . Next.js fornecerá um método getStaticPaths que permite retornar uma lista de urls. Como é um método async , você também pode buscar essa lista em uma fonte de dados como o seu CMS.

// pages/blog/[slug].js

// `getStaticProps` gets a `params` object holding the dynamic parameters
// For `/blog/hello-world` it would look like `{ slug: 'hello-world }`
export async function getStaticProps({ params }) {
  return {
    props: {}
  };
}

// `getStaticPaths` allows the user to return a list of parameters to
// render to HTML at build time.
export async function getStaticPaths() {
  return {
    paths: [
      // This renders /blog/hello-world to HTML at build time
      { params: { slug: "hello-world" } }
    ]
  };
}

Cair pra trás

Em muitos casos, você pode não querer pré-renderizar todas as rotas possíveis em seu aplicativo no momento da construção (por exemplo, se você tiver milhões de produtos). Por esta razão, Next.js irá gerar automaticamente uma página fallback que é uma renderização da página sem dados (para que um estado de carregamento possa ser mostrado) para quando a página ainda não foi gerada.

O comportamento exato de servir será:

  • Pedido de entrada

    • Next.js verifica se o caminho foi gerado no momento da construção

    • Se o caminho foi gerado



      • servir diretamente



    • Se o caminho não foi gerado



      • Sirva o substituto


      • Next.js renderiza a página (com dados) em segundo plano e a adiciona à lista de páginas geradas


      • A solicitação subsequente para o mesmo caminho exibirá a página gerada


      • Isso garante que os usuários sempre tenham uma experiência rápida e nunca tenham um TTFB lento da renderização do servidor, preservando compilações rápidas e propriedades de geração estática



Caso você queira que caminhos que não foram gerados no momento da compilação resultem em um erro 404, isso também é possível retornando fallback: false de getStaticPaths

// `getStaticPaths` allows the user to return a list of parameters to
// render to HTML at build time.
export async function getStaticPaths() {
  return {
    // Opt-out of the described fallback behavior
    fallback: false,
    paths: [
      // This renders /blog/hello-world to HTML at build time
      { params: { slug: "hello-world" } }
    ]
  };
}

getServerSideProps

Ao usar getServerSideProps , a página não é gerada estaticamente (SSG) e, em vez disso, é renderizada sob demanda em cada solicitação ao servidor (SSR).

Next.js também irá expor automaticamente um endpoint de API que retorna o resultado da chamada de getServerSideProps . Isso está sendo usado para roteamento do lado do cliente.

Ao rotear do lado do cliente por next/link ou next/router , Next.js buscará este endpoint de API exposto para obter os dados JSON que são transformados nos suportes necessários para renderizar a página do lado do cliente.

Este método é o mais semelhante ao getInitialProps atual, com a principal diferença sendo getServerSideProps sempre executado no lado do servidor em vez de no navegador. Tanto na renderização do lado do servidor quanto na busca de API durante o roteamento do lado do cliente.

Da mesma forma que getStaticProps as propriedades são retornadas sob uma chave props .

// pages/index.js

// getServerSideProps is only called server-side
// In theory you could do direct database queries
export async function getServerSideProps(context) {
  return {
    // Unlike `getInitialProps` the props are returned under a props key
    // The reasoning behind this is that there's potentially more options
    // that will be introduced in the future.
    // For example to allow you to further control behavior per-page.
    props: {}
  };
}

O context conterá:

  • params - Os parâmetros em uma rota dinâmica
  • req - O objeto de solicitação HTTP
  • res - O objeto de resposta HTTP
  • query - A string de consulta (não tenho certeza absoluta sobre esta, mas provavelmente necessária)

Autoria de @timneutkens , @Timer , @ijjk , @lfades. Colaborou com @rauchg , @jescalan e outros 🚀

Comentários muito úteis

O suporte para geração de site estático de próxima geração (SSG) foi lançado como estável no Next.js 9.3!

Esta versão também inclui suporte para "Modo de visualização" ou a capacidade de ignorar a página pré-renderizada estaticamente e renderizar a página sob demanda para usuários autorizados .

Você pode ler mais sobre isso em nossa postagem do blog . Se você estiver mais prático, vá direto para nossos documentos !

Todos 250 comentários

export async function getStaticProps(context) {
  return {
    // Unlike `getInitialProps` the props are returned under a props key
    // The reasoning behind this is that there's potentially more options
    // that will be introduced in the future.
    // For example to allow you to further control behavior per-page.
    props: {}
  };
}

Estou interessado em ver em que circunstância precisaríamos retornar dados adicionais além dos que podem estar contidos em props . Achei a explicação in-line "para controlar ainda mais o comportamento por página" um pouco vaga.

Parece muito interessante! Seria um substituto para getInitialProps ou ao lado? Por exemplo, para nosso caso de uso, a API de busca de dados é um serviço público. Portanto, na navegação do lado do cliente, esperamos que o cliente chame diretamente a camada API, enquanto no SSR o servidor a chama. No futuro, esse caso de uso continuaria a ser resolvido pelo método anterior?

Estou interessado em ver em que circunstância precisaríamos retornar dados adicionais além dos que podem estar contidos em props . Achei a explicação in-line "para controlar ainda mais o comportamento por página" um pouco vaga.

Tem mais a ver com a prova futura do método, de modo que nos permita estendê-lo mais tarde, se necessário.

Parece muito interessante! Seria um substituto para getInitialProps ou ao lado? Por exemplo, para nosso caso de uso, a API de busca de dados é um serviço público. Portanto, na navegação do lado do cliente, esperamos que o cliente chame diretamente a camada API, enquanto no SSR o servidor a chama. No futuro, esse caso de uso continuaria a ser resolvido pelo método anterior?

Em geral, esse comportamento tem algumas desvantagens, por exemplo, buscas em cachoeira que podem ser lentas em certas áreas ao redor do mundo. A abordagem getServerProps permite armazenar a resposta em cache com mais eficiência.

Isso parece muito interessante! Ótima ideia!

No entanto, estou preocupado com a implantação ...

Vamos imaginar que estou hospedando no Now.
Para a primeira implantação, é óbvio que todos os aplicativos são construídos na implantação.

Em seguida, altero algum conteúdo no CMS e procuro acionar a reconstrução apenas das páginas SSG, mas o código do aplicativo não mudou.

O alarme dispara imediatamente, neste caso, se eu acionar a compilação, há duas soluções possíveis:

1) Nada é reconstruído, pois tudo é armazenado em cache - nenhum código foi alterado e blabla.
2) I --force it, e agora "tudo" foi reconstruído, mas eu apenas solicitei que as páginas SSG fossem reconstruídas.

_Estas são apenas hipóteses, já que depende dos próprios sistemas de construção - quão cientes eles estão do Next_

Isso provavelmente afetaria qualquer outra solução de hospedagem.

O próximo em si tem um .next/cache ... como isso funcionaria em torno disso?

@joltmode é basicamente o caso de todos os geradores de sites estáticos atualmente. .next/cache é preservado entre as implantações no Now e reutilizado. Lembre-se de que você provavelmente está usando getInitialProps neste caso com cache (potencialmente https://zeit.co/blog/serverless-pre-rendering), que renderiza dinamicamente em uma função sem servidor e, em seguida, armazena em cache em nosso CDN, o comportamento ainda está totalmente bem e continuará a funcionar se você usar getServerProps .

Realmente incrível, se encaixaria perfeitamente em como estamos usando o Next para projetos de clientes e removeria alguns códigos clichê que copiamos.

Uma coisa a se considerar é a nomenclatura de getStaticProps e getServerProps, se eles retornarem um {props} e outras opções potenciais no futuro, os * Props não seriam confusos? Talvez getStaticConfiguration, getStaticSetup, getStaticOptions fossem mais genéricos?

@kibs, os valores de retorno sempre se relacionam a como os adereços são tratados. Portanto, a nomenclatura está bem.

Isso é simplesmente incrível! Isso está resolvendo todos os casos de uso e necessidades que tive recentemente ou que poderia pensar enquanto desenvolvia aplicativos da web profissionais e privados. Você acabou de me impedir de iniciar meu próprio gerador de site híbrido, obrigado!

Também posso me relacionar com os novos métodos sendo melhores do que os anteriores getInitialProps() e exportPathMap() , o que me pareceu um pouco confuso no início quando comecei a usar Next.js e me aprofundou em SSR / SSG. A abordagem por página também faz mais sentido para mim.

Mal posso esperar para experimentar!

Apenas uma observação lateral: no último exemplo, acho que getServerProps() está faltando um parâmetro context .

Apenas uma observação lateral: no último exemplo, acho que getServerProps () está faltando um parâmetro de contexto.

Fixo!

Isso parece ótimo! Eu só me pergunto da perspectiva do usuário TypeScript se ter getStaticProps , getStaticPaths e getServerProps como métodos estáticos no componente da página (como getInitialProps no momento) seja mais fácil de digitar / usar corretamente.

const Page: NextPage<Props> = (props) => ...

// Explicit types needed here
export const getStaticPaths: NextGetStaticPaths<Params> = () => ...
export const getStaticProps: NextGetStaticProps<Props, Params> = (context) => ...
export const getServerProps: NextGetServerProps<Props> = (context) => ...

export default Page

// vs.

const Page: NextPage<Props, Params> = (props) => ...

// Static method types come from NextPage<Props, Params>
Page.getStaticPaths = () => ...
Page.getStaticProps = (context) => ...
Page.getServerProps = (context) => ..

export default Page

@herrstucki, o problema com essa abordagem é que se torna significativamente mais difícil sacudir a árvore (leia-se: quase impossível). O que significaria que um código desnecessário seria enviado para o navegador.

@timneutkens bom argumento ... mas um arquivo separado não faria ainda mais sentido? Ou algo assim é _fiavelmente_ abalado por árvores?

// This should all be removed in client-side code …
import {fetchQuery, queryTag} from 'big-data-fetching-lib';
const query = queryTag`...`
export const getStaticProps = async () => ({ props: await fetchQuery(query) })

// Only this should be included client-side
export default (props) => ...

@herrstucki, podemos

Parece muito interessante! Seria um substituto para getInitialProps ou ao lado? Por exemplo, para nosso caso de uso, a API de busca de dados é um serviço público. Portanto, na navegação do lado do cliente, esperamos que o cliente chame diretamente a camada API, enquanto no SSR o servidor a chama. No futuro, esse caso de uso continuaria a ser resolvido pelo método anterior?

Em geral, esse comportamento tem algumas desvantagens, por exemplo, buscas em cachoeira que podem ser lentas em certas áreas ao redor do mundo. A abordagem getServerProps permite armazenar a resposta em cache com mais eficiência.

Claro, mas estou falando sobre como evitar o RTT para o servidor react. Considere o caso em que a saída SSR do servidor é armazenada em cache no proxy do servidor CDN / cache. Junte isso com a busca de dados para navegação do cliente chamando diretamente uma camada API diferente (comum para web / apps / todos os clientes), significa que a camada do servidor Next.js não precisa ser escalada tanto em um cenário de alto tráfego.

Eu entendo seu ponto de buscas em cascata, mas dar aos consumidores a capacidade de tratar o servidor Next como uma camada SSR em vez de uma fonte de dados permitiria configurações de escalonamento muito melhores.

Parece muito interessante! Seria um substituto para getInitialProps ou ao lado? Por exemplo, para nosso caso de uso, a API de busca de dados é um serviço público. Portanto, na navegação do lado do cliente, esperamos que o cliente chame diretamente a camada API, enquanto no SSR o servidor a chama. No futuro, esse caso de uso continuaria a ser resolvido pelo método anterior?

Em geral, esse comportamento tem algumas desvantagens, por exemplo, buscas em cachoeira que podem ser lentas em certas áreas ao redor do mundo. A abordagem getServerProps permite armazenar a resposta em cache com mais eficiência.

Claro, mas estou falando sobre como evitar o RTT para o servidor react. Considere o caso em que a saída SSR do servidor é armazenada em cache no proxy do servidor CDN / cache. Junte isso com a busca de dados para navegação do cliente chamando diretamente uma camada API diferente (comum para web / apps / todos os clientes), significa que a camada do servidor Next.js não precisa ser escalada tanto em um cenário de alto tráfego.

Eu entendo seu ponto de buscas em cascata, mas dar aos consumidores a capacidade de tratar o servidor Next como uma camada SSR em vez de uma fonte de dados permitiria configurações de escalonamento muito melhores.

Acho que você não entendeu que esse novo comportamento significa que você pode armazenar em cache os resultados completos em um CDN, já que o CDN oferece suporte a respostas dinâmicas. Anteriormente, isso não era possível de forma confiável com getInitialProps.

@timneutkens Eu brinquei com o canário, tentando portar algum código babel-plugin-preval para getStaticProps . Tive um problema com fs .

Estou tentando ler os arquivos .md do meu diretório ./pages/blog/ e percorrê-los para poder criar uma página de índice do blog com todas as minhas postagens

import React from 'react';
import Link from 'next/link';
import fs from 'fs-extra';

const Index = ({ posts }) => (
  <div>
    Hello World. <Thing msg="hello" />
    <Link href="/thing">
      <a>About</a>
    </Link>
    {posts.map(p => (
      <div key={p.title}>{p.title}</div>
    ))}
  </div>
);

Index.getStaticProps = async () => {
  const items = await fs.readdir('./pages/blog');
  items.forEach(path => /* .... do some stuff ... */ )
  return { props: { posts: items } };
};

export default Index;

Este código leva a este erro:

Module not found: Can't resolve 'fs' in '/Users/jared/Downloads/nextjs-typescript-template/node_modules/fs-extra/lib'

IIRC da Razzle, este erro está relacionado aos stubs do sistema de arquivos do webpack (ou à falta deles). Acho que uma vez consertei isso com o Razzle, adicionando-o à configuração do webpack.

node: {
  fs: "empty";
}

Eu tentei esse next.config.js, mas ele simplesmente fez o erro desaparecer. No entanto, parece que fs / fs-extra realmente não funciona, ou funciona e talvez os caminhos não (para mim não estejam claros). Alguma opinião sobre isso?

Minha outra pergunta, de forma mais geral, é o que você imagina que as melhores práticas serão para usar importar versus exigir em getStaticProps . Se não me engano, meu snippet acima tentará importar fs-extra no React isomorphically ??. Portanto, seria melhor alterar a importação para um requerimento embutido como este?

js Index.getStaticProps = async () => { const fs = require('fs-extra'); // only require when needed at SSG const props = await fs.readdir('./pages/blog'); return { props: { posts } }; };

Acho que você não entendeu que esse novo comportamento significa que você pode armazenar em cache os resultados completos em um CDN, já que o CDN oferece suporte a respostas dinâmicas. Anteriormente, isso não era possível de forma confiável com getInitialProps.

Ah, acho que entendi o que você quis dizer. Isso significaria que getServerProps na primeira geração de SSR criaria um ponto de extremidade exclusivo, em um hash endereçável de conteúdo talvez na URL, talvez possamos então armazenar em cache no CDN? A única desvantagem disso seria que o referido cache não seria compartilhável entre aplicativos não Next (android / ios) e aplicativos Next. Além disso, com uma fonte de dados externa, as diretivas de controle de cache são upstream, mas aqui, como o Next assumiria a responsabilidade de servir os dados, precisamos de APIs ou props para especificar aqueles para os terminais de dados gerados.

@jaredpalmer Suponho que https://github.com/zeit/next.js/issues/9524#issuecomment -558628066 (incluindo minha preocupação sobre a trepidação da árvore confiável ) seria resolvido por ter um arquivo separado que seria compilado completamente separado de código do pacote do cliente? Por exemplo

pages/
    foo.js
    foo.data.js (<- exports getStaticProps etc.)

or:

pages/
    foo.js
pages-data/
    foo.js (<- exports getStaticProps etc.)

A agitação da árvore

Como sempre, obrigado por tudo que vocês fazem. Next.js tem sido uma alegria absoluta para trabalhar e, como eu disse antes, quase todos os lançamentos de recursos nos permitem _reduzir_ o tamanho das bases de código que gerencio. É incrível.

É difícil criticar esse RFC, pois, conforme escrito, ele é imediatamente útil para MUITOS aplicativos. No entanto, quero abordar uma linha com a qual não tenho certeza se concordo:

" getStaticPaths substitui a necessidade de ter um exportPathMap e funciona por página."

Em alguns aplicativos, é impraticável ou impossível saber as rotas no momento da construção. Alguns exemplos seriam:

  • Páginas de perfil de usuário
  • Páginas de produtos (para empresas com um inventário em constante mudança)
  • Páginas de detalhes do pedido de vendas

As rotas para páginas como essa provavelmente estarão no formato /entity-name/entity-id e as rotas dinâmicas do Next funcionam muito, muito bem, pois você pode fazer coisas como router.push('/customers/[customerId]', '/customers/baer') . Ainda há um problema. Se você planeja servir esses arquivos estaticamente com algo como Serve, Netlify, NGINX, etc, você precisará gerar um conjunto de redirecionamentos para que os usuários não obtenham um erro 404 na atualização da página e, para fazer isso, você ainda precisa de exportPathMap .

O seguinte é copiado, quase como está, de uma base de código em que trabalho regularmente:

const buildServeConfig = redirects => {
  const config = {
    public: `dist`,
    trailingSlash: true,
    rewrites: redirects
  };

  const outputPath = `${__dirname}/serve.json`;

  fs.writeFile(outputPath, JSON.stringify(config, null, 2), err => {
    if (err) {
      throw err;
    }
    // eslint-disable-next-line no-console
    console.log(`Generated: ${outputPath}`);
  });
};

...

exportPathMap: function(defaultPathMap, { dev, outDir }) {
  const redirects = Object.entries(defaultPathMap)
    // No need to create a redirect rule for `/dirname/` or `/dirname/index.html`
    .filter(([url]) => url !== `/` && url !== `/index`)
    .map(([url, { page }]) => ({
      // Replaces /[customerId] with /:customerId
      source: url.replace(/]/g, ``).replace(/\[/g, `:`),
      destination: `${page}/index.html`
    }));

  // By default, the routes are sorted such that a route like `/order/:orderId`
  // comes before `/order/new`. Since the `:orderId` portion of `/order/:orderId` 
  // is a wildcard, the route `/order/new` will be a match and consider `new` 
  // as a value for `:orderId`. To get past this, we sort the redirects by the 
  // number of parameters in ascending order.
  const sortedRedirects = [...redirects].sort(
    (currentRedirect, nextRedirect) =>
      currentRedirect.source.split(`:`).length >
      nextRedirect.source.split(`:`).length
  );

  buildServeConfig(sortedRedirects);

  return defaultPathMap;
}

Eu entendo que este RFC não desaprova ou remove quaisquer APIs e eu também reconheço que é possível construir esses redirecionamentos percorrendo o diretório de compilação, então mesmo que fosse desaprovado, eu tenho um bom ecape hatch. Mas, não "elimina a necessidade de getStaticPaths ".

Mais uma vez, obrigado por sua consideração em como você executa este projeto

getStaticProps / getStaticPaths e getServerProps mutuamente exclusivos? ou seja, seria possível ter uma parte pré-renderizada e uma parte dinâmica ao mesmo tempo?

Sim, eles são, pois um é a geração estática e o outro é a renderização do lado do servidor.

Isso corrige uma das grandes coisas que sinto falta de Gatsby antes de migrarmos para o Next:

Temos um arquivo JSON monolítico (100s de kbs) do qual extraímos dados para renderizar nossas páginas que nunca mudam. Em Gatsby, carregamos o arquivo JSON no esquema GraphQL e o consultamos, obtendo apenas os dados de que precisávamos para renderizar uma determinada página. Com o Next, a maneira mais fácil / limpa que encontramos de fazer isso é import monolith from './monolith.json' , que requer que o usuário baixe todo o arquivo JSON.

Este RFC 100% aborda este caso de uso e traz a Next um passo mais perto de estar no mesmo nível de Gatsby nas áreas em que Gatsby brilha (obviamente, Gatsby não pode executar SSR em tempo de execução, então estou falando apenas de renderizações estáticas de tempo de construção)

@timneutkens , obrigado pelo RFC!

Tenho um caso de uso para Next.js que discuti recentemente com @rauchg.

Next.js oferece DX muito suave e alguns padrões razoáveis. Portanto, estou interessado em usar Next.js para um aplicativo renderizado apenas do lado do cliente, um aplicativo Smart TV.

Os aplicativos da Smart TV são quase aplicativos da web clássicos executados pelo mecanismo do navegador da TV:

  1. O aplicativo é empacotado em um pacote: estilos, scripts, imagens, _index.html_, certificados e arquivo de configuração de TV.
  2. O pacote é enviado para revisão na loja de aplicativos da plataforma.
  3. O pacote é então instalado da loja como um aplicativo e executado pelo usuário.

O problema é que o pacote é hospedado estaticamente pelo próprio dispositivo de TV e não é carregado do servidor. Portanto, nenhuma opção de SSR é possível (o Node.js não é exposto aos desenvolvedores para esses fins). Mas o próprio aplicativo é dinâmico (digamos, Netflix).

Portanto, precisamos executar um SPA hospedado por um servidor da web estático.

Pelo que entendi, recusar getServerProps (ou getInitialProps ) completamente ajudará a evitar o SSR. Mas o que acontece com a renderização dinâmica no cliente? E o roteamento neste caso? De acordo com esta RFC, o problema ainda não foi resolvido. @timneutkens , você poderia, por favor, sugerir a melhor maneira de habilitar a renderização apenas do lado do cliente em Next.js? E se ele se encaixa no Next.js em primeiro lugar? Obrigado!

PS: Posso criar um problema para este caso de uso se você achar melhor discuti-lo separadamente.

@grushetsky você pode criar um problema diferente. Esta é uma questão completamente diferente do que está sendo discutido no RFC 👍

@timneutkens A promessa deste RFC é uma das coisas que me deixou super animado com o Next! Só para esclarecer, getInitialProps ainda existiria também, certo?

Correto @outdooricon - getInitialProps permanecerá disponível no futuro próximo.

De acordo com o RFC:

Este RFC discute exclusivamente adições de API. Todas as novas funcionalidades são totalmente compatíveis com as versões anteriores e podem ser adotadas de forma incremental. Este RFC não apresenta depreciações.

Ótimo RFC, super animado por isso!

Estive pensando no getServerProps em relação a um caso de uso específico, colocando os resultados em um cache. Uma vez que isso é transformado em um endpoint de API e o resultado entregue ao componente como adereços, existe uma maneira prescrita de colocar o resultado em um cache externo como Redux, GraphQL-caches etc, etc do lado do cliente?

Se entendi getInitialProps corretamente, já que é estático e assíncrono, o Next tem a oportunidade de esperar que ele seja concluído antes de renderizar o componente pela primeira vez. Isso nos permite colocar as coisas em um cache externo lá. Este não será o caso com getServerProps uma vez que é executado no servidor, e colocar coisas em um cache no ciclo de vida do componente parece significar que temos que ter uma renderização onde os dados ainda não estão disponíveis no cache , mesmo que esteja disponível em adereços?

Isso pode ser intencional, é claro, e posso estar perdendo uma abordagem, mas pensei em perguntar se é algo que está sendo considerado.

Editar: acho que isso também se aplica a getStaticProps . 😄

Talvez eu tenha perdido em algum lugar, mas como lidamos com situações quando o conteúdo é armazenado em cache, mas é atualizado em db ou uma nova postagem de blog é criada? Há necessidade de fazer uma nova construção automaticamente? Eu acho que sim.

Em primeiro lugar! Ótima proposta, é uma grande melhoria em relação a exportPathMaps no caso de uso da maioria das pessoas. É muito apreciado. Dito isso, estou tentando entender como poderíamos fazer funcionar com a internacionalização de rotas.

Há alguma sugestão sobre como lidar com rotas prefixadas i18n? Meu caso de uso específico requer a construção de alguns milhares em páginas com diferentes prefixos e URLs de idioma de país.

/nl/brillen
/gb/glasses
/es/gafas
...

Parece que getStaticPaths será realmente útil quando o prefixo para a url for bem conhecido, como no seu exemplo (usando /blog/[id].js ). Mas como você acha que uma implementação getStaticPaths ficará se precisar gerar caminhos no nível da raiz, com um prefixo dinâmico (país-idioma) e um caminho dinâmico?

@reaktivo pages/[lang]/blog/[id].js -> em getStaticPaths fornece todos os urls para renderizar estaticamente.

@timneutkens Alguma ideia de quando isso estará disponível / testável?

Em geral, não fornecemos ETAs porque testamos extensivamente os recursos em relação aos aplicativos de produção para garantir que a solução seja a certa.

Essas melhorias me farão totalmente depreciar meu projeto fenômico "não mantido assim" (reação ssg que ninguém usa exceto eu). Impressionante ver Next.js adicionando essas peças que faltam!

Eu gostaria de esclarecer uma dúvida. Considerando o uso de um CMS como o wordpress. Pelo que entendi, com o método getStaticPaths eu iria buscar todas as postagens e passar uma lista como:

export async function getStaticPaths () {
  return [
    // This renders / blog / hello-world to HTML at build time
    {params: {slug: "hello-world"}}
  ];
}

O slug de cada postagem seria usado no método getStaticProps para buscar o conteúdo.
Isso aconteceria no npm build.
Minha pergunta é sobre novos posts que serão adicionados após a construção.
O método getStaticProps seria usado para buscar este novo post por slug?
Esta nova postagem terá um arquivo .html como o da versão anterior?
Amo trabalhar com o próximo e em vários projetos que tenho isso seria muito bom.

Nada diretamente relacionado, mas o suporte não consegue me dar uma resposta que corresponda à minha pergunta.

O que você sugere aqui pode ser a solução, mas, por enquanto, não consigo fazer o nextJS para construir um JAMSTACK baseado em alterações de webhooks.

se eu tivesse getInitialProps, serei renderizado pelo servidor.
Se não fizer isso, estou apenas CDNized, mas sem pré-renderização não é? E a página ficará sem conteúdo enquanto o XHR não retornar (tchau, SEO)

Você tem algum exemplo em execução agora de Jamstack com nextJS e poderíamos fazer no netlify.

Obrigado,
Andréas

Ei @ScreamZ - next export por um longo tempo, mas ele ainda buscaria dados nas transições de rota do lado do cliente usando getInitialProps . Com a capacidade de usar getStaticProps , você pode executar transições do lado do cliente sem que nenhum dado adicional seja buscado - todos os dados buscados em getStaticProps são buscados uma vez, no momento da compilação, e não atualizados em seu site ao vivo, a menos que você reconstrua novamente. Esta é a arquitetura clássica de sites estáticos baseados em dados, vincule sua fonte de dados ao seu host via webhook e quando a fonte de dados mudar, você diz ao host para reconstruir o seu site.

Existem muitos exemplos de sites nextjs totalmente estáticos, e é trivial executar um site nextjs na netlify. O site da minha empresa está rodando no nextjs e hospedado pela netlify, espero que isso sirva como um bom exemplo.

É muito importante notar que o serviço de hospedagem zeit também é algo que vale a pena ser fortemente considerado. O preço é bastante semelhante e sua integração com os sites nextjs é incomparável - você literalmente nem precisa configurar nada, basta vincular o github e a hospedagem do zeit reconhecerá que você está executando o nextjs e configurará e implantará automaticamente tudo.

Este não é um anúncio de forma alguma, eu não trabalho para zeit, apenas um endosso genuíno. Você pode absolutamente fazer funcionar com a netlify, e eu tenho pessoalmente para vários sites como prova. Mas você precisa entender completamente como o nextjs funciona, e você precisa ter certeza de que tudo está configurado corretamente para que funcione sem problemas no netlify. Se você está procurando a hospedagem mais simples e infalível para um site nextjs, eu experimentaria a hospedagem do Zeit.

@jescalan Obrigado por este ótimo compartilhamento 🙏🏻

Não tenho problemas para usar NextJS com netlify, porque você pode usar Publish directory para especificar a pasta out . Mas no zeit Now, não há como dizer, por favor, não use SSR, mas vá totalmente estático com next export .

@ScreamZ isso é meio que verdade, mas depende de como exatamente você define um site "totalmente estático". Se você usar getStaticProps para todas as suas páginas com o serviço de hospedagem zeit, o que você obterá é efetivamente igual a um site estático, mesmo que não execute next export , já que todas as páginas com getStaticProps são construídos apenas quando o site é implantado e são servidos diretamente do CDN depois disso.

A principal diferença é que, até onde eu sei, não há uma maneira de forçar todas as páginas a serem estáticas na hospedagem do Zeit (edit: zeit mudou recentemente para que qualquer site com uma configuração que contenha exportPathMap seja executado um site totalmente estático, então isso não é mais verdade). As páginas com getStaticProps se comportam exatamente da mesma forma que as páginas geradas por next export - uma única cópia estática da página é servida diretamente do CDN em cada hit. Mas você também poderia executar algumas páginas com getServerProps ou getInitialProps e elas se comportariam como páginas renderizadas pelo servidor. Pessoalmente, vejo isso como um benefício - se houver necessidade de uma rota SSR, você pode simplesmente usar um método de busca de dados diferente e essa rota única agora é SSR, enquanto todas as outras rotas podem permanecer estáticas.

@jescalan Obrigado,

Então, só preciso esperar para que isso seja implementado, enquanto isso irei usar o netlify para estática

Existe uma história em torno da configuração SSG? Especificamente, gostaríamos de usar artefatos de compilação compartilhados, mas executar next export com configurações diferentes para QA / prod. Esses valores de configuração seriam lidos apenas em getStaticProps . Isso usaria serverRuntimeConfig ou publicRuntimeConfig ou process.env diretamente?

@ScreamZ @jescalan Consegui suporte zero-config next export no Now hoje junto com @Timer (ele merece todos os créditos). Você pode fazer:

"build": "next build && next export"

E funcionará automaticamente.

Me diga como foi 🙏

Sim, eu fui o cara que perguntou sobre o suporte e eles me disseram que isso foi implementado ainda 😅 Pelo que eu posso ver, você precisará definir um mapa de exportação na configuração?

@ScreamZ não, você pode simplesmente adicionar next build && next export conforme mostrado acima e funcionará.

@timneutkens Se eu substituir getInitialProps por getServerProps , ainda preciso adicionar target: 'serverless' ao arquivo de configuração para habilitar Server Pre Rendering ? Obrigado.

Como podemos tentar isso?

Como podemos tentar isso?

Eu acho que todos esses métodos atualmente precisam do prefixo unstable_ para serem reconhecidos.

por exemplo, unstable_getStaticProps

@timneutkens

@ScreamZ @jescalan Consegui suporte zero-config next export no Now hoje junto com @Timer (ele merece todos os créditos). Você pode fazer:

"build": "next build && next export"

E funcionará automaticamente.

Me diga como foi 🙏

Meu script de construção está fazendo um pouco mais de coisas, mas parece que funciona perfeitamente:

"build": "graphql codegen && next build && npm run export",

Além disso, é ótimo! Era exatamente o que eu procurava 😅 (Adeus GatsbyJS, meu framework favorito agora é forte como você!)

Muito obrigado por essa reatividade.

Eu também atualizei para 9.1.6 e surpreendentemente vi que
Screenshot 2019-12-21 at 19 25 43

Achei que aquele tópico fosse um RFC, parece que já está aberto pra gente ahah, não tá?
No entanto, os tipos de texto tipográfico não estão habilitados em 9.1.6.

Droga, estou tão empolgado com isso agora! 🤣

Últimas perguntas:

  • Se eu receber, getInitialProps ficará obsoleto no futuro? Ou ainda é relevante em alguns casos? Um exemplo?
  • next export também pode ser preterido em favor de páginas com getStaticProps e next build apenas?

Obrigado por essa ótima ferramenta 🙏🏻

Se eu conseguir, getInitialProps será descontinuado no futuro? Ou ainda é relevante em alguns casos? Um exemplo?

Conforme dito no RFC inicial:

Este RFC discute exclusivamente adições de API. Todas as novas funcionalidades são totalmente compatíveis com as versões anteriores e podem ser adotadas de forma incremental. Este RFC não apresenta depreciações.

Achei que aquele tópico fosse um RFC, parece que já está aberto pra gente ahah, não tá?

Não é, estamos testando em aplicativos ZEIT e parte da visibilidade da superfície já atingiu (por exemplo, a árvore de páginas que você viu).

a próxima exportação também pode ser descontinuada em favor de páginas com getStaticProps e próxima construção apenas?

Correto, em geral você acabará não usando next export . Ele será mantido por motivos de compatibilidade com versões anteriores, mas em geral você desejará criar um aplicativo híbrido, pois oferece todos os benefícios da exportação com suporte para outros recursos como rotas de API e opção de renderização do lado do servidor para algumas páginas.

Como podemos tentar isso?

Eu acho que todos esses métodos atualmente precisam do prefixo unstable_ para serem reconhecidos.

por exemplo, unstable_getStaticProps

É altamente recomendável não usá-lo ainda, é experimental e pode ser interrompido entre os lançamentos.

Portanto, estou testando esse recurso e observei que o arquivo JSON que contém os dados da página é sempre buscado após acessar a página SSG de outra página.

Vocês planejam alguma otimização de pré-carregamento para o arquivo JSON?
Talvez pré-carregando-o quando o usuário está prestes a navegar para a página (isto é: o usuário está passando o mouse sobre um link SSG) ou pré-carregando da mesma forma que você está pré-carregando outras páginas js que são referenciadas a partir de um componente Link.

A propósito desse recurso!

Vocês planejam alguma otimização de pré-carregamento para o arquivo JSON?

sim.

Pelo que vale a pena, eu sou totalmente a favor da exportação desordenada dessas funções, em vez de arquivos separados.

Qual é o status deste recurso? Quais são seus bloqueadores?

@mikestopcontinues este RFC está sendo intensamente testado internamente por nossa equipe e alguns parceiros selecionados. Você pode optar por seu comportamento altamente experimental usando os prefixos unstable_ , conforme mencionado acima ! 😄

No entanto, não migre as cargas de trabalho de produção para os novos métodos, pois ainda podemos atualizar as APIs de maneira inovadora.

Pessoalmente, utilizo-o para a geração de sites estáticos de 8 a 20K páginas (com possibilidade de ter alguns pedidos dinâmicos em algumas páginas). Funciona muito bem (exceto para o limite de 10K de arquivos no Now), a única coisa que acho uma vergonha é que sem o método getStaticPaths, getStaticProps é chamado a cada recarga. Um comportamento que pode ser bom é que a primeira chamada cria o arquivo json e a próxima o usa.

As construções incrementais estão planejadas? Portanto, apenas o conteúdo novo / alterado é reconstruído?

Você pode optar por seu comportamento altamente experimental usando os prefixos unstable_ , conforme mencionado acima !

Eu gostaria de testar o método unstable_getServerProps , mas parece que ele está ignorado no momento e não consigo encontrá-lo em nenhum lugar do zeit/next.js repo. Ainda não foi implementado ou estou apenas fazendo errado?

As construções incrementais estão planejadas? Portanto, apenas o conteúdo novo / alterado é reconstruído?

A implementação foi projetada com reconstruções incrementais em mente, mas ainda não é suportada (nem abordada neste RFC).

Fique tranquilo, a arquitetura está pronta e iremos explorá-la depois que esses recursos estabilizarem.
É por isso que getStaticProps é definido por página, e não uma vez para o aplicativo inteiro!

Eu gostaria de testar o método unstable_getServerProps, mas parece que ele está ignorado no momento [...]

getServerProps ainda não está disponível na visualização, desculpe!

getServerProps ainda não está disponível na visualização, desculpe!

Obrigado pelo aviso. Definitivamente estarei observando este tópico, porque quando chegar lá, eu tenho um _banco_ de código que pode ser substituído renomeando uma única função! 😍

Esclareça, não estou 100% certo se getServerProps / getStaticProps estão disponíveis para uso ou não.

Com base neste tópico: Não

Mas se for esse o caso, então estou me perguntando por que meu terminal aludiu a ele quando executei next build se eles ainda não estão disponíveis? Ver a mensagem me deixou com a suposição inicial de que esses métodos estavam em produção e demorei um pouco para descobrir que não estavam. Só estou curioso sobre o raciocínio ou se há algo que estou entendendo mal.

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

(na próxima versão 9.1.6)

Obrigado

@stevenjchang eles estão disponíveis usando a seguinte sintaxe em pages/**/*.js :

export function unstable_getStaticPaths() {} // return [{params: {...}}, ...]
export function unstable_getStaticProps({params: {...}) {} // return {props: {...}}

E eu também devo acrescentar, eles são maravilhosos, embora ainda sejam um pouco ásperos ao usar o servidor de desenvolvimento.

embora eles ainda sejam um pouco ásperos ao usar o servidor de desenvolvimento.
@mikestopcontinues

Você poderia, por favor, elaborar mais sobre isso? Ninguém mais nos deu feedback negativo sobre a experiência do servidor de desenvolvimento e adoraríamos resolver o problema!

@Timer Eu realmente gosto da nova api. Meu principal problema durante o desenvolvimento é que o json é solicitado novamente a cada carregamento. Isso retarda o teste, mas também deturpa a experiência do usuário ao navegar no site.

Por “a cada carregamento” você quer dizer o carregamento da página? Ou reconstruir? Ou...?

@mmmeff Cada vez que você navega para o mesmo caminho, ele solicita novamente o json. Portanto, se você clicar para frente e para trás entre duas páginas, perderá muito tempo esperando pelos dados.

@mikestopcontinues este é o comportamento pretendido, já que os dados mais atualizados são geralmente preferíveis no desenvolvimento. Estaria aberto para discutir algumas heurísticas melhores em uma nova edição!

@timneutkens Este RFC parece muito promissor. Tenho algumas dúvidas / preocupações sobre a segurança e como ela funciona exatamente.

Vejamos um caso de negócios genérico que depende de SSR e SSG.

Contexto

Queremos exibir algumas informações em um site (também conhecido como "aplicativo").
Essas informações são armazenadas em um BDD que pode ser acessado por meio de uma API GraphQL.
Algumas dessas informações são públicas, outras são privadas (por exemplo: e-mails / senha do usuário).

O aplicativo usa dois estágios:

  • Um estágio de "teste", onde o cliente pode ver as mudanças em tempo real no aplicativo de teste (eles atualizam essas informações por meio de algum back-office ou similar)
  • Uma fase de "produção", onde o cliente não tem acesso e não pode atualizar nada por si mesmo. Para atualizar o aplicativo de produção, uma nova implantação deve ser feita. (eles pedem que uma nova implantação de produção seja feita, a partir de seu referido back-office)

Neste cenário, usamos SSR e SSG:

  • O aplicativo de teste usa SSR, porque busca em tempo real os dados da API GraphQL (ao construir uma página)
  • O aplicativo de produção usa SSG, porque quando uma nova implantação é feita, ele busca os dados da API GraphQL e gera páginas estáticas a partir dela (elas são, portanto, estáticas e não mudarão mais, nenhuma consulta será feita na API GraphQL em tempo de execução (pelo menos não ao carregar uma página))

Este cenário deve ser genérico o suficiente e deve ser (IMHO) um dos principais casos de uso de SSG.
O aplicativo de produção nada mais é do que um instantâneo do aplicativo de teste.

Algumas questões:

  1. Isso é possível com este RFC ? Ter o mesmo aplicativo se comportando de maneira diferente com base em um determinado "estágio" (produção / teste)
  2. Como os dados são obtidos da API GraphQL injetada?

    • No teste, eles são buscados dinamicamente por meio de SSR ou CSR conforme o usuário navega pelas páginas (e estarão disponíveis no navegador se buscados durante o CSR)

    • Na produção, eles são buscados em tempo de construção, mas então, eles são armazenados dentro de uma variável global JS e, portanto, podem ser lidos por qualquer pessoa? (preocupação de segurança, pois devemos estar atentos para não buscar dados confidenciais que podem ser disponibilizados no navegador, semelhante a como é feito ao usar o CSR)

  3. Você teria alguma preocupação com essa abordagem com SSR / SSG misto? (segurança, desempenho, facilidade de manutenção, etc.)

Quando você planeja lançar isso? Vai ser uma atualização principal (v10) ou uma atualização compatível com versões anteriores?

Ei,

Alguém já experimentou essa solução com um servidor personalizado e fez com que funcionasse?

Exemplo:

// server.js

const express = require('express');
const next = require('next');

const port = parseInt(process.env.PORT, 10) || 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/:id', (req, res) => {
    console.log('My params needed be passed to page:', req.params);
    return app.render(req, res, '/blogDetail', { id: req.params.id });
  });

  server.listen(port, err => {
    if (err) throw err;
    console.log(`> Ready on http://localhost:${port}`);
  });
});

// blogDetail.js
export async function unstable_getStaticProps(props) {
  console.log('What is passed', props);

  return {};
}

const BlogPostPage = ({ post }) => {
  return <div>Hey</div>;
}

export default BlogPostPage;
# Terminal output

My params needed be passed to page: { id: 'test' }
What is passed { params: undefined }

Por que getStaticProps incluir a string de consulta? Atualmente, tenho uma página que preciso fazer SSR simplesmente para obter os parâmetros de consulta sem renderizar novamente. Usar o gancho useRouter causa múltiplas re-renderizações, uma vez que a consulta é inicialmente um objeto vazio. Esta é uma página usada para acompanhamento de conversões, então, obviamente, não é um iniciante.

@pjaws O RFC menciona especificamente getStaticProps é para geração estática. O HTML estático não pode receber uma string de consulta.

Então, por que ele pode receber parâmetros de URL dinâmicos? Como é que isso é diferente?

Na terça - feira, 14 de janeiro de 2020 à 1h30, Tim Neutkens
escreveu:

@pjaws https://github.com/pjaws O RFC que menciona especificamente
getStaticProps é para geração estática. HTML estático não pode receber um
string de consulta.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=AMVRRIQCKDJNF4MPWSLYNV3Q5WA2NA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEI35G2I#issuecomment-574083945 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AMVRRIRJXLYC4MC4U7DH7NDQ5WA2NANCNFSM4JRPBELQ
.

Porque em getStaticPaths você deve retornar as páginas que serão renderizadas no momento da construção.

Essas mudanças parecem muito promissoras, ótimo trabalho como sempre! 👍

Eu me pergunto sobre o caso de uso de getInitialProps em _app.js para satisfazer as necessidades de dados compartilhados entre as páginas (por exemplo, configurar provedores de contexto). Eu entendi corretamente que é impossível usar getStaticProps da mesma maneira? Só é possível definir em páginas individuais?

Eu me pergunto sobre o caso de uso de getInitialProps em _app.js para satisfazer as necessidades de dados compartilhados entre as páginas (por exemplo, configurar provedores de contexto). Eu entendi corretamente que é impossível usar getStaticProps da mesma maneira? Só é possível definir em páginas individuais?

Correto, inicialmente será apenas para páginas individuais. Pode reconsiderar mais tarde. O getInitialProps de _app ainda será chamado ao exportar para HTML estático para que você possa mover incrementalmente para getStaticProps.

oi pessoal, uma pergunta relacionada - como os ativos serão tratados? porque estou vendo agora que se eu usar um CMS headless (mesmo wordpress ou graphcms ou qualquer outro), o URL do ativo é usado no html estático.

Existem duas preferências aqui - que os links de ativos sejam usados ​​como tal.
Mas o mais provável - baixe o ativo, construa o html (link para ele localmente) e então coloque um CDN na frente. Esta é a prática muito mais aceitável.

Isso também combina muito bem com o uso de sistemas de implantação como o Netlify - que têm uma infraestrutura disponível globalmente muito, muito mais adequada do que algo como DatoCMS ou Graphcms. Portanto, se estou usando o Netlify como implantação, gostaria que tudo fosse servido a partir do domínio do Netlify e deixá-lo fazer sua mágica.

@sandys Se bem entendi em https://github.com/zeit/next.js/issues/9054#issuecomment -570427085, você deve baixar os ativos, armazená-los em .next/static e criar um link você mesmo em getStaticProps .

Também existe a ideia de ter rotas de API estáticas, mas não tenho certeza de como você controlaria o comportamento de cache do navegador com isso.

@Janpot obrigado por vinculá-lo. Os comentários ali parecem indicar que esse material deve ser feito por você mesmo.

Por favor, adicione meu pedido para ter este integrado. Talvez # 9054 seja mais genérico, mas estou pensando da perspectiva do SSG e isso é EXTREMAMENTE essencial.

Esqueci de mencionar, mas o hashing de ativos também será essencial para o SSG.

@homoky , não consegui fazer isso funcionar, você fez algum progresso nesse meio tempo?

@homoky , não consegui fazer isso funcionar, você fez algum progresso nesse meio tempo?

Não é possível e também não está planejado: # 10071

😢

@sandys, na verdade, a solução é muito mais simples quando você usa https://github.com/zeit/next.js/issues/9081 para adicionar uma reescrita de, por exemplo, /images ao CMS. Por exemplo, no ZEIT Agora ele já armazenaria o resultado em cache quando os cabeçalhos corretos fossem adicionados, sem necessidade de download adicional (sobrecarga massiva na construção).

@timneutkens obrigado por responder.
Não tenho certeza do que você quer dizer. Portanto, usamos o netlify - você está sugerindo que mantenham os urls do CMS como tais e coloquemos uma camada de CDN sobre ele?
Não tenho muita certeza se o netlify (cloudfront que estamos planejando usar) pode funcionar perfeitamente com todos esses serviços.

Se as imagens forem baixadas e fizerem parte da implantação, todo esse problema será extremamente simplificado. Porque eu configurei o CDN para armazenar em cache a partir do url de base (que no meu caso será servido a partir de s3).

Não tenho certeza se sua solução depende de mim usando o Zeit NOW

Se as imagens forem baixadas e fizerem parte da implantação, todo esse problema será extremamente simplificado. Porque eu configurei o CDN para armazenar em cache a partir do url de base (que no meu caso será servido a partir de s3).

Na verdade, isso torna o processo de construção muito mais complexo e 10x mais lento, definitivamente não mais simples.

Não tenho certeza se sua solução depende de mim usando o Zeit NOW

Funciona com todos os proxy do mundo. Incluindo Cloudfront.

@timneutkens somos agnósticos quanto ao tempo do processo de compilação, na verdade. não importa se demorar mais. mas por muitos motivos (incluindo todos os ativos servidos a partir de um url de base conhecido), seria altamente preferível tê-lo incluído no build.

Certamente não estou defendendo que você ative isso para todos. Muitas pessoas ficarão felizes em criar links diretos para um CMS. Mas administramos um site de alto tráfego e isso é definitivamente algo que sites como nós precisam.

Além disso, me perdoe, mas não entendi sua solução. como devemos configurar isso? Eu não tenho controle sobre qual url um CMS usa. Por exemplo, o Datocms começa a ser veiculado em

somos agnósticos quanto ao tempo do processo de compilação, na verdade. não importa se demorar mais

Isso pode ser verdade para o seu aplicativo, mas não é o caso para a maioria dos aplicativos.

mas por muitos motivos (incluindo todos os ativos servidos a partir de um url de base conhecido), seria altamente preferível tê-lo incluído no build.

Realmente não tem que ser como disse, você pode usar uma reescrita que faz proxy /images/* para a url do cms, por exemplo www.datocms-asset.com/* ou similar. E então apenas vincule todas as imagens usando /images .

Observe que isso está começando a sair do tópico.

@sandys na verdade, a solução é muito mais simples quando você usa # 9081 para adicionar uma reescrita de, por exemplo, / images ao CMS. Por exemplo, no ZEIT Agora ele já armazenaria o resultado em cache quando os cabeçalhos corretos fossem adicionados, sem necessidade de download adicional (sobrecarga massiva na construção).

@timneutkens Só para deixar as coisas claras para mim. Na situação ideal, você criaria hash da imagem e armazenaria em cache para sempre no navegador em um url exclusivo, e os criadores de conteúdo podem atualizar o arquivo sempre que quiserem com o mesmo nome no CMS. Isso significa que, na configuração que você propõe, o CMS deve ser responsável por:

  1. otimizando as imagens
  2. hashing das imagens e veiculá-las sob este hash
  3. fornecer um mapa do url da imagem para o url da imagem com hash que pode ser baixado em getStaticProps para remapear os urls da imagem para sua contraparte imutável no CMS

O que, eu acho, não é impossível. Só quero ter certeza de que esta é a configuração proposta.

Os provedores de CMS da

@sandys, isso não está relacionado ao SSG RFC, então sinta-se à vontade para criar um novo problema quando for lançado.

no entanto, gostaria apenas de mencionar que, em todas as nossas mentes, isso está intimamente ligado ao SSG. Já que o caso ideal é o comando de exportação SSG fazer isso. Isso geralmente não é necessário em outros casos.
O melhor é que este seja um recurso opcional durante a próxima exportação.

Mas, como você deseja - respeite sua decisão.

Mas é algo que next export nem mesmo faz atualmente. Daí porque é uma coisa completamente nova e não relacionada a este RFC.

Também não aconteceria com getServerProps e renderização sob demanda.

Os provedores de CMS da

👍 sim, isso faz sentido. Mas isso também significa que se você usar imagens em seu projeto e quiser otimizá-las e armazená-las em cache, você tem 2 opções:

  1. construir uma configuração de pacote web personalizado
  2. usar um CMS externo

editar:

E se bem entendi, file-loaderestá incluído para CSS. Não é uma questão de habilitá-lo para JS também?

@Janpot o ponto específico que Sandeep mencionou é que os urls viriam de uma fonte externa, não do projeto em si. Incluir o carregador de arquivos por padrão é uma solicitação de recurso diferente.

Percebi que, para sites implantados no ZEIT Now, quando tenho uma página com um URL dinâmico usando as novas APIs estáticas, para páginas que não foram geradas estaticamente usando unstable_getStaticPaths , a função unstable_getStaticProps é executado no servidor em tempo de execução, em vez de retornar um 404.

Por exemplo, eu tenho uma página /blog/[slug].js , cuja getStaticPaths retorna a matriz:

[{ params: { slug: 'hello' } }]

e meu getStaticProps tem alguma lógica para ler um arquivo baseado no slug. Quando eu visito /blog/hello a página é pré-renderizada conforme o esperado, mas quando eu visito uma página inválida como /blog/doesnt-exist , então getStaticProps é executado em tempo de execução e recebo um erro 500, em vez de um 404. Ou se eu adicionar tratamento de erros, a página renderiza, em vez de 404, apesar de não estar listada na saída de getStaticPaths .

Essa lógica é intencional?

Esta é uma grande melhoria. Estávamos prestes a escrever alguns scripts pré-compilados para fazer exatamente isso.
Acabei de testar mover um de nossos sites para unstable_getStaticPaths e unstable_getStaticProps no Next 9.2 e funcionou bem.

Temos uma regressão em comparação com exportPathMap : ao construir um caminho usando exportPathMap , você pode especificar algo assim:

{
 "/path/to/page": {page: "/index", query: { pageId: 123 } }
}

e a construção estática irá construir

/path
   /to
     /page
       index.html

Quando você retorna o equivalente de unstable_getStaticPaths no modelo [slug].jsx ,

[{ slug: '/path/to/page' }]

O próximo 9.2 gera '% 2Fpath% 2Fto% 2Fpage` em vez dos diretórios aninhados.

/%2Fpath%2Fto%2F
   index.html

Construir diretórios (correspondendo ao comportamento exportPathMap existente) é importante para a forma como estamos construindo páginas. Usamos um único arquivo de modelo, mas o caminho publicado pode ser aninhado arbitrariamente.

@dpfavand , nesse caso, você vai querer usar uma rota pega-tudo: https://nextjs.org/blog/next-9-2#catch -all-dynamic-routes

Potencialmente, podemos avisar quando você tenta retornar um caminho incluindo barras, mas o comportamento é correto ao usar [slug].js , no seu caso você deseja [...slug].js .

Quando está previsto o pouso? Estará em um patch de 9.2 ou em sua própria versão secundária?

Nós realmente apreciamos todo o entusiasmo em torno desse recurso. Conforme mencionado em outro lugar, geralmente não compartilhamos cronogramas para recursos, pois queremos garantir que eles tenham a experiência de desenvolvedor certa, restrições e resistência ao futuro.

Como é um novo recurso, será menor.

Sim, normalmente entenderia, mas o blog 9.1.7 deu a impressão
já estava solto.

Na sexta-feira, 17 de janeiro de 2020 às 17h05, Tim Neutkens [email protected]
escreveu:

Nós realmente apreciamos todo o entusiasmo em torno desse recurso. Como mencionado
em outros lugares, geralmente não compartilhamos cronogramas para recursos como queremos
garantir que eles tenham a experiência de desenvolvedor certa, restrições e futuro
prova.

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=ADKINGF724256WCEFHBFIH3Q6ITRXA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJJDN5Q#issuecomment-575813366 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/ADKINGBVCG6MFMOG5U2FGMDQ6ITRXANCNFSM4JRPBELQ
.

>

Lassiter Gregg
[email protected] [email protected]
célula (832) 495-9903

Existe algo como getStaticProps mas que é executado apenas uma vez para todo o aplicativo, em vez de por página?

Meu caso de uso é que tenho um Contexto React ( PricingPlansContext ) que é usado por várias páginas e quero que os dados (planos de preços) sejam recuperados do meu servidor externo apenas uma vez, no momento da compilação ( next export ). Nunca em tempo de execução e sem ter que adicionar getStaticProps de cada página.

EDIT: Encontrado um comentário relacionado acima: https://github.com/zeit/next.js/issues/9524#issuecomment -574179540. Espero que seja considerado.

Eu uso babel plugin-preval` para isso, embora também tenha visto pessoas escreverem um
arquivo json em exportPathMa () com next.config.js, que eles importam
dentro de seu código.

Acabei escrevendo um arquivo json usando um script npm por enquanto, mas obrigado por sugerir exportPathMap, talvez seja um lugar melhor.

@dpfavand , nesse caso, você vai querer usar uma rota pega-tudo: https://nextjs.org/blog/next-9-2#catch -all-dynamic-routes

Potencialmente, podemos avisar quando você tenta retornar um caminho incluindo barras, mas o comportamento é correto ao usar [slug].js , no seu caso você deseja [...slug].js .

@timneutkens, obrigado pelo acompanhamento. Tentei dois métodos sem sucesso. Basicamente, ao especificar o valor do slug como uma string em getStaticPaths , ele não é passado para getStaticProps alguma. Ao retornar o valor do slug como uma matriz, a construção falha, pois o valor deve ser uma string.

Caso 1, assumindo um arquivo pages/[...slug].jsx , slug como string:

export async function unstable_getStaticPaths() {
    return [{ params: { slug: 'en/about' } }];
}

export async function unstable_getStaticProps({ params }) {
    console.log('params', params);
    return { slug: params.slug };
}

No caso acima, params em getStaticProps é um objeto vazio - nenhuma chave slug .

Caso 2, pages/[...slug].jsx , slug como array,

export async function unstable_getStaticPaths() {
    const allPaths = Object.keys(pathMap).map(slug => ({ params: { slug } }));
    return [{ params: { slug: ['en', 'about'] } }];
}
export async function unstable_getStaticProps({ params }) {
    console.log('params', params);
    return { slug: params.slug };
}

No caso 2, a construção falha com

> Build error occurred
{ Error: A required parameter (slug) was not provided as a string.
    at _validParamKeys.forEach.validParamKey (/project/node_modules/next/dist/build/utils.js:21:569)
    at Array.forEach (<anonymous>)
    at toPrerender.forEach.entry (/project/node_modules/next/dist/build/utils.js:21:495)
    at Array.forEach (<anonymous>)
    at Object.isPageStatic (/project/node_modules/next/dist/build/utils.js:17:122)
    at process._tickCallback (internal/process/next_tick.js:68:7) type: 'Error' }

Só vejo parâmetros de caminho nos exemplos getStaticPaths acima. Será possível usar caminhos SSG que incluam parâmetros de consulta? Por exemplo:

/store/widgets/circles-n-squares?sort=price&minWeight=2&color=black

Estou pensando especialmente da perspectiva de um site de comércio eletrônico, onde seria difícil cobrir todas as facetas da pesquisa de produtos no pathname de um url.

Eu postei uma mensagem aqui recentemente e não tive nenhuma resposta - essencialmente, getStaticProps está se comportando como getServerProps quando um site é implantado no ZEIT Now (ou seja, ignorando getStaticPaths e lidando com solicitações dinamicamente) - Eu acho que isso é um bug?

@dpfavand estou experimentando exatamente a mesma coisa! Tentando construir um site inicial para agilitycms e nextjs com roteamento de página dinâmico baseado em páginas no CMS.

@timneutkens, obrigado pelo acompanhamento. Tentei dois métodos sem sucesso. Basicamente, ao especificar o valor do slug como uma string em getStaticPaths , ele não é passado para getStaticProps alguma.

Caso 1, assumindo um arquivo pages/[...slug].jsx , slug como string:

export async function unstable_getStaticPaths() {
  return [{ params: { slug: 'en/about' } }];
}

export async function unstable_getStaticProps({ params }) {
  console.log('params', params);
  return { slug: params.slug };
}

No caso acima, params em getStaticProps é um objeto vazio - nenhuma chave slug .

Aliás, pequeno mundo! Obrigado novamente por falar em fastr_conf.

Olá @timneutkens ,

Estou muito animado com a ideia de fazer next.js se comportar como um gerador de site estático.

Gostaria de perguntar como os métodos getStaticProps e getStaticPaths podem ser usados ​​no caso em que um grande bloco de dados é solicitado uma vez e, em seguida, usado para gerar páginas diferentes.

Por exemplo, estou usando um cliente JavaScript SDK de um CMS baseado em API que tem um método para buscar todos os objetos disponíveis. Alguns desses objetos representam páginas do site.

const entries = await cmsSdkCient.getEntries();

Até agora, tenho usado o método exportPathMap para buscar todas as entradas do CMS de uma vez e gerar um mapa entre os caminhos dessas páginas e seus dados. A função exportPathMap faz duas coisas:

  1. Fornece mapa de páginas com seus dados e ssr: true que é consumido por getInitialProps no momento da exportação
  2. Grava os mesmos dados, desta vez com ssr: false , em init-props.json arquivos, colocados na pasta correspondente ao caminho de cada página. Então, quando getInitialProps é chamado do cliente, os dados necessários são carregados de init-props.json da página correspondente.


next.config.js usando exportPathMap

module.exports = {
  exportTrailingSlash: true,
  exportPathMap: (defaultPathMap, { outDir }) => {
    // load data from CMS
    const objects = await cmsSdkCient.getEntries();

    // create map between page paths and page data
    return objects.reduce((accum, object) => {

      // if the object does not have a slug, it is not a page
      if (!object.slug) return accum;

      const pagePath = '/' + object.slug;
      const ssrQueryData = Object.assign({ ssr: true }, object);
      const clientQueryData = Object.assign({ ssr: false }, object);

      // generate the map for export phase with {ssr: true}
      accum[pagePath] = {
        // using additional fields from the page object,
        // the pageFromPagePath() computes which page file should
        // be used to render the page object
        page: pageFromPagePath(object),
        query: ssrQueryData
      };

      // write json files that will be loaded by client
      if (outDir) {
        const jsonFilePath = path.join(outDir, _.trim(pagePath, '/'), 'init-props.json');
        fse.outputFileSync(jsonFilePath, JSON.stringify(clientQueryData));
      }

      return accum;
    }, {});
  }
}


pages / my_page.js usando getInitialProps

Index.getInitialProps = async (context) => {
  const ssr = _.get(context, 'query.ssr', false);
  if (ssr) {
    // we are on server, return the data
    return _.get(context, 'query', {});
  } else {
    // we are on client side, request the data through /init-props.json endpoint
    const url = context.asPath + '/init-props.json';
    return fetch(url).then(response => {
      return response.json();
    });
  }
};

Eu posso ver a grande vantagem de usar os métodos getStaticProps e getStaticPaths que irão reduzir muito do meu código relacionado a salvar arquivos JSON e carregá-los do cliente.

// pages/my_page.js
export async function getStaticProps(context) {
  const objects = await cmsSdkCient.getEntries();
  const props = _.find(object, { type: 'my_page' })
  return { props };
}

// pages/blog/[slug].js
export async function getStaticProps(context) {
  const objects = await cmsSdkCient.getEntries();
  const props = _.find(object, { type: 'post', slug: context.params.slug })
  return { props };
}

export async function getStaticPaths() {
  const objects = await cmsSdkCient.getEntries();
  return objects
    .filter(object => object.type === 'post')
    .map(object => ({ params: { slug: object.slug } }))
}

O que me preocupa é como posso otimizar o fluxo de trabalho para trazer todas as entradas de uma vez, em vez de buscá-las sempre que getStaticProps ou getStaticPaths são chamados?

Outra pergunta, pode não estar necessariamente relacionada a este problema, mas como estamos no mundo dos SSGs e fontes de dados remotas, vale a pena perguntar. Supondo que next.js seja executado no modo dev, como alguém pode notificar next.js para reexecutar esses métodos a fim de buscar novamente os dados remotos e reconstruir o site.

@smnh Como é “apenas JavaScript”, você pode buscar suas entradas uma vez e armazenar em cache os resultados em seu método de busca de dados. Quando for chamado novamente em alguns métodos getStatic * de outra página, a rede não será atingida novamente.

Quanto à sua segunda pergunta, ela o faz automaticamente. Execute next dev e você está pronto para ir.

Só vejo parâmetros de caminho nos exemplos getStaticPaths acima. Será possível usar caminhos SSG que incluam parâmetros de consulta? Por exemplo:

/store/widgets/circles-n-squares?sort=price&minWeight=2&color=black

Estou pensando especialmente da perspectiva de um site de comércio eletrônico, onde seria difícil cobrir todas as facetas da pesquisa de produtos no pathname de um url.

Não acho que isso faça sentido no contexto do ssg. O SSG gera um arquivo para cada entrada - os parâmetros de consulta não fazem parte do nome do arquivo, então você precisa de uma camada de servidor para reescrever as solicitações em um arquivo real. (Qual seria o nome do seu arquivo estático no exemplo acima?) Sugiro considerar a pré-renderização da visualização padrão (o que você obtém se visitar a página sem facetas) e a atualização no lado do cliente se houver parâmetros de consulta na solicitação. Mas isso se torna um problema além deste RFC SSG.

@dpfavand estou experimentando exatamente a mesma coisa! Tentando construir um site inicial para agilitycms e nextjs com roteamento de página dinâmico baseado em páginas no CMS.

@timneutkens, obrigado pelo acompanhamento. Tentei dois métodos sem sucesso. Basicamente, ao especificar o valor do slug como uma string em getStaticPaths , ele não é passado para getStaticProps alguma.
Caso 1, assumindo um arquivo pages/[...slug].jsx , slug como string:

export async function unstable_getStaticPaths() {
    return [{ params: { slug: 'en/about' } }];
}

export async function unstable_getStaticProps({ params }) {
    console.log('params', params);
    return { slug: params.slug };
}

No caso acima, params em getStaticProps é um objeto vazio - nenhuma chave slug .

Aliás, pequeno mundo! Obrigado novamente por falar em fastr_conf.

Ei! A equipe do Nextjs começou a resolver isso, há um tíquete aberto para resolver alguns problemas adicionais com a implementação canário atual: https://github.com/zeit/next.js/issues/10190

@smnh o que acabo fazendo é ter um script que pré-busca o conteúdo compartilhado e o salva em JSON antes de executar o build + export. Em seguida, basta importar esse JSON diretamente na página como um módulo.

Para reconstruções, tenho webhooks configurados no CMS para acionar ganchos de compilação do Netlify quando o conteúdo relevante é alterado. GetStaticProps pode então apenas buscar o conteúdo específico da página.

Obrigado @zeusdeux
Ré:

Quanto à sua segunda pergunta, ela o faz automaticamente. Execute o próximo desenvolvimento e pronto.

Se eu armazená-los em cache em um módulo e, em seguida, alterar os dados no CMS, como o cache será invalidado e executado novamente por dev , mas sem interromper next.js e executá-lo novamente :)

Se eu armazená-los em cache em um módulo e, em seguida, alterar os dados no CMS, como o cache será invalidado e executado novamente por dev , mas sem interromper next.js e executá-lo novamente :)

getStaticPaths só é invocado em uma construção de produção, então você só pode dizer ao método fetching para armazenar em cache no estado do módulo quando chamado a partir dessa função.

Ei, eu não vi se alguém teve o mesmo problema que eu.

Digamos que eu tenho a mesma página em várias rotas com unstable_getStaticProps :

1. /providers/[category]/[city] 
2. /providers/[category] 

O código-fonte é o mesmo para ambas as páginas, portanto, não há necessidade de duplicá-lo. Portanto, para o primeiro arquivo conter código-fonte com lógica, o segundo importa apenas o primeiro como export { default } from './[city]'; .

Mas gera um erro de que os dados de getStaticProps são indefinidos. Se eu copiar o mesmo código para os dois arquivos, ele funciona.

@homoky, você precisa exportar novamente os métodos:

export { default, unstable_getStaticProps } from './[city]';

Tenho tentado SSG, mas sem sorte.

O código abaixo com v9.2.1 deve resultar em SSG?

function Page({ stars }) {
  return <div>Next stars: {stars}</div>
}

Page.unstable_getStaticProps = async ctx => {
  return { props: { stars: 5 } }
}

export default Page

A saída do meu console de next build mostra:

Page                                                           Size     First Load
┌ ○ /                                                          354 B       72.1 kB
...
λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

@joostmeijles unstable_getStaticProps precisa ser exportado em vez de anexado ao componente da página, por exemplo

export const unstable_getStaticProps = async () => {
  return {
    props: { stars: 5 }
  }
}

@joostmeijles unstable_getStaticProps precisa ser exportado em vez de anexado ao componente da página, por exemplo

export const unstable_getStaticProps = async () => {
  return {
    props: { stars: 5 }
  }
}

Obrigado, isso resolve tudo.

Se alguém quiser ver um exemplo prático de ponta a ponta disso, criando páginas dinâmicas (a partir de um CMS) com uma rota pega-tudo e SSG, confira https://github.com/agility/agilitycms-next-starter- ssg.

Fiquei perplexo algumas vezes e percebi que isso poderia ser útil para outras pessoas.

Como posso acessar as próximas rotas de API durante a construção com getStaticProps ao implantar em zeit.co/now? A busca isomórfica requer um URL absoluto; localmente, ele funciona com http: // localhost : 3000, mas não com a implantação agora (ou fiz errado 🤷‍♂️). Alguma ideia?

Se eu estiver correto, as rotas de API serão implantadas como funções sem servidor e eu acho que elas não estão prontas durante o processo de construção?

Você vai querer chamar a função de sua rota de api diretamente, pois isso é muito menos sobrecarga do que passar por http.

Você vai querer chamar a função de sua rota de api diretamente, pois isso é muito menos sobrecarga do que passar por http.

Há algum recurso que eu possa ler na documentação sobre esse tópico? Estou no meio da migração para zeit.co/now :)

Considerado literalmente, importe e chame a função:

import MyFunction from '../lib/somewhere'


export async function /* unstable_ */getStaticProps() {
  const result = await MyFunction()
}

Outra pergunta: será possível usar getStaticProps / getStaticPaths e getServerProps lado a lado? Por exemplo, se eu pré-renderizei algumas páginas com SSG, mas se alguma não for encontrada no cache do CDN, ele retornará ao SSR para gerar a página sob demanda?

getStaticProps fará fallback para SSR e adicionará o resultado ao cache,

getStaticProps fará fallback para SSR e adicionará o resultado ao cache,

@lfades , se entendi bem, estou super 😍 sobre isso, porque significa que posso pré-renderizar algumas das páginas populares, em vez de olhar para cima e gerar vários milhares de páginas com antecedência.

Mas apenas para ter certeza de que entendi ... Digamos que eu tenha uma página de caminho dinâmico /products/[productId].js . Se eu fornecer getStaticProps e um número limitado de resultados de getStaticPaths , então você está dizendo que /products/123 não foi encontrado no cache CDN (porque não foi t em getStaticPaths ), ele retornará ao SSR, executará getStaticProps e, em seguida, armazenará em cache o resultado como uma página estática?

Pergunta de acompanhamento: isso também funcionará se eu não fornecer getStaticPaths ?

@flintinatux Sim e sim 👍

getStaticProps fará fallback para SSR e adicionará o resultado ao cache

Isso é um problema porque não há como fazer 404s, uma vez que getStaticProps não permite alterar o objeto res - será 200 ou 500 se houver um erro durante a chamada da função.

Isso está planejado para mudar?

@ davidbailey00 ao criar sites estáticos, as páginas 404 já não têm o código de status 404.

Claro que se eu fizer uma exportação totalmente estática, não há como fazer códigos de status, já que tudo é apenas um arquivo. Estou falando sobre implantar sites híbridos usando getStaticProps para ZEIT Now - parece que ele deve respeitar getStaticPaths e servir 404 páginas, em vez de forçar a renderização de todas as páginas que correspondem a um caminho dinâmico, independentemente disso.

Não é apenas assim que funciona no Now, o mesmo em next start .

Vou repetir como disse antes: isso é experimental e qualquer coisa ainda pode mudar no comportamento.

Mas é possível servir 404 páginas com getServerProps ou getInitialProps - se getStaticProps ignorar getStaticPaths ao considerar o código de resposta, então é completamente inviável para qualquer site que se preocupa com bom SEO.

Provavelmente introduziremos mais maneiras de lidar com códigos de status, mas tenha em mente que a maioria dos sites estáticos (por exemplo, CRA) direcionam /* para index.html onde 404 ainda é 200.

Oi pessoal, tenho uma pergunta direta. Estou construindo um site simples usando o novo [unstable_]getStaticProps para SSG algumas das páginas. Tudo está funcionando bem até agora, com exceção do amplificador .

Se uma página contém [unstable_]getStaticProps , então amp está desabilitado. Aqui está um exemplo simples de trabalho com a próxima v9.2.1, onde você pode verificar se:

import React from "react";
import { useAmp } from "next/amp";

export const config = { amp: `hybrid` };

const AmpExample = ({ date }) => {
  const isAmp = useAmp();
  return (
    <>
      <p>
        Welcome to the {isAmp ? `AMP` : `normal`} version of the Index page!!
      </p>
      <p>date: {date}</p>
    </>
  );
};
/**
 * If I get the dynamic data from getStaticProps,
 * page is SSG render but AMP is disabled when accessing
 * with `/ampExample?amp=1`
 */
export async function unstable_getStaticProps() {
  return {
    props: {
      date: new Date().toISOString(),
    },
  };
}

/**
 * If I get the dynamic data from getInitialProps,
 * page is SSR render but AMP is disabled when accessing
 * with `/ampExample?amp=1`
 */
// AmpExample.getInitialProps = () => {
//   return { date: new Date().toISOString() }
// }
export default AmpExample;

Alguma ajuda para entender como ter as páginas SSG com dados e amp funcionando?

Olá, que tal oferecer suporte a getStaticProps para o componente App ( _app.tsx ), ou seja, para casos como a busca de dados comuns para todos os componentes da página durante o estágio de compilação?

Olá, que tal oferecer suporte a getStaticProps para o componente App ( _app.tsx ), ou seja, para casos como a busca de dados comuns para todos os componentes da página durante o estágio de compilação?

@ pkral78 Posso dizer como resolvo o atual estado de desenvolvimento.

Eu criei um Layout com a abordagem "Layout como um Componente de Ordem Superior (HOC)" (não mais nos documentos de aprendizagem 🤷‍♂️).

Enfim, criei um Layout como o seguinte (apenas um exemplo):

import React from "react";
import Head from "next/head";

const withSSGLayout = Page => {
  const WithSSGLayout = props => {
    return (
      <>
        <Head>
          <title>My Web Page</title>
          <link rel="icon" href="/favicon.ico" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <link
            href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"
            rel="stylesheet"
          />
        </Head>
        <Page {...props} />
      </>
    );
  };

  WithSSGLayout.unstable_getStaticProps = async () => {
    const pageStaticProps = Page.unstable_getStaticProps
      ? await Page.unstable_getStaticProps()
      : {};

    // Here you can make parent level queries too
    return {
      props: {
        ...pageStaticProps.props,
        parentProp: `dynamic prop-${new Date().toISOString()}`,
      },
    };
  };
  return WithSSGLayout;
};

export default withSSGLayout;

E então, na página que deseja usar esta abordagem, você pode simplesmente adicionar o HOC (você tem que exportar explicitamente o [unstable_]getStaticProps e o amplificador não funcionando juntos), mas eu encontrei uma "maneira legal" de ter uma solicitação de alto nível e consultas SSG por página.

import React from "react";
import withSSGLayout from "../hocs/withSSGLayout";

export const config = { amp: `true` };

const Index = props => {
  const { date, parentProp } = props;
  return (
    <div>
      <h1>Example</h1>
      <h3>Local Prop?: {date}</h3>
      <h3>Parent Prop?: {parentProp}</h3>
    </div>
  );
};

// In theory you could do direct database queries
Index.unstable_getStaticProps = async () => {
  // Here you can make page level queries
  return {
    props: {
      date: new Date().toISOString(),
    },
  };
};
const IndexHOC = withSSGLayout(Index);

export const { unstable_getStaticProps } = IndexHOC;
export default IndexHOC;

Gostaria de enganar se for uma boa abordagem. No meu caso, estou usando essa técnica para consultar os links no pai e por conteúdo de página nas páginas. Espero que ajude.

@robertovg Você deve exportar no nível do módulo, pois o código é

@timneutkens Você poderia propor uma solução melhor para este pequeno exemplo ? Eu estava tentando ter "Consulta SSG de nível de layout" e "Consulta SSG de nível de página" de alguma forma e pensei sobre essa abordagem de layout HOC.

A principal restrição para mim era explicitamente "exportar [unstable_] getStaticProps" que você precisa ter em cada página para marcar como página SSG.

Eu realmente gostaria de receber mais informações sobre se o amp + SSG será compatível, perguntei antes.

Obrigado 🙏

@robertovg Primeiro, separe o layout dos dados, então, para o layout compartilhado, você teria algo simples como isto:

import Layout from '../components/layout'

const Page = () => (
  <Layout>
    <h1>Hello World!</h1>
  </Layout>
)

export default Page

E então, para getStaticProps busque os dados compartilhados usando um método de outro módulo, de forma que o exemplo completo possa se parecer com:

import fetchSharedData from '../lib/fetch-shared-data'
import Layout from '../components/layout'

export const unstable_getStaticProps = async () => {
  const sharedData = await fetchSharedData()
  const pageProps = {...}

  return {  props: { ...sharedData, ...pageProps } }
}

const Page = () => (
  <Layout>
    <h1>Hello World!</h1>
  </Layout>
)

export default Page

@robertovg Primeiro, separe o layout dos dados, então, para o layout compartilhado, você teria algo simples como isto:

import Layout from '../components/layout'

const Page = () => (
  <Layout>
    <h1>Hello World!</h1>
  </Layout>
)

export default Page

E então, para getStaticProps busque os dados compartilhados usando um método de outro módulo, de forma que o exemplo completo possa se parecer com:

import fetchSharedData from '../lib/fetch-shared-data'
import Layout from '../components/layout'

export const unstable_getStaticProps = async () => {
  const sharedData = await fetchSharedData()
  const pageProps = {...}

  return {  props: { ...sharedData, ...pageProps } }
}

const Page = () => (
  <Layout>
    <h1>Hello World!</h1>
  </Layout>
)

export default Page

Eu vejo e entendo essa solução, mas o problema que eu estava tentando levantar era como dimensionar o uso de dados compartilhados.
Por exemplo, se você tiver um <Header /> que usa sharedData para obter os links e eles vêm de um CMS sem cabeça. Você tem que injetar <Header /> como um filho de <Layout /> com adereços ou outra solução. E você precisa repetir a injeção de <Header /> em todas as páginas que deseja usar.

Com a abordagem HOC, você apenas adicionaria <Header /> uma vez no HOC.

É por isso que achei um bom ponto o levantado por @ pkral78 , para evitar duplicação de código, se possível.

É por isso que achei um bom ponto o levantado por @ pkral78 , para evitar duplicação de código, se possível.

Estava em minha mente. A página _app deve ter seu getStaticProps que é chamado uma vez durante a renderização da primeira página e então passar props salvos para as próximas páginas renderizadas. Mas ainda estou pensando se é um conceito adequado.

Não tenho certeza se esse tipo de coisa é um caso de uso pretendido, mas parece não funcionar:

// /pages/[...slug].jsx
import ReactDOMServer from "react-dom/server";

export async function unstable_getStaticProps({ params: { slug } }) {
  const filePath = "../content/" + slug.join("/") + ".mdx";
  const { default: Component } = await import(filePath);
  const content = ReactDOMServer.renderToStaticMarkup(<Component />);
  return {
    props: { title: slug.join(" "), content }
  };
}

export default function Page({ title, content }) {
  return (
    <div>
      <h1>{title}</h1>
      <div dangerouslySetInnerHTML={{ __html: content }} />
    </div>
  );
}

Mesmo que não seja um caso de uso pretendido, ele registra um erro que parece um pouco suspeito:

[ warn ]  ./pages/[...slug].jsx
Critical dependency: the request of a dependency is an expression

Editar:

Oh, ok, isso resolve quando eu faço

const { default: Component } = await import(`../content/${slug.join("/")}.mdx`);

https://codesandbox.io/s/happy-oskar-40bug

Isto está reclamando sobre o caminho do seu arquivo de importação ser dinâmico

Na quinta-feira, 30 de janeiro de 2020 às 00h29, Jan Potoms [email protected] escreveu:

Não tenho certeza se esse tipo de coisa
https://codesandbox.io/s/nifty-cache-jspqr é um caso de uso pretendido, mas
parece não funcionar:

// /pages/[...slug].jsximport ReactDOMServer de "react-dom / server";
exportar função assíncrona unstable_getStaticProps ({params: {slug}}) {
// quão seguro é isso mesmo?
const filePath = "../content/" + slug.join ("/") + ".mdx";
const {padrão: Componente} = espera importação (filePath);
const content = ReactDOMServer.renderToStaticMarkup (Component);
Retorna {
adereços: {título: slug.join (""), conteúdo}
};
}
exportar função padrão Página ({título, conteúdo}) {
Retorna (


{título}




);
}

Mesmo que não seja um caso de uso pretendido, ele registra um erro que parece um
um pouco suspeito:

[avisar] ./pages/[...slug].jsx
Dependência crítica: o pedido de uma dependência é uma expressão

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=AAADKRKOL34WKTG7J5QFRJ3RAIGPBA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKJESJY#issuecomment-580012327 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AAADKRIWNA2DSMWFRGD453DRAIGPBANCNFSM4JRPBELQ
.

É por isso que achei um bom ponto o levantado por @ pkral78 , para evitar duplicação de código, se possível.

Estava em minha mente. A página _app deve ter seu getStaticProps que é chamado uma vez durante a renderização da primeira página e então passar props salvos para as próximas páginas renderizadas. Mas ainda estou pensando se é um conceito adequado.

@ pkral78 , Pode ser porque na maioria dos sites SSG que imagino implementados com o Next, gostaria de ter uma "peça comum" (cabeçalho, rodapé, barras laterais ...). E porque não fazer apenas a consulta por aquele trecho comum no _app se precisar, e tê-lo disponível nas páginas filhas sem ter que fazer manualmente em cada página.

Minha única preocupação é que se você colocá-lo em _app.js , não poderemos ter mais de uma "peça comum" dependendo da página. Com a ideia que estava fazendo o protótipo, eu queria poder tê-lo no Layout porque nos permitiria ter vários Layouts dependendo do tipo de página que você deseja renderizar, "é por isso que chamei withSSGLayout para meu HOC porque eu estava planejando ter não apenas páginas SSG, mas SSR e páginas totalmente baseadas no cliente, ou até mais de um SSGLayout. Isso poderia ser feito se o Layouts também pudesse ser responsável por um método pai getStaticProps .

De qualquer forma, ter SSG no Next irá torná-lo a ferramenta para qualquer tipo de site 🙌

@Janpot com relação a https://github.com/zeit/next.js/issues/9524#issuecomment -580012327

É altamente recomendável nunca usar caminhos dinâmicos em import() . Ele agrupará todos os arquivos possíveis sob o caminho para o pacote JS e reduzirá significativamente o desempenho de construção ao fazer isso.

@timneutkens Claro, faz sentido. getStaticProps serve apenas para consultar APIs externas, não o sistema de arquivos?

@Janpot você pode ler do sistema de arquivos, mas frequentemente você acabará consultando alguma API externa.

@timneutkens Ok, melhor usar @mdx-js/runtime então, ao invés de confiar em @next/mdx eu acho.

import ReactDOMServer from "react-dom/server";
import { promises as fs } from "fs";
import MDX from "@mdx-js/runtime";

export async function unstable_getStaticProps({ params: { slug } }) {
  const mdxContent = await fs.readFile(`./content/${slug.join('/')}.mdx`, {
    encoding: "utf-8"
  });
  const content = ReactDOMServer.renderToStaticMarkup(<MDX>{mdxContent}</MDX>);
  return {
    props: { title: slug.join(" "), content }
  };
}

export default function Page({ title, content }) {
  return (
    <div>
      <h1>{title}</h1>
      <div dangerouslySetInnerHTML={{ __html: content }} />
    </div>
  );
}

@Janpot sim! você também pode usar o markdown simples, é o que fazemos para nextjs.org/docs.

Em relação a https://github.com/zeit/next.js/issues/9524#issuecomment -580207073, é exatamente como eu atualmente uso Next com SSR. Eu tenho uma solicitação GraphQL que é executada no nível do Layout e seu conteúdo é compartilhado com os componentes comuns do aplicativo (Navbar, Footer e os filhos dinâmicos). Em seguida, os filhos dinâmicos geralmente fazem outra solicitação GraphQL para conteúdo específico da página.

Portanto, ter uma maneira de reutilizar isso parece importante, eu não gostaria de ter que duplicar o código em cada página para buscar esses dados comuns.

Ei!
Sou bastante novo aqui. Acabei de começar a trabalhar na migração do aplicativo para NextJS.

Há um caso de uso básico que se beneficiaria muito com esse recurso - versões em vários idiomas. O aplicativo da web em que estou trabalhando tem cerca de 16 idiomas com mais de 100.000 visualizações de página por dia e ser capaz de gerar apenas uma página de destino estaticamente, por exemplo, seria fantástico, mas o problema é o roteamento.

Com a renderização do lado do servidor, posso ler cabeçalhos de solicitação ou cookies e renderizar a versão de idioma adequada, mas sem isso, a única solução é criar caminhos para cada versão como / en, / de, / fr e em "/" fazer NextJS fazer apenas redirecionar?

Depois de aprender sobre ReactDOMServer.renderToStaticMarkup , adicionei-o à minha função unstable_getStaticProps e descobri que ele melhorou minha pontuação do PageSpeed ​​(móvel) de 96 para 100, graças à melhoria drástica do Tempo para Interatividade e Atraso de entrada de potencial máximo .

Posso visitar a página sem JavaScript e ela carrega bem, então parece que o React está funcionando no carregamento da página, apesar de usar SSG.

Talvez seja uma falta de entendimento sobre React, mas eu esperaria que o desempenho com e sem JavaScript fosse o mesmo, e não esperaria que a pré-renderização dos componentes ajudasse (pensei que era isso que o SSG estava fazendo).

O esperado é um bug ou algo que estou fazendo de errado?

Pré-confirmação: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2F5e310826bcf5030008a91209--josephduffynextjs.netlify.com%2Fposts%2Fgathered-1-0-1&tab=mobile
Commit: https://github.com/JosephDuffy/josephduffy.co.uk/pull/54/commits/d23898b874e5088ebcfabf577ee396b476ed97e4
Pós-confirmação: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2F5e3371beda1b8f0009368ef9--josephduffynextjs.netlify.com%2Fposts%2Fgathered-1-0-1&tab=mobile

@JosephDuffy

portanto, parece que o React está trabalhando no carregamento da página, apesar de usar SSG.

Está hidratando o DOM. Basicamente:

  1. seu navegador carrega o SSR html no navegador DOM
  2. React reconstrói todo o DOM virtual
  3. O React atravessa esses DOMs e os sincroniza (hidratação)

Se o seu conteúdo for realmente estático, sem efeitos colaterais ou manipuladores de eventos, as etapas 2 e 3 são desnecessárias. Com o seu método, você basicamente reduz a árvore de componentes para 1 componente com 1 atributo, o que é muito rápido para o React renderizar e hidratar. (+ dangerouslySetInnerHTM é ignorado durante a hidratação)

<div dangerouslySetInnerHTML={{ __html: props.htmlContent }} />

Lembre-se de que manipuladores de eventos e efeitos colaterais não funcionarão com esse método.

Editar:

Uma ideia poderia ser permitir a omissão da exportação padrão em uma página se getStaticProps retornar html estático. ie

export async function unstable_getStaticProps() {
  // ...
  return {
    props: { dangerouslySetInnerHTML: { __html: '<div>static content</div>' } }
  };
}

Como nada precisa ser renderizado no lado do cliente, next.js pode excluir seu tempo de execução da página e apenas embutir o html que getStaticProps retornou. E funcionaria da mesma maneira como se dangerouslySetInnerHTML fosse usado no nó raiz next.js.
Acho que seria mais fácil de implementar do que a hidratação parcial, embora menos potente. Reutilizar a terminologia do próprio React aqui pode reduzir a confusão sobre como esse recurso funcionaria.

Estou tentando migrar um site estático para Next.js e gostaria de redirecionar todas as variantes .html de postagens de blog para versões que não terminam em .html. Parece que getStaticProps não obtém contexto no momento, então não posso executar uma verificação de slug de entrada e redirecionamento. Seria útil se getStaticProps tivesse contexto completo para que eu pudesse fazer algumas coisas condicionais com ele.

@nodabladam , parece que você está procurando o RFC de rotas personalizadas: # 9081.

Esse RFC permitiria que você defina algo assim:

// next.config.js
module.exports = {
  redirects() {
    return [
      // Redirect from the old HTML version of a blog post
      {
        source: "/blog/:post.html",
        destination: "/blog/:post",
        permanent: true
      }
    ];
  }
};

No momento, você pode experimentar este recurso com a tecla experimental :

// next.config.js
module.exports = {
  experimental: {
    redirects() {
      // ...
    }
  }
};

Implementei getStaticProps e getStaticPathNames em um projeto meu (cerca de 8 mil páginas).

No entanto, os arquivos de saída são contados para o limite de 10 K de arquivos por implantação. Com páginas de 8K, você obtém 16K de arquivos de saída, já que cada página também recebe um arquivo json.

Existem planos para aumentar esse limite? Ou posso contornar esse limite?

Eu tenho o mesmo problema.
Eu entendo que eles estão tentando aumentar esse limite, mas não sei quando será implantado.

Então, eu uso getStaticProps em todas as páginas e getStaticPaths apenas em algumas delas e funciona (minha página de produto gera 70% do total de páginas, então não coloquei nenhum getStaticPaths nela). Eu fico abaixo do limite, mas não é perfeito, o primeiro carregamento é bastante longo e difícil de lidar com erros 404.

Eu tenho o mesmo problema.
Eu entendo que eles estão tentando aumentar esse limite, mas não sei quando será implantado.

Então, eu uso getStaticProps em todas as páginas e getStaticPaths apenas em algumas delas e funciona (minha página de produto gera 70% do total de páginas, então não coloquei nenhum getStaticPaths nela). Eu fico abaixo do limite, mas não é perfeito, o primeiro carregamento é bastante longo e difícil de lidar com erros 404.

Espero que eles aumentem o limite logo, porém espero que não seja 20K .. isso não será o suficiente para mim no longo prazo.

Eu quero evitar os primeiros tempos de carregamento com getStaticPaths .. Posso ter que procurar outras soluções além do Zeit Now

Next.js também expõe automaticamente um endpoint de API que retorna o resultado da chamada de getServerProps. [...] Next.js buscará este endpoint de API exposto para obter os dados JSON que são transformados nos adereços necessários para renderizar a página do lado do cliente.

Next.js buscará dados deste endpoint antes de fazer a mudança de rota real e renderizar o componente da página (ele não pode, pelo menos por padrão, fazer isso de outra maneira). Assim, o usuário pode experimentar um site extremamente ágil devido a certas páginas sendo geradas estaticamente, mas se clicar em um link para uma página SSR, de repente o site irá "travar" um pouco antes de a rota mudar.

Existe uma maneira recomendada de carregar o componente _primeiro_ para que ele possa ser preenchido com indicadores de carregamento, marcadores de posição animados, etc.? (Em vez de adicioná-los à página atual.) Se não, poderia ser relevante para os recursos recentemente propostos? Eu consegui usando uma combinação de getInitialProps e ganchos dentro do método de renderização, mas parece confuso.

Eu acho que esse padrão UX (troca de página instantânea) é preferido por muitos (a maioria?), Mas eu não vi nenhum exemplo dele usando Next.js ainda. Só usei a estrutura por alguns dias, então corrija-me se estiver errado.

Muito animado com os novos recursos! Obrigado pelo seu trabalho.

@nicoqh , suas preocupações sobre as transições de página não são específicas do SSG, já que o travamento ocorre com o getInitialProps atual. Eu uso nprogress para pelo menos mostrar uma barra de progresso no topo enquanto a próxima página está carregando, mas também vejo este exemplo de transições de página legítimas que parecem mais próximas do que você está descrevendo. Eu não tentei sozinho, mas espero que ajude com o que você precisa:
https://github.com/zeit/next.js/tree/canary/examples/with-next-page-transitions

Parece que o arquivo json /_next/data/BUILD_ID/<file>.json que é retornado não honra o assetPrefix. Isso faz com que o arquivo seja 404 para mim em meu ambiente de produção, pois tenho uma configuração que espera que tudo _next seja um ativo que passa por CDN. Esses arquivos json devem, em última instância, ser roteados por meio do assetPrefix (CDN), certo?

Eu tenho o mesmo problema.
Eu entendo que eles estão tentando aumentar esse limite, mas não sei quando será implantado.
Então, eu uso getStaticProps em todas as páginas e getStaticPaths apenas em algumas delas e funciona (minha página de produto gera 70% do total de páginas, então não coloquei nenhum getStaticPaths nela). Eu fico abaixo do limite, mas não é perfeito, o primeiro carregamento é bastante longo e difícil de lidar com erros 404.

Espero que eles aumentem o limite logo, porém espero que não seja 20K .. isso não será o suficiente para mim no longo prazo.

Eu quero evitar os primeiros tempos de carregamento com getStaticPaths .. Posso ter que procurar outras soluções além do Zeit Now

@erhankaradeniz e @ziltosh devemos lançar isso em breve. Se você gostaria de obter ajuda com isso o mais rápido possível, pode enviar um ping diretamente para mim ou [email protected] e eles irão resolver você.

Eu tenho o mesmo problema.
Eu entendo que eles estão tentando aumentar esse limite, mas não sei quando será implantado.
Então, eu uso getStaticProps em todas as páginas e getStaticPaths apenas em algumas delas e funciona (minha página de produto gera 70% do total de páginas, então não coloquei nenhum getStaticPaths nela). Eu fico abaixo do limite, mas não é perfeito, o primeiro carregamento é bastante longo e difícil de lidar com erros 404.

Espero que eles aumentem o limite logo, porém espero que não seja 20K .. isso não será o suficiente para mim no longo prazo.
Eu quero evitar os primeiros tempos de carregamento com getStaticPaths .. Posso ter que procurar outras soluções além do Zeit Now

@erhankaradeniz e @Ziltosh devemos lançar isso em geral muito em breve. Se você gostaria de obter ajuda com isso o mais rápido possível, pode enviar um ping diretamente para mim ou [email protected] e eles irão resolver você.

Obrigado @kvangundy
Entrei em contato com você no Twitter a respeito desse problema ;-)

@erhankaradeniz Você pode enviar um e-mail para [email protected] em vez disso? Dessa forma, ele acaba em nosso sistema corretamente.

@flintinatux , obrigado pela dica. Eu vi o exemplo, e ele não ajuda a carregar o componente da página antes de carregar os dados, então marcadores de posição in-page etc. não são possíveis. É um exemplo interessante, porém, obrigado!

Acho que não será abordado neste problema, o que significa que está fora do tópico, então encontrarei outro lugar para discuti-lo :)

Acho que a abordagem de dividir getInitialProps em getStaticProps & getServerProps é muito mais limpa! Tenho uma pergunta sobre como isso afeta nosso caso de uso:
Queremos criar 2 compilações separadas: uma versão estática para nosso site de produção e uma versão usando SSR para um ambiente de edição.

Eu estava pensando que poderia anexar condicionalmente getStaticProps vs getServerProps como métodos estáticos dependendo da compilação (semelhante a https://github.com/zeit/next.js/issues/9524#issuecomment- 558617056), mas não tenho certeza se isso será possível exportá-los condicionalmente como estão. Alguma ideia se isso será possível para suportar dinâmico / estático dependendo da construção?

Com relação a:

O RFC será atualizado para refletir as alterações posteriores, ainda iterando no uso do mundo real em nossos aplicativos.

Eu me pergunto se existe uma maneira de usar algum tipo de rota curinga para pegar rotas que são desconhecidas em tempo de construção. É incrível que eu possa renderizar páginas estáticas de, por exemplo, dados CMS, mas e se alguém adicionar um novo item? Não tenho uma página estática para isso. Esse problema me coça a cabeça por muito tempo.

Eu configurei uma rota dinâmica para processar páginas estáticas _pages / [slug] .js_. _getStaticPaths_ está obtendo todas as páginas que desejo renderizar estaticamente. Eu tenho _getStaticProps_ para consultar os dados e passá-los para a função de renderização. Todas as páginas fornecidas em _getStaticPaths_ são renderizadas como arquivos HTML dentro de _.next/server/static_ na construção. Excelente!

Agora eu executo npm run start e essas páginas como deveriam. Mas solicitar um url ausente (como _ / foo_) gera novos arquivos HTML e JSON estáticos dentro de _.next/server/static_. Isto não é bom. Como posso fazer o servidor redirecionar todos os outros urls para _pages / _error.js_?

https://github.com/zeit/next.js/issues/9524#issuecomment -582777067

Também estamos cobrindo isso.

Agora eu executo o npm run start e essas páginas como deveriam. Mas solicitar um url ausente (como / foo) gera novos arquivos HTML e JSON estáticos dentro de .next / server / static. Isto não é bom. Como posso fazer o servidor redirecionar todos os outros urls para pages / _error.js?

Isso ainda está em andamento e não é um comportamento inesperado no momento.

Mais uma vez, um lembrete de que você está usando um recurso experimental e que o comportamento pode mudar a qualquer momento. As coisas vão mudar e, potencialmente, quebrar entre todas as versões enquanto você usa isso quando não está estável.

@timneutkens Obrigado! Eu entendo a instabilidade. Tem alguma ideia de como administrar isso? Analisei o código e percebi que lançar um erro dentro de _unstable_getStaticProps_ renderiza a página de erro. Este pode ser um bom caminho a percorrer. Eu só precisaria de uma maneira de passar o erro adiante, pois é para _pages / _error.js_. Eu gostaria de enviar 404. Agora vai para 500.

Eu postei isso um monte de vezes antes em outros tópicos, mas "ir para _error" é um comportamento inesperado, a partir de agora sua página deve renderizar um estado 404. Basta dizer if(!data.something) { return <My404Component /> } , e então My404Component deve definir noindex meta tags.

Mesmo? A documentação instrui claramente o uso de _pages / _error.js_ para 404s.

Veja: https://nextjs.org/docs/advanced-features/custom-error-page

@ jiv-e que é para 404s causados ​​por:

  • página não encontrada
  • Arquivo não encontrado

Se você tiver rotas dinâmicas, terá que lidar com o caso "404" como eu disse, por exemplo, https://nextjs.org/docs/advanced-features/custom-error-page#reusing -the-built-in-error- página

Entendi! Obrigado!

Eu gostaria de usar getStaticProps para buscar as chaves de tradução / idioma no tempo de compilação porque elas provavelmente mudarão de 1 a 2 vezes por mês ou mesmo por ano. Também não precisa deles como JSON / props dentro do DOM. O problema é que não quero passar as chaves da árvore para o componente onde realmente as uso - Quais abordagens são adequadas para o meu caso de uso?

useTranslation () hook (ou HOC) com contexto?

Seria bom se AppTree fizesse parte do contexto NextGetStaticProps ( getStaticProps({ AppTree }) ). Caso contrário, não será possível executar coisas como apollos getDataFromTree no ssg.

Neste ponto, não estamos planejando permitir a passagem do AppTree em getStaticProps, pois isso é muito ruim para o desempenho (feedback consistente das empresas). Quando você adiciona getStaticProps a uma página, ele ainda passa por getInitialProps de _app para permitir a adoção incremental, portanto, ainda funcionaria com o Apollo.

Seria bom se pudéssemos ter amp: 'hybrid' e a funcionalidade SSG ao mesmo tempo.
Isso pode ser conseguido criando dois arquivos para uma página como esta, ou seja:

  • (SSG) index.html
  • (AMP) index.amp.html

Isso permitiria que os proxies resolvessem para um documento amp com base no parâmetro de consulta ?amp=1 .

Seria bom se pudéssemos ter amp: 'hybrid' e a funcionalidade SSG ao mesmo tempo.
Isso pode ser conseguido criando dois arquivos para uma página como esta, ou seja:

  • (SSG) index.html
  • (AMP) index.amp.html

Isso permitiria que os proxies resolvessem para um documento amp com base no parâmetro de consulta ?amp=1 .

Exatamente @Dacturne , esta é a única desvantagem que vejo em começar a usar SSG já em projetos, como estava comentando neste tópico há algum tempo.

🤞

@jansedlon Eu fiz uma postagem no blog respondendo à sua pergunta:

Eu me pergunto se existe uma maneira de usar algum tipo de rota curinga para pegar rotas que são desconhecidas em tempo de construção. É incrível que eu possa renderizar páginas estáticas de, por exemplo, dados CMS, mas e se alguém adicionar um novo item? Não tenho uma página estática para isso. Esse problema me coça a cabeça por muito tempo.

https://paqmind.com/en/blog/ssr-is-not-the-future

(não postando aqui porque é muito grande)

@ ivan-kleshnin Eu dei uma olhada rápida e parece super emocionante! Você só pode ter me salvado centenas de horas! Muito obrigado, vou dar uma olhada mais aprofundada mais tarde hoje.

https://github.com/zeit/next.js/issues/9524#issuecomment -582799948

@jansedlon como disse antes, estamos trabalhando em algo relacionado a isso que não é abordado na postagem do blog de @ivan-kleshnin. Espero poder compartilhar mais sobre isso em breve.

@timneutkens Adorei as mudanças até agora 🙏 Você tem planos de melhorar / suportar a estática + internacionalização completa?

Temos usado as novas APIs getStaticProps / getStaticPaths em nossa migração de tinacms.org de Gatsby para Next.js e até agora tem sido ótimo!

Um obstáculo que tivemos foi a geração de um feed RSS. Idealmente, gostaríamos de gerá-lo estaticamente, uma vez que o conteúdo ao qual ele faz referência é gerado estaticamente. Não vejo uma maneira de fazer isso atualmente, então, em vez disso, estamos apenas tratando do lado do servidor, consultando o conteúdo e escrevendo XML para a resposta.

Houve alguma discussão sobre o suporte à geração estática para tipos de conteúdo não HTML?

Para sua informação, começamos a usar getStaticProps no zeit agora e lançamentos usando o sinalizador --prod e o cache não estava sendo limpo para os arquivos json em novos lançamentos. Mudar nossa versão de produção de volta para o uso do recurso de alias funcionou e o cache foi limpo.

Temos usado as novas APIs getStaticProps / getStaticPaths em nossa migração de tinacms.org de Gatsby para Next.js e até agora tem sido ótimo!

Um obstáculo que tivemos foi a geração de um feed RSS. Idealmente, gostaríamos de gerá-lo estaticamente, uma vez que o conteúdo ao qual ele faz referência é gerado estaticamente. Não vejo uma maneira de fazer isso atualmente, então, em vez disso, estamos apenas tratando do lado do servidor, consultando o conteúdo e escrevendo XML para a resposta.

Houve alguma discussão sobre o suporte à geração estática para tipos de conteúdo não HTML?

Eu estava pensando por mim mesmo e acabei de descobrir isso. Aqui estão meus scripts:

"scripts": {
    "dev": " next",
    "build": "yarn sitemap && next build",
    "start": "next start",
    "sitemap": "ts-node --project ./cli/tsconfig.spec.json ./cli/generateSitemap.ts"
  },

Antes de next build é chamado de yarn sitemap que gera um mapa do site estaticamente. Você poderia usar a mesma técnica, para armazenar em cache todos os dados para json, por exemplo, que você precisará em getStaticProps e você pode reutilizá-los em várias páginas.

Atualizado o RFC, mudou um pouco o comportamento de getStaticPaths (você precisa retornar uma chave paths agora, isso espelha getStaticProps onde props deve ser retornado. a mudança ainda não chegou ao Next.js.

Também foi adicionada uma explicação para o comportamento de fallback (geração de segundo plano sob demanda de páginas que não foram exportadas no momento da compilação).

Fez outra atualização para o RFC, acrescentou explicação para as mudanças na navegação do cliente com relação a um estado Loading .

Podemos querer adicionar uma maneira para que os usuários saibam se o estado de carregamento está sendo renderizado por meio de um gancho React 🤔

Coisas boas! Eu estava pensando, haveria uma maneira de as páginas geradas estaticamente compartilharem dados entre várias rotas usando um único arquivo JSON (como divisão de código, mas para dados)?

Eu subi para a última canary build e imediatamente fui mordido pelo novo estado Loading . No passado, era bom supor com segurança que já obtive os dados corretos antes que a camada de visualização comece a renderizar. O carregamento assíncrono forçado é um grande afastamento disso. Eu realmente gostei de retirar todos os endpoints clichês que os novos endpoints SSR gerados automaticamente irão substituir, mas eu não planejava redesenhar cada página para incluir novos Loading estados.

Eu entendo o desejo de um TTFB mais rápido e, no futuro, isso pode ser bom para meu aplicativo. Mas seria possível tornar o estado Loading um recurso opt-in ou opt-out , semelhante ao fallback: false para getStaticPaths ? Talvez export const enableLoadingState = false na página ou em todo o site next.config.js .

https://github.com/zeit/next.js/issues/9524#issuecomment -583962425

Mais uma vez, um lembrete de que você está usando um recurso experimental e que estamos experimentando o comportamento atualmente.

Implantei meu site SSG (experimental) no Now (usando uma configuração padrão). Funciona bem, mas vejo erros 404 na guia de rede ao navegar no site. Todos os erros 404 apontam para _next/static/pages/[slug].js .

Este é o comportamento esperado enquanto é experimental? Ou devo alterar algumas configurações?

@joostmeijles , parece que você não está fornecendo os href e as corretos para next/link . Para páginas dinâmicas, href deve ser a página href='/[slug]' e as deve ser o URL as='/slug-1'

Estou recebendo 3 logs no console durante a compilação. Isso é um bug?

// Page is showing three logs despite static path only having 2 entries and output generating only two files as intended
export default function Page(props){
    console.log("Page - should only show twice", props); 
    return <><h1>Page</h1></>
}

export async function unstable_getStaticProps(props) {
    console.log("unstable_getStaticProps - should only show twice", props);
    return {
      props
    };

}

export async function unstable_getStaticPaths() {
    console.log("show once")
    return {
        paths: [
        { params: { year: "1901" } },
        { params: { year: "1902" } },
        ]
    }
}

Não, isso é esperado de acordo com fallback no RFC.

Não, isso é esperado de acordo com fallback no RFC.

export async function unstable_getStaticPaths() {
    console.log("show once")
    return {
        fallback: false,
        paths: [
        // This renders /blog/hello-world to HTML at build time
        { params: { year: "1901" } },
        { params: { year: "1902" } },
        ]
    }
}

Tentei desativar, mas estou recebendo este erro.

Erro: chaves extras retornadas de unstable_getStaticPaths em / [year] (fallback) O único campo permitido atualmente é paths

Mais uma vez, um lembrete de que você está usando um recurso experimental e que estamos experimentando o comportamento atual e nem tudo está implementado.

Este recurso getStaticProps estará disponível apenas para páginas?
Seria interessante para app / document também, por exemplo, buscar alguma configuração global para o aplicativo?

Eu implementei isso com 'sucesso' e estou feliz com os resultados até agora ... mas gostaria de saber se há alguma maneira de tornar as compilações subsequentes 'mais rápidas'? Por exemplo, verifique se as páginas geradas por SSG não foram alteradas e não as gere novamente. (Provavelmente pensamento positivo de mim)

@timneutkens Você tem planos de adicionar um gerador de sitemap.xml para páginas SSG? Não estou nem falando sobre rotas dinâmicas, pois acho que é mais fácil implementá-las apenas para páginas estáticas por enquanto.

@timneutkens Você tem planos de adicionar um gerador de sitemap.xml para páginas SSG? Não estou nem falando sobre rotas dinâmicas, pois acho que é mais fácil implementá-las apenas para páginas estáticas por enquanto.

Sim, essa seria uma ótima opção. Atualmente gerando um para mim com SSR. (mas o arquivo sitemap.xml leva muito tempo para carregar)

https://github.com/zeit/next.js/issues/9524#issuecomment -585293270

Inicialmente apenas para páginas, porque haverá outro trabalho que afetará getStaticProps depois que ele chegar.

https://github.com/zeit/next.js/issues/9524#issuecomment -586957539

Sim, mas não como parte deste RFC. Haverá um acompanhamento após este pousar.

@timneutkens Acho que a implementação de páginas SSG é fácil porque você pode enviar um URI para um array sempre que o Next constrói uma página estática e, quando terminar, apenas mapeie o array em cada tag XML, junte-o e insira-o no meio de uma tag <sitemapindex> . O getStaticProps poderia ter outra chave no objeto de retorno chamada excludeFromSitemap então o padrão seria todas as páginas a serem incluídas em sitemap.xml mas com uma opção de cancelamento.

Se fosse esse o caso, os desenvolvedores teriam um controle preciso sobre qual página estática iria para o mapa do site (por exemplo: se a página [foo] 's getStaticPaths função retornasse caminhos com foo params 'abc' e 'xyz' mas apenas o arquivo 'abc' deve estar no mapa do site, o desenvolvedor seria capaz de definir excludeFromSitemap para true se o parâmetro ==='xyz' em getStaticProps .

Além disso, para SSR e páginas estáticas, pode ser possível exportar uma constante (ou seja, export const excludeFromSitemap = true; ) do arquivo de página, assim como getServerProps , getStaticPaths e getStaticProps são exportados.

Em páginas SSG, se houver uma constante excludeFromSitemap exportada (padrão da página) e essa chave também estiver no objeto retornado da função getStaticProps (específico do caminho), o valor exportado deve atuar como padrão valor para todos os caminhos nessa página e o caminho específico excludeFromSitemap , quando presente no objeto getStaticProps , deve substituir o padrão da página (para que uma página pudesse fazer export cosnt excludeFromSitemap = true e, em seguida, adicione a chave excludeFromSitemap ao objeto retornado de getStaticProps com o valor false para excluir todos os caminhos do mapa do site, exceto aquele específico).

O código para anexar à matriz seria algo assim (eu calculei a tabela verdade e obtive a expressão booleana mínima com um mapa de Karnaugh):

//...somewhere else
const validExcludeFromSitemapTypes = ['boolean','undefined'];

//...for each path
const isSSG = !!getStaticPropsReturnedObj && typeof getStaticPropsReturnedObj === "object";
if(
    validExcludeFromSitemapTypes.indexOf(typeof pageExports.excludeFromSitemap)<0 ||
    (isSSG && validExcludeFromSitemapTypes.indexOf(typeof getStaticPropsReturnedObj.excludeFromSitemap)<0)
) {
    throw new Error("'excludeFromSitemap' can either be ommited (undefined) or be a boolean");
}
const defaultExcludedValue = !!pageExports.excludeFromSitemap;
const hasSpecificExcluded = isSSG && typeof getStaticPropsReturnedObj.excludeFromSitemap !== "undefined";
const specificExcludedValue =  isSSG ? !!getStaticPropsReturnedObj.excludeFromSitemap : false;

if(!specificExcludedValue && (!defaultExcludedValue || hasSpecificExcluded))
    sitemapURIs.push(correctlyEncodedURI);

Transformar a matriz no mapa do site seria tão fácil quanto fazer isso (assumindo que os URIs na matriz já estão codificados e filtrados por !excludeFromSitemap ):

function createSitemap(sitemapURIs: string[]): string {
    return `<sitemapindex>${sitemapURIs.map(u=>`<sitemap><loc>u/loc></sitemap>`).join('')}</sitemapindex>`;
}

Acho que esse recurso se encaixaria perfeitamente no Next.JS porque parte de sua missão é dar aos usuários a pontuação de 100 de SEO e ter sitemap.xml ajudaria muito! ( robots.txt também poderia ser gerado adicionando um else à condição que adiciona os caminhos à matriz do mapa do site para anexar esse caminho a outra matriz de páginas não permitidas)

Na versão de lançamento atual, ao usar a função unstable_getStaticPaths junto com unstable_getStaticProps , você não pode fazer chamadas de API para funções que vivem em /api/ .
Como o servidor não está rodando, é impossível fazer as solicitações correspondentes e gerar os props estáticos desta forma.
Você não precisa fornecer as funções de caminhos (o que basicamente torna esse SSR com um cache, o que ainda é bom!) Ou depender do SSR em vez do SSG.

Talvez isso seja uma boa adição para esse recurso? Não tenho certeza de qual seria a melhor maneira aqui, li uma proposta em outro lugar, que sugeria um atalho para a solicitação http, com SSR e /api rotas, isso seria útil aqui também.

Mas tudo isso, é claro, significaria executar código no ambiente de construção, que faria chamadas para outros serviços / chamadas db ou semelhantes. Isso deve ficar claro quando for implementado, mas seria uma adição interessante para esse recurso.

@reckter Sim, eu também fiz algo semelhante. Eu tive que conectar ao meu banco de dados para cada solicitação de página separada enquanto eles estavam sendo gerados estaticamente. Me senti muito estranho ...

Espero que não seja o caso de uso final

Seria bom ter algum tipo de script de inicialização que você pudesse configurar a partir do next.config ou algo assim ...

@reckter Uma maneira de

De qualquer forma, uma possível solução para acessar rotas de API durante SSG seria ter um servidor local executando apenas as rotas /api antes de compilar as páginas estáticas! Portanto, as etapas de construção seriam:

  1. Inicie um servidor (talvez chamado de "servidor de compilação api" ou algo parecido) servindo apenas as rotas /api
  2. Execute unstable_getStaticPaths
  3. Execute unstable_getStaticProps
  4. Compile as páginas estáticas

@reckter basicamente você não precisa chamar as rotas de API, você pode chamar a função que ele implementa diretamente, isso também evita muitos overheads causados ​​por http.

Basicamente, se você atualmente tem uma rota de API parecida com esta:

import myDb from 'mydatabaseprovider'
const db = myDb()

export default async (req, res) => {
  cont myData = await db.query('posts')
  res.json(myData)
}

Você mudaria para:

import myDb from 'mydatabaseprovider'
const db = myDb()

export async function getData() {
  const myData = await db.query('posts')
  return myData
}

export default (req, res) => {
  const myData = await getData()
  res.json(myData)
}

E então em sua página:

import {getData} from './api/myfunction'

export async function getStaticProps() {
  const myData = await getData()
  return {
    props: {
     myData
   }
  }
}

Seria complicado fazer o mesmo para APIs GraphQL. E também para a maioria REST.

Chamada de API! = Buscando do banco de dados (em geral)
Quase sempre há alguma lógica de negócios na camada de API, como renomeação de campo, reformatação de dados, etc.

Tenho certeza de que você tem motivos para proibir pages/api chamadas ... mas ignorar a API real não será fácil ou barato. E alguns milissegundos poupados não compensarão as taxas de código extra / complexidade IMO.

Também parece estranho que as solicitações para qualquer API sejam permitidas. Exceto o seu 🤷‍♂

usar unstable_getStaticPaths faz com que a página seja recarregada, perdendo o estado atual no redux, por exemplo. Esse comportamento será alterado no futuro?

editar: parece que este comportamento pode ser contornado usando a opção as em links ou roteador

<Link
  href='/item/[key]'
  as={`/item/${itemName}`}
>
router.push(
  '/item/[key]',
  `/item/${itemName}`
);

@meesvandongen sempre foi assim. Se o seu <Link> for inválido, ele o levará para a parte de back-end, basicamente funcionando como um <a> . Fragmentos dinâmicos como [key] devem ser emparelhados com os valores correspondentes.

@reaktivo pages/[lang]/blog/[id].js -> em getStaticPaths fornece todos os urls para renderizar estaticamente.

https://github.com/zeit/next.js/issues/9524#issuecomment -562625858
neste caso, é necessário adicionar getStaticPaths e getStaticProps função para cada página, exceto index.js.
Se houver algumas páginas mdx, o projeto é mais difícil de manter

considere mudar ou compatível com métodos estáticos getStaticPaths getStaticProps . https://github.com/zeit/next.js/issues/9524#issuecomment -558617056
Nesse caso, a página pode ser quebrada por função de ordem superior ou componente de ordem superior (HOC).
Dessa forma, o código é mais fácil de manter e mais conveniente para o typesscript.


tremor de árvore vs dinâmico. Que troca de dor de cabeça.😂

Com 9.2.3-canary.13 tentei usar fallback: false em getStaticPaths assim:

  return {
    fallback: false,
    paths: slugs.map(slug => ({params: {slug: slug}}))
  }

mas falha com o seguinte erro:

Error: Extra keys returned from unstable_getStaticPaths in /blog/[slug] (fallback) Expected: { paths: [] }

Com 9.2.3-canary.13 tentei usar fallback: false em getStaticPaths assim:

  return {
    fallback: false,
    paths: slugs.map(slug => ({params: {slug: slug}}))
  }

mas falha com o seguinte erro:

Error: Extra keys returned from unstable_getStaticPaths in /blog/[slug] (fallback) Expected: { paths: [] }

Eu acho que você precisa do mapa um nível mais alto, então map retorna o objeto que você tem atualmente, mas com um slug único. em vez de mapear nos caminhos.

Ainda não atualizei minha versão no nextjs, mas deve ser semelhante:

return data.map(item => {
    return {
      params: {
        slug: item.slug,
      },
    }
  })

@jorngeorg é um PR aberto: https://github.com/zeit/next.js/pull/10701

Contribuição fantástica! Realmente melhora o processo de renderização estática.

Eu recomendo adicionar aos documentos que em rotas dinâmicas, o "fallback" será gerado sem qualquer chamada para getStaticProps - significando que você deve codificar seu componente para considerar o caso em que props está vazio.

Como alternativa, você pode alterar o comportamento para chamar getStaticProps sem contexto ao criar o fallback. Isso seria consistente com como next export funciona atualmente (por exemplo, /p/[id].js é exportado para /p/[id].html executando seu getInitialProps sem contexto).

  • getStaticProps - Aceite a geração estática (SSG) no momento next build .
  • getServerProps - Opte pela renderização do lado do servidor (SSR), que renderiza sob demanda.

10722

Renomeie getServerProps para getServerSideProps.

Eu recomendo adicionar aos documentos que em rotas dinâmicas, o "fallback" será gerado sem qualquer chamada para getStaticProps - significando que você deve codificar seu componente para considerar o caso em que props está vazio.

Bom ponto de mencionar isso! Eu também tive alguns erros de construção / implantação porque não percebi isso.

Atualizado o RFC para refletir as mudanças

@timneutkens

  • A solicitação subsequente para o mesmo caminho exibirá a página gerada

Presumo que isso significa que Next.js armazenará em cache a página gerada. Este é um cache na memória? Este cache é limitado por limites ou isso pode resultar em vazamentos de memória?

Quando você usa next start ele usa lru-cache semelhante ao exemplo de cache atual, atualmente o limite padrão é 50 MB, podemos torná-lo configurável mais tarde: https://github.com/zeit/next.js/ blob / canary / packages / next / next-server / server / spr-cache.ts # L90

Quando você hospeda no ZEIT Agora, a geração e o armazenamento em cache acontecem no CDN / Proxy, então funciona um pouco diferente e você nunca precisa se preocupar com vazamentos de memória ou se estiver ultrapassando o limite de lru.

👍 ok, parece razoável. Isso é mais ou menos o que eu tinha em mente como um comportamento padrão sensato.

  • getStaticProps - Aceite a geração estática (SSG) no momento next build .
  • getServerProps - Opte pela renderização do lado do servidor (SSR), que renderiza sob demanda.

10722

Renomeie getServerProps para getServerSideProps.

Por que renomear? IMHO getServerProps é preciso o suficiente e mais curto para digitar, adicionando Side parece redundante para mim.

Eu queria saber se há alguma alteração feita no método getStaticPaths? Minhas páginas dinâmicas não são mais geradas como páginas estáticas, elas são exportadas como funções lambda agora?

Estou correto quando o comportamento padrão agora é que as páginas são primeiro renderizadas como lambda e somente depois de visitar uma página específica a página é gerada para uma página estática? (assim como mencionado no substituto)

@erhankaradeniz Nenhuma mudança foi feita em getStaticPaths que resultaria em sua (s) página (s) sendo Lambdas. Provavelmente é um erro de uso.

Você pode mostrar seu código para que possamos identificar o problema?

@Timer, por enquanto, voltei para [email protected], onde ainda posso usar parâmetros, até descobrir por que não está funcionando com caminhos.

é assim que eu atualmente gerei meus caminhos:

return cityData.map(city => {
    return {
      params: {
        country: city.countrySlug,
        city: city.slug,
      },
    }
  })

e em outra página eu faço:

return cityData.map(city => {
    return {
      params: {
        country: city.countrySlug,
        city: city.slug,
      },
    }
  })

não conseguiu convertê-lo para o novo lançamento canário com os caminhos. Devo estar fazendo algo errado, porque console.logs nem mesmo são acionados dentro de getStaticPath

Tenho problemas com pré-renderização de caminho aninhado e SSG:

// pages/[lang]/[...slugs].js

export async function getStaticPaths() {
  let knex = await import("knex/client").then(m => m.default)
  let pages = await knex("page").select(["lang", "url"])
  return {
    fallback: true,
    paths: pages.map(page => {
      return {
        params: {
          lang: page.lang,
          slugs: page.url == "/" ? [] : page.url.slice(1).split("/"),
        }
      }
    }),
  }
}

leva a

Error occurred prerendering page "/en/". Read more: https://err.sh/next.js/prerender-error:
Error: The provided export path '/en/' doesn't match the '/[lang]/[...slugs]' page.

para a página inicial. Por algum motivo, o NextJS não corresponde

{lang: "en", slugs: []}

para

/[lang]/[...slugs]

Se eu fornecer {lang: "en", slugs: ["/"]} ele cria, mas com um URL errado:

├ ● /[lang]/[...slugs]      875 B        204 kB
├   ├ /en/credits
├   ├ /en/%2F

Para registro, getServerSideProps funciona bem com uma configuração semelhante.

Eu sei que é experimental, mas este tópico é para dar feedback, certo?

pages/[lang]/[...slugs].js corresponde a /en/abcdef e não a /en , para isso você atualmente deve criar pages/[lang]/index.js .

Há uma solicitação de recurso aberta para isso: https://github.com/zeit/next.js/issues/10488

Em primeiro lugar, isso é incrível. Eu esperava ter algo assim no Next.js para que eu pudesse finalmente me afastar do Gatsby.js e ter um aplicativo híbrido (estático + dinâmico).

🚀 Eu tentei a versão do aplicativo complexo canário e meio cozido funcionou bem. Confesso que não li todos os comentários aqui, mas não tenho certeza se o tremor de árvore já foi implementado.

🤔 getStaticPaths parece muito mais com setStaticPaths onde estamos definindo o caminho estático para o comportamento SSG. Isso meio que me confundiu um pouco.

🧐 Eu me pergunto se podemos melhorar os tempos de construção com categorias de construção? Sei que isso complicaria a configuração, mas valerá a pena. Deixe-me explicar:

E se tivermos algo como setBuildCategory que defina como blog ou pages ou o que alguém quiser 2020-content . Em seguida, o construtor SSG procura a categoria da página que foi alterada e apenas tenta reconstruir essa categoria a partir de uma combinação de cache + nova renderização. Algo como isso pode nos ajudar a tornar o SSG mais rápido e evitar grandes tempos de construção para coisas que não são passíveis de mudança, mas ainda podem mudar, portanto, não podem ser arquivadas.

Se isso faz algum sentido; fico feliz em atender uma ligação e conversar sobre isso.

Como lidar com getServerSideProps com implementação de servidor personalizado?

if (pathname === '/a') {
  app.render(req, res, '/b', query)
}

No exemplo acima, visitar /a renderizará a página pages/b.js . Mas um redirecionamento do lado do cliente para /a tenta baixar a.json arquivo, que não existe neste caso.

Devemos ter condições semelhantes para solicitações de /_next/data/{BUILD_ID}/{PAGE}.json para renderizar arquivos JSON diferentes?

Para usar fallback: true em getStaticPaths, como obtenho o objeto req? Atualmente, parece que não posso. Preciso disso é pegar alguns cookies do navegador para autenticar uma rota

@tylermcrobert como você se imagina pegando biscoitos quando não há pedido algum ?!
Rotas com back-end dependendo de solicitações reais de visitantes não podem ser tornadas estáticas por definições de "estático" e "dinâmico". Não quer dizer que você não pode combinar static e auth ... é apenas a parte de autenticação que pertencerá à API e ao código do cliente em vez de páginas.

Como lidar com getServerSideProps com implementação de servidor personalizado?

if (pathname === '/a') {
  app.render(req, res, '/b', query)
}

No exemplo acima, visitar /a renderizará a página pages/b.js . Mas um redirecionamento do lado do cliente para /a tenta baixar a.json arquivo, que não existe neste caso.

Devemos ter condições semelhantes para solicitações de /_next/data/{BUILD_ID}/{PAGE}.json para renderizar arquivos JSON diferentes?

Next.js oferece suporte a parâmetros de rota dinâmica, portanto, o remapeamento em um servidor personalizado raramente é mais necessário: https://nextjs.org/docs/routing/dynamic-routes

A abordagem que você delineou já não funciona com <Link> (causaria uma transição de página inteira), portanto getServerSideProps já funciona.

@tylermcrobert como você se imagina pegando biscoitos quando não há pedido algum ?!
Rotas com back-end dependendo de solicitações reais de visitantes não podem ser tornadas estáticas por definições de "estático" e "dinâmico". Não quer dizer que você não pode combinar static e auth ... é apenas a parte de autenticação que pertencerá à API e ao código do cliente em vez de páginas.

Talvez eu esteja entendendo mal a opção de reserva nesse caso. O que você está dizendo faz sentido no contexto de tempo de construção.

fallback: true não é para quando não existe uma rota predefinida? Nesse caso, um substituto seria alcançado a partir do navegador, não?

@tylermcrobert yes fallback: true case tem uma solicitação, mas a API deve ser unificada pelo "menor denominador comum". Não consigo imaginar um sistema funcional em que tudo seja construído com um conjunto de premissas e, em seguida, atualizado de forma incremental com um conjunto de premissas totalmente diferente. Será um desastre apoiar.

Acho que você perdeu o ponto de que essas compilações incrementais ainda serão armazenadas em cache entre as compilações. Portanto, a função do primeiro visitante influenciará o resultado da construção para todos os usuários subsequentes! Parece uma má ideia.

@ ivan-kleshnin eu entendo e certamente concordo. A razão de eu perguntar é por causa do meu caso de uso específico.

Estou usando um CMS sem cabeçalho que permite a funcionalidade de visualização para que as páginas que precisam ser visualizadas não sejam incluídas no momento da compilação (porque a entrada que está sendo visualizada não existia neste momento). Achei que esse era um caso em que a opção de reserva entraria.

Para acessar essa visualização, preciso acessar a referência de visualização da API que é fornecida por meio de cookie.

É este um caso em que devo simplesmente descartar useStaticProps inteiramente? Eu odiaria perder o benefício das compilações estáticas porque não consigo visualizar meus documentos.

A atratividade desse RFC em relação a algo como o gatsby é que ele nos dá "controle híbrido" com geração de sites estáticos que torna menos trabalhoso trabalhar com CMSs sem cabeça

Estou usando um CMS sem cabeçalho que permite a funcionalidade de visualização para que as páginas que precisam ser visualizadas não sejam incluídas no momento da compilação (porque a entrada que está sendo visualizada não existia neste momento). Achei que esse era um caso em que a opção de reserva entraria.

Fique ligado, mais em breve 🕵

Portanto, se entendi corretamente, podemos usar o fallback true quando, por exemplo, no meu caso, um usuário se registrar (nenhuma página estática é gerada, pois é uma nova página / usuário), mas quando o perfil recebe uma visita, ele é gerado automaticamente?

Erhan Karadeniz
http://www.erhankaradeniz.com

Em 4 de março de 2020, às 20:25, Tim Neutkens [email protected] escreveu:


Estou usando um CMS sem cabeçalho que permite a funcionalidade de visualização para que as páginas que precisam ser visualizadas não sejam incluídas no momento da compilação (porque a entrada que está sendo visualizada não existia neste momento). Achei que esse era um caso em que a opção de reserva entraria.

Fique ligado, mais em breve 🕵

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub ou cancele a inscrição.

Os dados do usuário são um mau exemplo, pois você deseja obter esse lado do cliente. Fallback existe para páginas de geração estática sob demanda que não foram geradas no momento da construção. Por exemplo, você pode querer gerar os 100 principais posts do blog no momento da construção e não gerar outros com menos tráfego.

O Google Docs será enviado para ele em breve.

Sim, o que eu quis dizer é uma página de espaço reservado .. Eu realmente buscaria dados do usuário no lado do cliente.

@timneutkens Haverá alguma maneira de excluir ou reconstruir páginas específicas geradas estaticamente?

Oi!!! Parece o aplicativo ideal. Eu amo React e Next !!! Tornou tudo tão elegante e simples para nós usarmos !! Mas o exemplo inclui o blog de noção. Gostaria de ver um exemplo de uma implementação ao consultar um CMS Headless e fazer a busca feita por página / postagem como uma exportação como um item estático.

// gritos, já que é quase sexta !!!

@timneutkens isso é emocionante 👌

Um cenário que encontramos com frequência e ainda não tenho uma solução perfeita com next.js ou gatsby, exceto rotas dinâmicas ou geração de projetos em loop:

Por razões históricas, temos que lidar com vários domínios (e não há vontade de mudar isso) que veiculam as mesmas / exatas páginas com exceção de preços, moeda, números de telefone de suporte e seletores de idioma. Por natureza, a maioria dessas páginas de marketing são bastante estáticas e seria suficiente criá-las diariamente ou semanalmente (em vez de tê-las para renderizar a cada solicitação).

Minha pergunta / pensamento: você vê uma maneira (no futuro?) De getStaticPaths gerar páginas com base em algo que não é um parâmetro de rota, mas poderia ser usado em um nível de solicitação para alternar entre eles (por exemplo, sem servidor a função retorna um resultado estático pré-construído com base em locale )

Concretamente, isso significaria que https://mysite.com/my-product e https://mysite.co.uk/my-product serviriam a duas páginas estáticas diferentes, mas sem ter que gerar nosso próximo aplicativo 50 vezes ou ter que atingir um CMS em cada solicitação😅

Agradecemos antecipadamente e gostariamos de saber sua opinião, especialmente se isso for algo para o futuro que possa ser resolvido / contornado ❤️

Estou pensando em um caso de uso em que desejo usar SSG para páginas de destino de alto tráfego para SEO e para reduzir a carga do servidor, mas ainda quero que os dados atuais sejam usados ​​após a hidratação e no roteamento do lado do cliente para esta página. Isso seria possível?

Então, basicamente, no roteamento do lado do cliente para esta página, o comportamento deve ser como getInitialProps (os dados atuais são buscados antes que a página se torne visível). E no roteamento do lado do servidor para esta página, o html estático deve ser servido e hidratado e, em seguida, (opcionalmente) algumas respostas da API buscadas para atualizar alguns dados na página.

Joguei com unstable_getStaticProps apenas para experimentar e me deparei com um conflito divertido: é difícil usar rotas de API com getStaticProps .

Não preste atenção na semântica do código, mas apenas no fluxo de busca de dados:

// pages/api/healthcheck.ts
import { NextApiResponse, NextApiRequest } from 'next';

export type ApiHealthCheckResponse = {
  message: 'ok';
};

const healthCheckHandler = (
  req: NextApiRequest,
  res: NextApiResponse<ApiHealthCheckResponse | ''>,
) => {
  if (req.method === 'GET') {
    return res.status(200).json({ message: 'ok' });
  }

  return res.status(405).send('');
};

export default healthCheckHandler;
// pages/index.js
// ...

export async function unstable_getStaticProps() {
  return {
    props: {
      healthcheck: (await fetch('localhost:3000/api/healthcheck').json())
    },
  };
}

A construção da página travará no momento da construção porque o servidor não está funcionando. Não tenho certeza se este é um caso de uso válido, já que getStaticProps não deve ser usado com nada muito dinâmico, mas achei que era um caso de uso interessante para compartilhar (posso imaginar totalmente um endpoint da API Route encarregado de obter dados de outra API e reformate-os.

@martpie Você pode querer verificar este comentário: https://github.com/zeit/next.js/issues/9524#issuecomment -589772756

O suporte para geração de site estático de próxima geração (SSG) foi lançado como estável no Next.js 9.3!

Esta versão também inclui suporte para "Modo de visualização" ou a capacidade de ignorar a página pré-renderizada estaticamente e renderizar a página sob demanda para usuários autorizados .

Você pode ler mais sobre isso em nossa postagem do blog . Se você estiver mais prático, vá direto para nossos documentos !

Poste suas perguntas na comunidade Next.js do GitHub !

Isso é tão legal! Obrigado pelo trabalho árduo!

Este novo recurso não parece funcionar com saga e redux agora

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