Next.js: Улучшения статической генерации / SSG

Созданный на 25 нояб. 2019  ·  250Комментарии  ·  Источник: vercel/next.js

Резюме

Позвольте Next.js стать полностью гибридным, предоставляя методы для статической генерации и рендеринга на стороне сервера для каждой страницы.

  • Два новых метода выборки данных для каждой страницы

    • getStaticProps - включение статической генерации (SSG) в next build time.

    • getServerSideProps - Включите рендеринг на стороне сервера (SSR), который рендерится по запросу.

  • Новый метод статической генерации (SSG) набора маршрутов из динамических источников.

    • getStaticPaths - Возвращает список параметров для динамических маршрутов для статической генерации (SSG)

В этом RFC рассматриваются исключительно дополнения API. Все новые функции полностью обратно совместимы и могут быть адаптированы постепенно. Этот RFC не содержит устаревших рекомендаций.

Фон

При создании веб-сайтов или веб-приложений вам обычно приходится выбирать между двумя стратегиями: статическая генерация (SSG) или рендеринг на стороне сервера (SSR).

Next.js вместо этого позволяет создавать гибридные приложения, которые позволяют выбирать для каждой страницы, какую стратегию использовать. Начиная с Next.js 9, страницы без getInitialProps оптимизируются статически и выводятся как файлы .html после next build .

Однако вы можете захотеть выполнить выборку данных при создании статических страниц для вашего конкретного варианта использования.

Например, для статической генерации маркетинговых страниц из раздела CMS или блога на сайте.

В этом случае использование getInitialProps переключит вас на SSR.

Next.js в настоящее время имеет команду next export , которая делает приложение полностью SSG, теряя гибридную природу Next.js.

Если вы используете next export с getInitialProps возникает другая проблема. getInitialProps вызывается во время сборки (что отлично), но затем, когда вы используете next/link для перемещения между страницами getInitialProps вызывается на стороне клиента, вместо использования next export результат.

Это также означает, что источник данных (конечная точка CMS / API) вызывается непосредственно при переходах на стороне клиента, если ваш источник данных не работает, переходы на стороне клиента прерываются при перемещении между страницами.

Мы сотрудничали с активными пользователями SSG и next export в Next.js, такими как HashiCorp (спасибо @jescalan), и тщательно исследовали правильные ограничения для введения двух новых методов выборки данных: getStaticProps и getServerSideProps . Но также способ предоставить параметры для статической генерации статических страниц для динамических маршрутов: getStaticPaths (замена exportPathMap каждой страницы).

Эти новые методы имеют много преимуществ по сравнению с моделью getInitialProps поскольку существует четкое различие между SSG и SSR.

  • getStaticProps отмечает страницу, которая будет статически сгенерирована во время сборки (при запуске next build )
  • getStaticPaths позволяет возвращать список параметров для генерации во время сборки для динамических маршрутов.
  • getServerSideProps отмечает страницу, отображаемую на стороне сервера при каждом запросе, и наиболее похоже на текущее поведение getInitialProps при использовании сервера.

Разделение этих методов также позволяет нам предоставить правильный объект контекста, который можно ввести с помощью TypeScript. Когда вы выбираете конкретную стратегию рендеринга, вы получаете правильные значения, в настоящее время с getInitialProps вы должны угадать, что доступно на SSG по сравнению с SSR при использовании TypeScript.

Более того, сделав эти методы явными, мы сможем более четко задокументировать различные компромиссы.

Реализация

Обратите внимание, что все эти методы находятся на верхнем уровне в файле компонента страницы и не могут быть вложенными, как getInitialProps .

getStaticProps

Использование getStaticProps означает, что страница будет отображаться статически во время сборки (SSG).

Этот новый метод позволит вам выполнять выборку данных для страницы, которая будет статически сгенерирована в файл .html за next build time.

Next.js также автоматически сгенерирует файл JSON, содержащий результат getStaticProps при next build time. Это используется для маршрутизации на стороне клиента.

При маршрутизации на стороне клиента через next/link или next/router Next.js будет извлекать этот файл JSON, чтобы получить реквизиты, необходимые для рендеринга страницы на стороне клиента.

Свойства возвращаются под ключом props чтобы в будущем можно было ввести другие параметры.

// 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: {}
  };
}

context будет содержать:

  • params - Параметры при динамическом маршруте.

getStaticPaths

Это расширение для использования getStaticProps для динамических маршрутов.

getStaticPaths заменяет необходимость наличия exportPathMap и работает на каждой странице.

Поскольку вам может потребоваться статически сгенерировать список URL-адресов с динамическим параметром, как в примере ниже slug . Next.js предоставит метод getStaticPaths который позволяет возвращать список URL-адресов. Поскольку это метод async вы также можете получить этот список из источника данных, такого как ваша 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" } }
    ]
  };
}

Отступать

Во многих случаях вы можете не захотеть предварительно визуализировать все возможные маршруты в вашем приложении во время сборки (например, если у вас есть миллионы продуктов). По этой причине Next.js автоматически сгенерирует страницу fallback которая представляет собой визуализацию страницы без данных (чтобы можно было показать состояние загрузки), когда страница еще не была сгенерирована.

Точное поведение сервировки будет:

  • Входящий запрос

    • Next.js проверяет, был ли путь создан во время сборки

    • Если путь был сгенерирован



      • служить напрямую



    • Если путь не был сгенерирован



      • Обслуживайте запасной вариант


      • Next.js отображает страницу (с данными) в фоновом режиме и добавляет ее в список сгенерированных страниц.


      • Последующий запрос по тому же пути будет обслуживать сгенерированную страницу.


      • Это гарантирует, что у пользователей всегда будет быстрый опыт и никогда не будет медленного TTFB из-за серверного рендеринга, сохраняя при этом быстрые сборки и свойства статической генерации.



Если вы хотите, чтобы пути, которые не были созданы во время сборки, приводили к ошибке 404, это также возможно путем возврата fallback: false из 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

При использовании getServerSideProps страница не создается статически (SSG), а вместо этого отображается по запросу при каждом запросе к серверу (SSR).

Next.js также автоматически предоставляет конечную точку API, которая возвращает результат вызова getServerSideProps . Это используется для маршрутизации на стороне клиента.

При маршрутизации на стороне клиента через next/link или next/router Next.js будет извлекать эту открытую конечную точку API, чтобы получить данные JSON, которые превращаются в реквизиты, необходимые для рендеринга страницы на стороне клиента.

Этот метод наиболее похож на текущий метод getInitialProps , с основным отличием в том, что getServerSideProps всегда выполняется на стороне сервера, а не в браузере. Либо при рендеринге на стороне сервера, либо при выборке API при маршрутизации на стороне клиента.

Аналогично getStaticProps свойства возвращаются под ключом 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: {}
  };
}

context будет содержать:

  • params - Параметры динамического маршрута
  • req - объект HTTP-запроса
  • res - объект HTTP-ответа
  • query - Строка запроса (не совсем уверена в этом, но, вероятно, нужна)

Автор: @timneutkens , @Timer , @ijjk , @lfades. Сотрудничал с @rauchg , @jescalan и другими 🚀

Самый полезный комментарий

Поддержка генерации статических сайтов следующего поколения (SSG) стала стабильной в Next.js 9.3!

Этот выпуск также включает поддержку «режима предварительного просмотра» или возможность обхода статически предварительно отображаемой страницы и визуализации страницы по запросу для авторизованных пользователей .

Вы можете прочитать об этом в нашем блоге . Если у вас больше возможностей, сразу переходите к нашей документации !

Все 250 Комментарий

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: {}
  };
}

Мне интересно узнать, при каких обстоятельствах нам нужно будет вернуть дополнительные данные, кроме тех, которые могут содержаться в props . Я нашел встроенное объяснение «для дальнейшего контроля поведения на странице» немного расплывчатым.

Смотрится очень интересно! Будет ли он заменой getInitialProps или рядом? Например, для нашего случая использования API извлечения данных является общедоступной службой. Таким образом, при навигации на стороне клиента мы ожидаем, что клиент будет напрямую вызывать уровень API, тогда как в SSR его вызывает сервер. Забегая вперед, будет ли этот вариант использования по-прежнему решаться предыдущим методом?

Мне интересно узнать, при каких обстоятельствах нам нужно будет вернуть дополнительные данные, кроме тех, которые могут содержаться в props . Я нашел встроенное объяснение «для дальнейшего контроля поведения на странице» немного расплывчатым.

Это больше касается будущей проверки метода, чтобы мы могли расширить его позже, если это необходимо.

Смотрится очень интересно! Будет ли он заменой getInitialProps или рядом? Например, для нашего случая использования API извлечения данных является общедоступной службой. Таким образом, при навигации на стороне клиента мы ожидаем, что клиент будет напрямую вызывать уровень API, тогда как в SSR его вызывает сервер. Забегая вперед, будет ли этот вариант использования по-прежнему решаться предыдущим методом?

В целом у такого поведения есть некоторые недостатки, например, загрузка водопада, которая может быть медленной из определенных областей по всему миру. Подход getServerProps позволяет более эффективно кэшировать ответ.

Это выглядит действительно интересно! Классная идея!

Хотя у меня есть опасения по поводу развертывания ...

Представим, что я принимаю сейчас хостинг.
Для первого развертывания очевидно, что все приложения строятся на развертывании.

Затем я изменяю некоторый контент в CMS и пытаюсь запустить перестройку только страниц SSG, но код приложения не изменился.

Сразу же срабатывает сигнал тревоги, что в этом случае, если я запускаю сборку, есть два возможных решения:

1) Ничего не перестраивается, так как все кешируется - код не менялся и блабла.
2) Я --force это, и теперь "все" перестраивается, но мне нужно было перестроить только страницы SSG.

_Это всего лишь гипотезы, так как это зависит от самих систем сборки - насколько они осведомлены о Next_

Это, вероятно, повлияет на любое другое решение для хостинга.

Далее у себя есть .next/cache ... как бы это обойти это?

@joltmode, который в настоящее время имеет место для каждого генератора статических сайтов. .next/cache сохраняется между развертываниями в Now и используется повторно. Имейте в виду, что в настоящее время вы, вероятно, используете getInitialProps для этого случая с кешированием (потенциально https://zeit.co/blog/serverless-pre-rendering), которое динамически отображается в бессерверной функции, а затем кэшируется в нашем CDN, это поведение по-прежнему в порядке и будет продолжать работать, если вы используете getServerProps .

Действительно потрясающе, прекрасно вписывается в то, как мы используем Next для клиентских проектов, и удалял бы некоторый шаблонный код, который мы копируем.

Одна вещь, которую следует учитывать, - это именование getStaticProps и getServerProps, если они вернут {props} и другие возможные варианты в будущем, не будет ли * Props сбивать с толку? Может быть, getStaticConfiguration, getStaticSetup, getStaticOptions были бы более общими?

@kibs возвращаемые значения всегда будут относиться к тому, как обрабатываются реквизиты. Так что с именами все в порядке.

Это просто круто! Это решает все варианты использования и потребности, которые у меня были в последнее время или о которых я мог подумать при разработке как частных, так и профессиональных веб-приложений. Вы только что помешали мне запустить собственный генератор гибридных сайтов, спасибо!

Я также могу сказать, что новые методы лучше предыдущих getInitialProps() и exportPathMap() , что поначалу меня немного сбивало с толку, когда я начал использовать Next.js и покопался в SSR / SSG. Постраничный подход для меня тоже имеет больше смысла.

Не могу дождаться, чтобы попробовать это!

Небольшое примечание: в последнем примере я думаю, что в getServerProps() отсутствует параметр context .

Замечание: в последнем примере я думаю, что getServerProps () не хватает параметра контекста.

Фиксированный!

Звучит здорово! Я просто задаюсь вопросом с точки зрения пользователя TypeScript, если бы getStaticProps , getStaticPaths и getServerProps качестве статических методов в компоненте страницы (например, getInitialProps на данный момент) легче набирать / правильно использовать.

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 проблема с этим подходом в том, что встряхивать дерево становится значительно труднее (читай: почти невозможно). Это означало бы, что ненужный код будет отправлен в браузер.

@timneutkens - хороший

// 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, мы можем надежно встряхнуть дерево, но мы также все еще обсуждаем возможность создания отдельного файла. Лично я предпочитаю однофайловый подход.

Смотрится очень интересно! Будет ли он заменой getInitialProps или рядом? Например, для нашего случая использования API извлечения данных является общедоступной службой. Таким образом, при навигации на стороне клиента мы ожидаем, что клиент будет напрямую вызывать уровень API, тогда как в SSR его вызывает сервер. Забегая вперед, будет ли этот вариант использования по-прежнему решаться предыдущим методом?

В целом у такого поведения есть некоторые недостатки, например, загрузка водопада, которая может быть медленной из определенных областей по всему миру. Подход getServerProps позволяет более эффективно кэшировать ответ.

Конечно, но я говорю о том, чтобы вообще не использовать RTT для реагирующего сервера. Рассмотрим случай, когда вывод SSR с сервера кэшируется на прокси-сервере CDN / cache. Добавьте к этому выборку данных для клиентской навигации, напрямую вызывающую другой уровень API (общий для веб / приложений / всех клиентов), это означает, что уровень сервера Next.js не нужно увеличивать так сильно в сценарии с высоким трафиком.

Я понимаю вашу точку зрения на водопадные выборки, но предоставление потребителям возможности рассматривать сервер Next как слой SSR по сравнению с источником данных позволит значительно улучшить настройки масштабирования.

Смотрится очень интересно! Будет ли он заменой getInitialProps или рядом? Например, для нашего случая использования API извлечения данных является общедоступной службой. Таким образом, при навигации на стороне клиента мы ожидаем, что клиент будет напрямую вызывать уровень API, тогда как в SSR его вызывает сервер. Забегая вперед, будет ли этот вариант использования по-прежнему решаться предыдущим методом?

В целом у такого поведения есть некоторые недостатки, например, загрузка водопада, которая может быть медленной из определенных областей по всему миру. Подход getServerProps позволяет более эффективно кэшировать ответ.

Конечно, но я говорю о том, чтобы вообще не использовать RTT для реагирующего сервера. Рассмотрим случай, когда вывод SSR с сервера кэшируется на прокси-сервере CDN / cache. Добавьте к этому выборку данных для клиентской навигации, напрямую вызывающую другой уровень API (общий для веб / приложений / всех клиентов), это означает, что уровень сервера Next.js не нужно увеличивать так сильно в сценарии с высоким трафиком.

Я понимаю вашу точку зрения на водопадные выборки, но предоставление потребителям возможности рассматривать сервер Next как слой SSR по сравнению с источником данных позволит значительно улучшить настройки масштабирования.

Я думаю, вы неправильно понимаете, что это новое поведение означает, что вы действительно можете кэшировать полные результаты в CDN, учитывая, что CDN поддерживает динамические ответы. Раньше это было невозможно с getInitialProps.

@timneutkens Я играл с babel-plugin-preval на getStaticProps . У меня проблема с fs .

Я пытаюсь прочитать .md файлы моего каталога ./pages/blog/ и просмотреть их, чтобы я мог сделать страницу индекса блога со всеми моими сообщениями.

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;

Этот код приводит к этой ошибке:

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

IIRC от Razzle, эта ошибка связана с заглушками файловой системы webpack (или их отсутствием). Думаю, однажды я исправил это с помощью Razzle, добавив это в конфигурацию webpack.

node: {
  fs: "empty";
}

Я пробовал следующий файл next.config.js, но он просто устраняет ошибку. Однако похоже, что fs / fs-extra самом деле не работает, или работает, и, возможно, пути нет (мне непонятно). Есть мысли по этому поводу?

Мой другой вопрос, в более общем плане, заключается в том, что, по вашему мнению, будет лучше всего использовать import vs. require в getStaticProps . Если я не ошибаюсь, мой приведенный выше фрагмент попытается изоморфно импортировать fs-extra в React ??. Не лучше ли было бы изменить импорт на встроенный, как это?

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

Я думаю, вы неправильно понимаете, что это новое поведение означает, что вы действительно можете кэшировать полные результаты в CDN, учитывая, что CDN поддерживает динамические ответы. Раньше это было невозможно с getInitialProps.

Ах, я думаю, я понял, что ты имеешь в виду. Означает ли это, что getServerProps в первом поколении SSR создаст уникальную конечную точку в хеш-коде с адресацией содержимого, возможно, в URL-адресе, который мы затем сможем кэшировать в CDN? Единственным недостатком этого может быть то, что указанный кеш не будет использоваться совместно между приложениями, отличными от Next (android / ios), и приложениями Next. Кроме того, с внешним источником данных директивы управления кешем находятся в восходящем направлении, но здесь, поскольку Next будет брать на себя ответственность за обслуживание данных, нам нужны API или реквизиты, чтобы указать их для конечных точек сгенерированных данных.

@jaredpalmer Я предполагаю, что https://github.com/zeit/next.js/issues/9524#issuecomment -558628066 (включая мою озабоченность по поводу надежной раскачиваемости дерева ) будет решен путем наличия отдельного файла, который будет скомпилирован полностью отдельно от код клиентского пакета? Например

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

or:

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

Встряхивание дерева

Как всегда, спасибо за все, что вы делаете. Работать с Next.js было абсолютным удовольствием, и, как я уже говорил ранее, почти каждый выпуск функции позволяет нам уменьшить размер кодовых баз, которыми я управляю. Это потрясающе.

Трудно критиковать этот RFC, поскольку, как написано, он сразу же полезен для МНОЖЕСТВА приложений. Однако я хочу обратиться к одной строке, с которой я не уверен, что согласен:

« getStaticPaths заменяет необходимость наличия exportPathMap и работает на каждой странице».

В некоторых приложениях узнать маршруты во время сборки либо непрактично, либо невозможно. Вот несколько примеров:

  • Страницы профиля пользователя
  • Страницы продуктов (для компаний с быстро меняющимся товарным запасом)
  • Страницы с описанием заказа на продажу

Маршруты для таких страниц, вероятно, будут иметь форму /entity-name/entity-id и динамические маршруты Next работают очень хорошо, поскольку вы можете делать такие вещи, как router.push('/customers/[customerId]', '/customers/baer') . Есть еще одна загвоздка. Если вы планируете обрабатывать эти файлы статически с помощью чего-то вроде Serve, Netlify, NGINX и т. Д., Вам нужно будет сгенерировать набор перенаправлений, чтобы пользователи не получали 404 при обновлении страницы, и для этого вы все равно нужно exportPathMap .

Следующее почти как есть скопировано из кодовой базы, над которой я регулярно работаю:

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

Я понимаю, что этот RFC не осуждает и не удаляет какие-либо API-интерфейсы, и я также понимаю, что эти перенаправления можно создавать, просматривая каталог сборки, поэтому, даже если он был объявлен устаревшим, у меня есть хорошая штриховка ecape. Но это не совсем «устраняет необходимость в getStaticPaths ».

Еще раз спасибо за вашу внимательность в том, как вы ведете этот проект.

Являются ли getStaticProps / getStaticPaths и getServerProps взаимоисключающими? т.е. возможно ли иметь часть предварительно визуализированной и динамическую часть одновременно?

Да, они как один - статическая генерация, а второй - рендеринг на стороне сервера.

Это исправляет одну из важных вещей, которые мне не хватает в Гэтсби до того, как мы перешли на Next:

У нас есть монолитный (100 кбайт) файл JSON, из которого мы извлекаем данные для рендеринга наших страниц, которые никогда не меняются. В Gatsby мы загрузили файл JSON в схему GraphQL и запросили его, захватив только те данные, которые нам нужны для рендеринга данной страницы. С Next самый простой / чистый способ, который мы нашли, - это import monolith from './monolith.json' , который требует, чтобы пользователь загрузил весь файл JSON.

Этот RFC на 100% обращается к этому варианту использования и приближает следующий шаг к тому, чтобы быть на одном уровне с Гэтсби в тех областях, в которых Гэтсби сияет (очевидно, Гэтсби не может выполнять SSR во время выполнения, поэтому я говорю только о статических рендерингах во время сборки)

@timneutkens , спасибо за RFC!

У меня есть вариант использования Next.js, который я недавно обсуждал с @rauchg.

Next.js обеспечивает очень плавный DX и некоторые разумные настройки по умолчанию. Итак, я заинтересован в использовании Next.js для приложения, отображаемого только на стороне клиента, приложения Smart TV.

Приложения Smart TV - это почти классические веб-приложения, запускаемые движком браузера телевизора:

  1. Приложение упаковано в пакет: стили, сценарии, изображения, _index.html_, сертификаты и файл конфигурации ТВ.
  2. Пакет отправлен на рассмотрение в магазин приложений платформы.
  3. Затем пакет устанавливается из магазина как приложение и запускается пользователем.

Дело в том, что связка статически размещается на самом телевизоре, а не загружается с сервера. Таким образом, вариант SSR невозможен (Node.js не предоставляется разработчикам для этих целей). Но само приложение динамическое (скажем, Netflix).

Итак, нам нужно запустить SPA, который размещен на статическом веб-сервере.

Насколько я понимаю, полный отказ от getServerProps (или getInitialProps ) поможет избежать SSR. Но что происходит с динамическим рендерингом на клиенте? А как насчет маршрутизации в этом случае? Согласно этому RFC проблема еще не решена. @timneutkens , не могли бы вы подсказать, как лучше всего включить рендеринг только на стороне клиента в Next.js? И подходит ли он в первую очередь Next.js? Спасибо!

PS Я могу создать проблему для этого варианта использования, если вы считаете, что лучше обсудить его отдельно.

@grushetsky, может ты другой выпуск создаешь. Это совершенно другой вопрос, чем обсуждается в RFC 👍

@timneutkens Обещание этого RFC - одна из вещей, которые меня очень взволновали в Next! Просто чтобы прояснить, getInitialProps тоже все равно будет существовать, верно?

Правильный @outdooricon - getInitialProps останется в обозримом будущем.

Согласно RFC:

В этом RFC рассматриваются исключительно дополнения API. Все новые функции полностью обратно совместимы и могут быть адаптированы постепенно. Этот RFC не содержит устаревших рекомендаций.

Отличный RFC, очень рад этому!

Я думал о getServerProps применительно к конкретному варианту использования, помещая результаты в кеш. Поскольку это превращается в конечную точку API, а результат доставляется компоненту в качестве реквизита, существует ли предписанный способ помещения результата во внешний кеш, такой как Redux, GraphQL-кеши и т. Д., И т. Д. На стороне клиента?

Если я правильно понимаю getInitialProps , поскольку он статический и асинхронный, у Next есть возможность дождаться его завершения, прежде чем когда-либо визуализировать компонент в первый раз. Это позволяет нам помещать вещи во внешний кеш. Этого не будет с getServerProps поскольку он работает на сервере, и помещение вещей в кеш в жизненном цикле компонента, похоже, означает, что нам нужно иметь рендеринг, в котором данные еще не доступны в кеше. , даже если он есть в реквизите?

Конечно, это могло быть намеренно, и я мог упустить какой-то подход, но я подумал, что спрошу, рассматривался ли это как-то?

Изменить: я думаю, это также относится к getStaticProps . 😄

Возможно, я где-то это пропустил, но как мы справляемся с ситуациями, когда контент кешируется, но обновляется в базе данных или создается новое сообщение в блоге? Есть необходимость делать новую сборку автоматически? Полагаю, что так.

Прежде всего! Отличное предложение, это огромное улучшение по сравнению с exportPathMaps в сценарии использования большинства людей. Это действительно ценится. С учетом сказанного, я изо всех сил пытаюсь понять, как мы сможем заставить его работать с интернационализацией маршрутов.

Есть ли какие-либо предложения о том, как обрабатывать маршруты с префиксом i18n? Мой конкретный вариант использования требует создания нескольких тысяч страниц с разными префиксами и URL-адресами языка страны.

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

Кажется, что getStaticPaths будет действительно полезным, когда префикс для URL-адреса хорошо известен, как в вашем примере (с использованием /blog/[id].js ). Но как вы думаете, как будет выглядеть реализация getStaticPaths , если ей потребуется генерировать пути на корневом уровне, как с динамическим префиксом (country-lang), так и с динамическим путем?

@reaktivo pages/[lang]/blog/[id].js -> в getStaticPaths предоставляет все URL-адреса для статической визуализации.

@timneutkens Есть идеи, когда это будет доступно / протестировано?

Как правило, мы не выдаем ETA, потому что мы тщательно тестируем функции на рабочих приложениях, чтобы убедиться, что решение правильное.

Эти улучшения полностью заставят меня отказаться от моего "не поддерживаемого" феномического проекта (реагировать на ssg, который никто не использует, кроме меня). Приятно видеть, как Next.js добавляет эти недостающие части!

Хочу прояснить одно сомнение. Учитывая использование CMS, такой как wordpress. Насколько я понимаю, с помощью метода getStaticPaths я бы получил все сообщения и передал список вроде:

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

Заголовок каждого сообщения будет использоваться в методе getStaticProps для получения содержимого.
Это произойдет в сборке npm.
У меня вопрос о новых сообщениях, которые будут добавлены после сборки.
Можно ли использовать метод getStaticProps для получения этого нового сообщения по слагу?
Будет ли в этом новом посте файл .html, как в предыдущей сборке?
Я люблю работать со следующим, и в нескольких проектах у меня это было бы очень хорошо.

Ничего прямо не связанного, но служба поддержки не может дать мне ответ, соответствующий моему вопросу.

То, что вы предлагаете, может быть решением, но пока что я не могу использовать nextJS для создания JAMSTACK на основе изменений веб-перехватчиков.

если бы у меня был getInitialProps, я был бы обработан сервером.
Если я этого не сделаю, я просто CDNized, но без предварительного рендеринга - нет? И страница будет без контента, пока XHR не вернется (до свидания, SEO)

У вас есть какой-нибудь работающий пример Jamstack с nextJS, который мы могли бы сделать на netlify.

Спасибо,
Андреас

Привет, @ScreamZ - я думаю, это изменение позволяет создавать полностью статический сайт с помощью nextjs. Мы долгое время могли компилировать сайт nextjs в статический, используя next export , но он все равно будет получать данные о переходах маршрута на стороне клиента, используя getInitialProps . Благодаря возможности использовать getStaticProps , вы можете запускать переходы на стороне клиента без извлечения каких-либо дополнительных данных - все извлеченные данные в getStaticProps извлекаются один раз во время сборки и не обновляются на вашем live сайт, если вы не перестроите его снова. Это классическая архитектура статических сайтов, управляемых данными. Свяжите источник данных с хостом через веб-перехватчик, и при изменении источника данных вы говорите хосту, что нужно перестроить ваш сайт.

Существует множество примеров полностью статических веб-сайтов nextjs, и запускать сайт nextjs на netlify несложно. Веб-сайт моей компании в настоящее время работает на nextjs и размещен на netlify, надеюсь, это послужит хорошим примером.

Стоит отметить, что услуга хостинга zeit также заслуживает особого внимания. Цены очень похожи, а их интеграция с сайтами nextjs не имеет себе равных - вам буквально даже не нужно вообще ничего настраивать, вы просто связываете github, и хостинг zeit распознает, что вы используете nextjs, и автоматически настраивает и развертывает все.

Это ни в коем случае не реклама, я работаю не на zeit, а только искреннее одобрение. Вы можете полностью заставить его работать с netlify, и я лично для нескольких сайтов в качестве доказательства. Но вам нужно будет досконально понять, как работает nextjs, и вам нужно будет убедиться, что все настроено правильно, чтобы он работал без сбоев в netlify. Если вы ищете самый простой и надежный хостинг для сайта nextjs, я бы попробовал хостинг zeit.

@jescalan Спасибо за отличный обмен 🙏🏻

У меня нет проблем с использованием NextJS с netlify, потому что вы можете использовать Publish directory чтобы указать папку out . Но на zeit. Теперь невозможно сказать, пожалуйста, не используйте SSR, а полностью используйте статику с помощью next export .

@ScreamZ, это в getStaticProps для всех своих страниц со службой хостинга zeit, то, что вы получите, фактически равно статическому сайту, даже если он не запускает next export , поскольку все страницы с getStaticProps создаются только при развертывании сайта и после этого обслуживаются непосредственно из CDN.

Основное отличие состоит в том, что, насколько я знаю, нет способа заставить все страницы быть статичными на хостинге zeit (edit: zeit недавно изменил его, так что любой сайт с конфигурацией, содержащей exportPathMap будет работать полностью статический сайт, так что это уже не так). Страницы с getStaticProps ведут себя точно так же, как страницы, созданные next export - одна статическая копия страницы обслуживается непосредственно из CDN при каждом обращении. Но вы также можете запустить некоторые страницы с getServerProps или getInitialProps и они будут вести себя как страницы, отображаемые сервером. Лично я вижу в этом преимущество - если есть необходимость в маршруте SSR, вы можете просто использовать другой метод выборки данных, и этот единственный маршрут теперь является SSR, в то время как все остальные маршруты могут оставаться статическими.

@jescalan Спасибо,

Так что просто нужно подождать, пока это будет реализовано, а пока воспользуемся netlify для статического

Есть ли какая-нибудь история вокруг конфигурации SSG? В частности, мы хотели бы использовать общие артефакты сборки, но запустить next export с разными конфигурациями для QA / prod. Эти значения конфигурации будут прочитаны только в getStaticProps . Будет ли это использовать напрямую serverRuntimeConfig или publicRuntimeConfig или process.env ?

@ScreamZ @jescalan Сегодня я получил поддержку с нулевой конфигурацией next export на сайте Now вместе с @Timer (он заслуживает всех благодарностей). Ты можешь сделать:

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

И это будет работать автоматически.

Дай мне знать, как дела

Да, я был тем парнем, который просил о поддержке, и они сказали мне, что это только что реализовано 😅 Насколько я понимаю, вам нужно определить карту экспорта в конфигурации?

@ScreamZ нет, вы можете просто добавить next build && next export как показано выше, и это сработает.

@timneutkens Если я заменю getInitialProps на getServerProps , мне все равно нужно будет добавить target: 'serverless' в файл конфигурации, чтобы включить Server Pre Rendering ? Спасибо.

Как мы можем это попробовать?

Как мы можем это попробовать?

Я предполагаю, что все эти методы в настоящее время нуждаются в префиксе unstable_ для распознавания.

например, unstable_getStaticProps

@timneutkens

@ScreamZ @jescalan Сегодня я получил поддержку с нулевой конфигурацией next export на сайте Now вместе с @Timer (он заслуживает всех благодарностей). Ты можешь сделать:

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

И это будет работать автоматически.

Дай мне знать, как дела

Мой скрипт сборки делает немного больше, но похоже, что он работает как шарм:

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

К тому же это здорово! Это было именно то, что я искал 😅 (Прощай, GatsbyJS, мой любимый фреймворк теперь силен, как и ты!)

Большое спасибо за такую ​​реакцию.

Я также перешел на 9.1.6 и неожиданно увидел, что
Screenshot 2019-12-21 at 19 25 43

Я думал, что эта ветка была RFC, похоже, она уже открыта для нас, ага, не так ли?
Однако типы машинописного текста не включены в 9.1.6.

Черт, я так взволнован этим сейчас! 🤣

Последние вопросы:

  • Если я его получу, getInitialProps будущем станут устаревшими? Или это все еще актуально в некоторых случаях? Пример?
  • next export можно исключить и использовать только страницы с getStaticProps и next build ?

Спасибо за этот отличный инструмент 🙏🏻

Если я получу его, getInitialProps в будущем станет устаревшим? Или это все еще актуально в некоторых случаях? Пример?

Как сказано в первоначальном RFC:

В этом RFC рассматриваются исключительно дополнения API. Все новые функции полностью обратно совместимы и могут быть адаптированы постепенно. Этот RFC не содержит устаревших рекомендаций.

Я думал, что эта ветка была RFC, похоже, она уже открыта для нас, ага, не так ли?

Это не так, мы пробуем это в приложениях ZEIT, и некоторые элементы видимости уже появились (например, дерево страниц, которое вы видели).

следующий экспорт также может быть устаревшим в пользу страниц с getStaticProps и только следующей сборкой?

Правильно, в общем, вы просто не используете next export . Он будет сохранен по причине обратной совместимости, но в целом вы захотите создать гибридное приложение, поскольку оно дает вам все преимущества экспорта с поддержкой других функций, таких как маршруты API и возможность рендеринга на стороне сервера для некоторых страниц.

Как мы можем это попробовать?

Я предполагаю, что все эти методы в настоящее время нуждаются в префиксе unstable_ для распознавания.

например, unstable_getStaticProps

Настоятельно рекомендую пока не использовать его, он экспериментальный и может прерываться между выпусками.

Итак, я играл с этой функцией и заметил, что файл JSON, содержащий данные страницы, всегда выбирается после доступа к странице SSG с другой страницы.

Вы, ребята, планируете оптимизацию предварительной загрузки для файла JSON?
Возможно, предварительная загрузка, когда пользователь собирается перейти на страницу (например, пользователь наводит курсор на ссылку SSG) или предварительная загрузка, как если бы вы предварительно загружали другие страницы js, на которые ссылается компонент Link.

Кстати, обожаю эту особенность!

Вы, ребята, планируете оптимизацию предварительной загрузки для файла JSON?

да.

Как бы то ни было, я сторонник древовидного экспорта этих функций, а не отдельных файлов.

Каков статус этой функции? Какие его блокаторы?

@mikestopcontinues, этот RFC в настоящее время интенсивно тестируется нашей командой и несколькими избранными партнерами. Вы можете выбрать его весьма экспериментальное поведение , используя префиксы unstable_ , как упоминалось выше ! 😄

Пожалуйста, не переносите производственные рабочие нагрузки на новые методы, так как мы по-прежнему можем обновлять API-интерфейсы.

Лично я использую его для генерации статических сайтов от 8 до 20К страниц (с возможностью иметь динамические запросы на некоторых страницах). Он работает очень хорошо (за исключением ограничения в 10K файлов на Now), единственное, что мне стыдно, это то, что без метода getStaticPaths getStaticProps вызывается при каждой перезагрузке. Одно поведение, которое может быть хорошим, заключается в том, что первый вызов создает файл json, а следующий его использует.

Планируются ли дополнительные сборки? То есть перестраивается только новый / измененный контент?

Вы можете выбрать его весьма экспериментальное поведение , используя префиксы unstable_ , как упоминалось выше !

Я хотел бы протестировать метод unstable_getServerProps , но похоже, что в настоящий момент он игнорируется, и я не могу найти его где-либо в репозитории zeit/next.js . Это еще не реализовано, или я просто не так делаю?

Планируются ли дополнительные сборки? То есть перестраивается только новый / измененный контент?

Реализация была разработана с учетом инкрементных перестроек, но пока не поддерживается (и не рассматривается в этом RFC).

Будьте уверены, архитектура готова, и мы будем исследовать ее после того, как эти функции станут стабильными.
Вот почему getStaticProps определяется для каждой страницы, а не один раз для всего приложения!

Я хотел бы протестировать метод unstable_getServerProps, но похоже, что в настоящий момент он игнорируется [...]

getServerProps пока недоступен в предварительной версии, извините!

getServerProps пока недоступен в предварительной версии, извините!

Спасибо за внимание. Я обязательно буду следить за этой веткой, потому что, когда она появится, у меня будет _bunch_ кода, который можно заменить переименованием одной функции! 😍

Пожалуйста, поясните, я не на 100% уверен, доступны ли в настоящее время getServerProps / getStaticProps для использования.

На основе этой темы: Нет

Но если это так, то мне интересно, почему мой терминал намекал на это, когда я запускал next build если они еще не доступны? Увидев это сообщение, я пришел к первоначальному рабочему предположению, что эти методы уже используются, и мне потребовалось время, чтобы обнаружить, что это не так. Просто интересно, почему я что-то не понимаю.

λ  (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)

(в следующей версии 9.1.6)

Спасибо

@stevenjchang они доступны с использованием следующего синтаксиса в pages/**/*.js :

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

И я должен также добавить, они замечательные, хотя они все еще немного грубоваты при использовании сервера разработки.

хотя они все еще немного грубоваты при использовании сервера разработки.
@mikestopcontinues

Не могли бы вы подробнее рассказать об этом? Никто больше не оставлял нам отрицательных отзывов об опыте работы с сервером разработки, и мы хотели бы решить эту проблему!

@Timer Мне очень нравится новый api. Моя основная проблема во время разработки заключается в том, что json повторно запрашивается при каждой загрузке. Это замедляет тестирование, но также искажает опыт пользователя при просмотре сайта.

Под «при каждой загрузке» вы имеете в виду загрузку страницы? Или перестроить? Или...?

@mmmeff Каждый раз, когда вы переходите по одному и тому же пути, он повторно запрашивает json. Поэтому, если вы переходите между двумя страницами, вы тратите много времени на ожидание данных.

@mikestopcontinues - это предполагаемое поведение, поскольку при разработке часто предпочтительнее использовать самые

@timneutkens Этот RFC выглядит очень многообещающим. У меня есть несколько вопросов / опасений по поводу безопасности и того, как она работает.

Давайте возьмем общий бизнес-пример, который полагается как на SSR, так и на SSG.

Контекст

Мы хотим отображать некоторую информацию на веб-сайте (также известном как «приложение»).
Эта информация хранится в BDD, доступном через GraphQL API.
Часть этой информации является общедоступной, а часть - частной (например, адреса электронной почты пользователя / пароль).

Приложение использует два этапа:

  • «Промежуточный» этап, на котором заказчик может видеть изменения в промежуточном приложении в реальном времени (они обновляют эту информацию через какой-то бэк-офис или аналогичный)
  • Этап «производства», когда заказчик не имеет доступа и не может ничего обновлять самостоятельно. Чтобы обновить производственное приложение, необходимо выполнить новое развертывание. (они просят развернуть новую производственную среду из своего бэк-офиса)

В этом сценарии мы используем как SSR, так и SSG:

  • Промежуточное приложение использует SSR, потому что оно извлекает в реальном времени данные из GraphQL API (при создании страницы)
  • Производственное приложение использует SSG, потому что при новом развертывании оно извлекает данные из GraphQL API и генерирует из них статические страницы (поэтому они статичны и больше не будут меняться, запросы к GraphQL API не будут выполняться. во время выполнения (по крайней мере, не при загрузке страницы))

Этот сценарий должен быть достаточно общим и (IMHO) одним из основных вариантов использования SSG.
Производственное приложение - это не что иное, как снимок промежуточного приложения.

Несколько вопросов:

  1. Возможно ли это с помощью этого RFC ? Одно и то же приложение ведет себя по-разному в зависимости от данной «стадии» (производство / постановка).
  2. Как вводятся данные, полученные из API GraphQL?

    • На этапе подготовки они загружаются динамически через SSR или CSR по мере того, как пользователь перемещается по страницам (и будут доступны в браузере, если будут загружены во время CSR).

    • В производственной среде они загружаются во время сборки, но хранятся ли они в глобальной переменной JS и, следовательно, могут быть прочитаны кем угодно? (проблема безопасности, поскольку мы должны знать, чтобы не получать конфиденциальные данные, которые могут быть доступны в браузере, аналогично тому, как это делается при использовании CSR)

  3. Есть ли у вас какие-либо опасения по поводу этого подхода со смешанным SSR / SSG? (безопасность, производительность, ремонтопригодность и т. д.)

Когда вы планируете выпустить это? Будет ли это крупное обновление (v10) или обновление с обратной совместимостью?

Привет,

Вы кто-нибудь пробовал это решение с настраиваемым сервером и заставлял его работать?

Пример:

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

Почему не может getStaticProps включить строку запроса? В настоящее время у меня есть страница, на которой мне нужно SSR, чтобы просто получить параметры запроса без повторной визуализации. Использование хука useRouter вызывает несколько повторных отрисовок, поскольку запрос изначально является пустым объектом. Это страница, которая используется для отслеживания конверсий, поэтому очевидно, что она не является стартовой.

@pjaws В RFC специально упоминается getStaticProps для статической генерации. Статический HTML не может получить строку запроса.

Тогда почему он может получать параметры динамического URL? Чем это отличается?

Во вторник, 14 января 2020 г., в 1:30 Тим Нейткенс [email protected]
написал:

@pjaws https://github.com/pjaws RFC, который в нем специально упоминается
getStaticProps предназначен для статической генерации. Статический HTML не может получить
Строка запроса.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=AMVRRIQCKDJNF4MPWSLYNV3Q5WA2NA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HS4DFMVREXWI45
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AMVRRIRJXLYC4MC4U7DH7NDQ5WA2NANCNFSM4JRPBELQ
.

Потому что в getStaticPaths вы должны вернуть страницы, которые будут отображаться во время сборки.

Эти изменения выглядят очень многообещающими, как всегда, отличная работа! 👍

Мне интересно, как использовать getInitialProps в _app.js для удовлетворения потребностей в данных, совместно используемых на страницах (например, настройка поставщиков контекста). Правильно ли я понимаю, что нельзя использовать getStaticProps таким же образом? Его можно определить только на отдельных страницах?

Мне интересно, как использовать getInitialProps в _app.js для удовлетворения потребностей в данных, совместно используемых на страницах (например, для настройки поставщиков контекста). Правильно ли я понимаю, что нельзя использовать getStaticProps таким же образом? Его можно определить только на отдельных страницах?

Правильно, изначально это будет только для отдельных страниц. Возможно, позже пересмотрю. GetInitialProps _app по-прежнему будет вызываться при экспорте в статический HTML, поэтому вы можете постепенно переходить к getStaticProps.

привет, ребята, один связанный с этим вопрос - как будут относиться к активам? потому что я прямо сейчас вижу, что если я использую безголовую CMS (даже wordpress, graphcms или что-то еще), URL-адрес ресурса используется в статическом html.

Здесь есть два предпочтения - использовать ссылки на ресурсы как таковые.
Но более вероятно - загрузите актив, создайте html (ссылку на него локально), а затем разместите CDN впереди. Это гораздо более приемлемая практика.

Это также очень хорошо сочетается с использованием таких систем развертывания, как Netlify, которые имеют гораздо более подходящую глобально доступную инфраструктуру, чем что-то вроде DatoCMS или Graphcms. Поэтому, если я использую Netlify в качестве развертывания, я бы хотел, чтобы все обслуживалось из домена Netlify и позволяло ему творить чудеса.

@sandys Если я правильно понимаю в https://github.com/zeit/next.js/issues/9054#issuecomment -570427085, вы должны загрузить активы, сохранить их под .next/static и создать ссылку себя в getStaticProps .

Также есть идея иметь статические маршруты api, но я не уверен, как именно с этим можно управлять поведением кеширования браузера.

@Janpot благодарит за

Пожалуйста, добавьте мой запрос к встроенному. Возможно, № 9054 более общий, но я думаю с точки зрения SSG, и это ЧРЕЗВЫЧАЙНО важно.

Я забыл упомянуть, но хеширование активов также будет иметь важное значение для SSG.

@homoky , Не удалось заставить это работать, у вас были какие-то успехи за это время?

@homoky , Не удалось заставить это работать, у вас были какие-то успехи за это время?

Это невозможно и не планируется: # 10071

😢

@sandys на самом деле решение намного проще, если вы используете https://github.com/zeit/next.js/issues/9081, чтобы добавить перезапись, например, из /images в CMS. Например, в ZEIT. Теперь он уже кэширует результат при добавлении правильных заголовков, нет необходимости в дополнительной загрузке (огромные накладные расходы при сборке).

@timneutkens благодарит за ответ.
Не совсем понимаю, что вы имеете в виду. Итак, мы используем netlify - вы предлагаете оставить URL-адреса CMS как таковые и покрыть их слоем CDN?
Я не очень уверен, может ли netlify (облачный интерфейс, который мы планируем использовать) без проблем работать со всеми этими сервисами.

Если образы загружаются и становятся частью развертывания, вся эта проблема значительно упрощается. Потому что я настраиваю CDN для кеширования с базового URL-адреса (который в моем случае будет обслуживаться с s3).

Не совсем уверен, что ваше решение основано на моем использовании Zeit NOW

Если образы загружаются и становятся частью развертывания, вся эта проблема значительно упрощается. Потому что я настраиваю CDN для кеширования с базового URL-адреса (который в моем случае будет обслуживаться с s3).

Это на самом деле делает процесс сборки намного более сложным и в 10 раз медленнее, но определенно не проще.

Не совсем уверен, что ваше решение основано на моем использовании Zeit NOW

Работает со всеми прокси в мире. В том числе Cloudfront.

@timneutkens на самом деле мы не

Я, конечно, не сторонник того, чтобы вы включали это для всех. Многие люди будут счастливы перейти на CMS. Но у нас сайт с высокой посещаемостью, и это определенно то, что нужно таким сайтам, как мы.

Кроме того, простите меня, но я не понял вашего решения. как нам это настроить? Я не могу контролировать, какой URL использует CMS. Например, Datocms начинает обслуживание с www.datocms-assets.com/ . Как нам использовать решение в №9081?

на самом деле мы не зависимы от времени процесса сборки. не имеет значения, если это займет больше времени

Это может быть верно для вашего приложения, но не для большинства приложений.

но по многим причинам (включая все ресурсы, обслуживаемые с известного базового URL-адреса), было бы очень предпочтительно, чтобы это было встроено в сборку.

На самом деле это не обязательно должно быть так, как было сказано, вы можете использовать перезапись, которая проксирует /images/* на URL-адрес cms, например www.datocms-asset.com/* или аналогичный. А затем просто свяжите все изображения с помощью /images .

Обратите внимание, что это начинает выходить за рамки темы.

@sandys на самом деле решение намного проще, если вы используете # 9081 для добавления перезаписи, например, из / images в CMS. Например, в ZEIT. Теперь он уже кэширует результат при добавлении правильных заголовков, нет необходимости в дополнительной загрузке (огромные накладные расходы при сборке).

@timneutkens Просто чтобы прояснить ситуацию. В идеальной ситуации вы бы хэшировали изображение и навсегда кешировали его в браузере под уникальным URL-адресом, а создатели контента могут обновлять файл, когда захотят, под тем же именем в CMS. Это означает, что в предлагаемой вами настройке CMS должна будет отвечать за:

  1. оптимизация изображений
  2. хеширование изображений и обслуживание их под этим хешем
  3. предоставить карту от URL-адреса изображения к URL-адресу хешированного изображения, которую можно загрузить в getStaticProps чтобы переназначить URL-адреса изображения на их неизменяемую копию на CMS

Что, я думаю, не невозможно. Просто хочу убедиться, что это предлагаемая установка.

Поставщики CMS

Это может быть верно для вашего приложения, но не для большинства приложений.

Опять же, я здесь не один. Подобных запросов масса. Прошу вас обдумать это.

https://spectrum.chat/next-js/general/how-would-you-handle-importing-remote-images-on-nextjs-static-export~30b2ba84-bc27-4da7-9ec8-21e4d5d287a3

на стороне Гэтсби - https://github.com/gatsbyjs/gatsby/issues/14076

https://spectrum.chat/gatsby-js/general/adding-remote-images-during-node-creation~e704e6fb-24b2-46c6-b1fc-93189d2e28a4

https://github.com/njosefbeck/gatsby-source-stripe/#downloading -files

@sandys не имеет отношения к SSG RFC, поэтому не стесняйтесь создавать новый выпуск, когда он будет выпущен.

однако я просто хотел упомянуть, что, по нашему мнению, это тесно связано с SSG. Поскольку в идеальном случае это делает команда экспорта SSG. Обычно это не требуется в других случаях.
В лучшем случае это будет дополнительной функцией во время следующего экспорта.

Но, как хотите - уважайте свое решение.

Но это то, чего next export настоящее время даже не делает. Следовательно, это совершенно новая вещь, не имеющая отношения к этому RFC.

Этого также не было бы с getServerProps и рендерингом по требованию.

Поставщики CMS

👍 да, в этом есть смысл. Но это также означает, что если вы используете изображения в своем проекте и хотите, чтобы они были оптимизированы и кэшированы, у вас есть 2 варианта:

  1. создать настраиваемую настройку веб-пакета
  2. использовать внешнюю CMS

редактировать:

И если я правильно понимаю, file-loader уже включена в CSS. Разве это не вопрос включения его и для JS?

@Janpot Сандип упомянул, что URL-адреса будут поступать из внешнего источника, а не из самого проекта. Включение загрузчика файлов по умолчанию - это отдельная просьба.

Я заметил, что для сайтов, развернутых в ZEIT Now, когда у меня есть страница с динамическим URL с использованием новых статических API, для страниц, которые не были статически созданы с использованием unstable_getStaticPaths , функция unstable_getStaticProps запускается на сервере во время выполнения, а не возвращает 404.

Например, у меня есть страница /blog/[slug].js , чья getStaticPaths возвращает массив:

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

и мой getStaticProps имеет некоторую логику для чтения файла на основе slug. Когда я посещаю /blog/hello страница предварительно отрисовывается, как и ожидалось, но когда я посещаю недопустимую страницу, например /blog/doesnt-exist , тогда getStaticProps запускается во время выполнения, и я получаю ошибку 500, а не 404. Или, если я добавлю обработку ошибок, тогда страница будет отображаться, а не 404, несмотря на то, что она не указана в выводе из getStaticPaths .

Эта логика преднамеренная?

Это большое улучшение. Мы как раз собирались написать несколько сценариев предварительной сборки, чтобы сделать именно это.
Я только что протестировал перенос одного из наших сайтов на unstable_getStaticPaths и unstable_getStaticProps в Next 9.2, и это сработало.

У нас есть одна регрессия по сравнению с exportPathMap : при построении пути с помощью exportPathMap вы можете указать что-то вроде этого:

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

и статическая сборка построит

/path
   /to
     /page
       index.html

Когда вы возвращаете эквивалент из unstable_getStaticPaths в шаблоне [slug].jsx ,

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

В следующем 9.2 создается «% 2Fpath% 2Fto% 2Fpage» вместо вложенных каталогов.

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

Создание каталогов (соответствие существующему поведению exportPathMap) важно для того, как мы создаем страницы. Мы используем один файл шаблона, но опубликованный путь может быть произвольно вложенным.

@dpfav и в этом случае вы захотите использовать маршрут для https://nextjs.org/blog/next-9-2#catch -all-dynamic-routes

Возможно, мы можем предупредить, когда вы попытаетесь вернуть путь, включая косые черты, но поведение правильное при использовании [slug].js , в вашем случае вы хотите [...slug].js .

Когда ожидается его приземление? Будет ли это патч 9.2 или его собственная минорная версия?

Мы очень ценим ажиотаж вокруг этой функции. Как уже упоминалось в другом месте, мы, как правило, не сообщаем о сроках реализации функций, так как хотим убедиться, что у них есть необходимый опыт разработчика, ограничения и надежность в будущем.

Поскольку это новая функция, она будет второстепенной.

Да, я бы нормально это понял, но блог 9.1.7 произвел впечатление
это уже было в дикой природе.

В пятницу, 17 января 2020 г., в 17:05 Тим Нейткенс [email protected]
написал:

Мы очень ценим ажиотаж вокруг этой функции. Как уже упоминалось
в других местах мы обычно не публикуем сроки для функций, как мы хотим
убедиться, что у них есть правильный опыт разработчика, ограничения и будущее
доказанность.

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=ADKINGF724256WCEFHBFIH3Q6ITRXA5CNFSM4JRPBEL2YY3PNVWWK3TUL52HTUL52HS4DFVREXORXG43LVMWK3TUL52HS4DFVREXG43LVMX4DFVREXG43LVMX4DFVREXG43LVMWB
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/ADKINGBVCG6MFMOG5U2FGMDQ6ITRXANCNFSM4JRPBELQ
.

>

Ласситер Грегг
[email protected] [email protected]
сотовый (832) 495-9903

Есть ли что-нибудь вроде getStaticProps но которое выполняется только один раз для всего приложения, а не для каждой страницы?

Мой вариант использования заключается в том, что у меня есть контекст React ( PricingPlansContext ), который используется несколькими страницами, и я хочу, чтобы данные (тарифные планы) извлекались с моего внешнего сервера только один раз, во время сборки ( next export ). Никогда во время выполнения и без необходимости добавлять getStaticProps с каждой страницы.

РЕДАКТИРОВАТЬ: нашел соответствующий комментарий выше: https://github.com/zeit/next.js/issues/9524#issuecomment -574179540. Надеюсь, это будет учтено.

Я использую для этого babel plugin-preval`, хотя я также видел, как люди пишут
json в exportPathMa () с next.config.js, который они затем импортируют
в их коде.

В итоге я написал json-файл с помощью сценария npm, но спасибо за предложение exportPathMap, возможно, это лучшее место.

@dpfav и в этом случае вы захотите использовать маршрут для https://nextjs.org/blog/next-9-2#catch -all-dynamic-routes

Возможно, мы можем предупредить, когда вы попытаетесь вернуть путь, включая косые черты, но поведение правильное при использовании [slug].js , в вашем случае вы хотите [...slug].js .

@timneutkens благодарит за продолжение. Я безуспешно пробовал два метода. Обычно при указании значения слага в виде строки в getStaticPaths оно вообще не передается в getStaticProps . При возврате служебного значения в виде массива сборка завершается ошибкой, поскольку значение должно быть строкой.

Случай 1. Предполагая, что файл pages/[...slug].jsx , slug as 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 };
}

В приведенном выше случае params в getStaticProps является пустым объектом - без ключа slug .

Случай 2, pages/[...slug].jsx , slug as 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 };
}

В случае 2 сборка завершается неудачно с

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

Я вижу параметры пути только в приведенных выше примерах getStaticPaths . Можно ли будет использовать пути SSG, содержащие параметры запроса? Например:

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

Я особенно думаю с точки зрения сайта электронной коммерции, где было бы сложно охватить каждый аспект поиска продукта в pathname URL-адреса.

Я недавно разместил здесь сообщение и не получил ответа - по сути, getStaticProps ведет себя как getServerProps когда сайт развернут в ZEIT Now (т.е. игнорирует getStaticPaths и обрабатывает запросы динамически) - думаю это баг?

@dpfavand я стартовый сайт для agilitycms и nextjs с динамической маршрутизацией страниц на основе страниц в CMS.

@timneutkens благодарит за продолжение. Я безуспешно пробовал два метода. Обычно при указании значения слага в виде строки в getStaticPaths оно вообще не передается в getStaticProps .

Случай 1. Предполагая, что файл pages/[...slug].jsx , slug as 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 };
}

В приведенном выше случае params в getStaticProps является пустым объектом - без ключа slug .

Кстати, маленький мир! Еще раз спасибо за выступление на fastr_conf.

Привет @timneutkens!

Мне очень нравится идея сделать next.js похожим на генератор статических сайтов.

Я хотел бы спросить, как можно использовать методы getStaticProps и getStaticPaths в случае, когда большой кусок данных запрашивается один раз, а затем используется для генерации разных страниц.

Например, я использую клиент SDK JavaScript для CMS на основе API, у которой есть метод для получения всех доступных объектов. Некоторые из этих объектов представляют собой страницы сайта.

const entries = await cmsSdkCient.getEntries();

До сих пор я использовал метод exportPathMap для одновременного получения всех записей из CMS и создания карты между путями этих страниц и их данными. Функция exportPathMap выполняет две функции:

  1. Предоставляет карту страниц с их данными и ssr: true которые потребляются getInitialProps во время экспорта
  2. Записывает те же данные, на этот раз с ssr: false , в файлы init-props.json , помещенные в папку, соответствующую пути каждой страницы. Затем, когда getInitialProps вызывается из клиента, необходимые данные загружаются из init-props.json соответствующей страницы.


next.config.js с использованием 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 с использованием 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();
    });
  }
};

Я вижу огромное преимущество использования методов getStaticProps и getStaticPaths , которые уменьшат большую часть моего кода, связанного с сохранением файлов JSON и их загрузкой с клиента.

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

Что меня беспокоит, так это вопрос, как я могу оптимизировать рабочий процесс, чтобы получать все записи один раз, а не получать их каждый раз при вызове getStaticProps или getStaticPaths ?

Другой вопрос, возможно, не обязательно связан с этой проблемой, но, поскольку мы находимся в мире SSG и удаленных источников данных, его стоит задать. Предполагая, что next.js работает в режиме разработки, как можно уведомить next.js о повторном выполнении этих методов, чтобы повторно получить удаленные данные и перестроить сайт.

@smnh Поскольку это «просто JavaScript», вы можете получить свои записи один раз и кэшировать результаты в своем методе выборки данных. Когда он снова вызывается в методах getStatic * какой-либо другой страницы, сеть больше не будет задействована.

Что касается вашего второго вопроса, он делает это автоматически. Запустите next dev и все готово.

Я вижу параметры пути только в приведенных выше примерах getStaticPaths . Можно ли будет использовать пути SSG, содержащие параметры запроса? Например:

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

Я особенно думаю с точки зрения сайта электронной коммерции, где было бы сложно охватить каждый аспект поиска продукта в pathname URL-адреса.

Я не думаю, что это имеет смысл в контексте ssg. SSG выводит файл для каждой записи - параметры запроса не являются частью имени файла, поэтому вам понадобится уровень сервера, чтобы переписать запросы в фактический файл. (Каким будет ваше статическое имя файла в приведенном выше примере?) Я бы предложил рассмотреть возможность предварительной визуализации представления по умолчанию (что вы получаете, если вы посещаете страницу без фасетов) и обновления на стороне клиента, если в запросе есть параметры запроса. Но это становится проблемой, выходящей за рамки этого RFC SSG.

@dpfavand я стартовый сайт для agilitycms и nextjs с динамической маршрутизацией страниц на основе страниц в CMS.

@timneutkens благодарит за продолжение. Я безуспешно пробовал два метода. Обычно при указании значения слага в виде строки в getStaticPaths оно вообще не передается в getStaticProps .
Случай 1. Предполагая, что файл pages/[...slug].jsx , slug as 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 };
}

В приведенном выше случае params в getStaticProps является пустым объектом - без ключа slug .

Кстати, маленький мир! Еще раз спасибо за выступление на fastr_conf.

Привет! Команда Nextjs начала заниматься этим, есть билет для решения некоторых дополнительных проблем с текущей реализацией канарейки: https://github.com/zeit/next.js/issues/10190

@smnh то, что я в итоге делаю, - это сценарий, который предварительно

Для перестроек у меня настроены веб-перехватчики в CMS, чтобы запускать перехватчики сборки Netlify при изменении соответствующего содержимого. После этого GetStaticProps может просто получить содержимое конкретной страницы.

Спасибо @zeusdeux
Re:

Что касается вашего второго вопроса, он делает это автоматически. Запустите следующего разработчика, и все готово.

Если я кэширую их в модуле, а затем изменяю данные в CMS, как кеш будет недействительным и повторно запущен dev , но без остановки next.js и его повторного запуска :)

Если я кэширую их в модуле, а затем изменяю данные в CMS, как кеш будет недействительным и повторно запущен dev , но без остановки next.js и его повторного запуска :)

getStaticPaths вызывается только в производственной сборке, поэтому вы можете указать методу выборки кэшировать в состоянии модуля только при вызове из этой функции.

Эй, я не видел, сталкивался ли кто-нибудь с той же проблемой, что и я.

Допустим, у меня есть одна и та же страница на нескольких маршрутах с unstable_getStaticProps :

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

Исходный код одинаков для обеих страниц, поэтому нет необходимости дублировать. Итак, первый файл содержит исходный код с логикой, второй импортирует только первый, например export { default } from './[city]'; .

Но выдает ошибку, что данные из getStaticProps не определены. Если я копирую один и тот же код в оба файла, он работает.

@homoky вам нужно повторно экспортировать методы:

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

Пробовал SSG, но безуспешно.

Должен ли приведенный ниже код с v9.2.1 привести к SSG?

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

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

export default Page

Мой вывод консоли из next build показывает:

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 необходимо экспортировать, а не прикреплять к компоненту страницы, например

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

@joostmeijles unstable_getStaticProps необходимо экспортировать, а не прикреплять к компоненту страницы, например

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

Спасибо, это решает.

Если кто-то хочет увидеть непрерывный рабочий пример этого, создание динамических страниц (из CMS) с всеобъемлющим маршрутом и SSG, проверьте https://github.com/agility/agilitycms-next-starter- ssg.

Пару раз я был в тупике и решил, что это может быть полезно для других.

Как я могу получить доступ к следующим маршрутам API во время сборки с помощью getStaticProps при развертывании на zeit.co/now? Isomorphic-fetch требует абсолютного URL-адреса; локально он работает с http: // localhost : 3000, но не с развертыванием сейчас (или я сделал это неправильно 🤷‍♂️). Любые идеи?

Если я прав, маршруты API будут развернуты как бессерверные функции, и я предполагаю, что они не готовы в процессе сборки?

Вы захотите вызвать функцию своего маршрута api напрямую, так как это намного меньше накладных расходов, чем при использовании http.

Вы захотите вызвать функцию своего маршрута api напрямую, так как это намного меньше накладных расходов, чем при использовании http.

Есть ли ресурсы, которые я могу прочитать в документации по этой теме? Я в процессе перехода на zeit.co/now :)

В буквальном смысле импортируйте и вызовите функцию:

import MyFunction from '../lib/somewhere'


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

Другой вопрос: можно ли будет использовать getStaticProps / getStaticPaths и getServerProps бок о бок? Например, если я предварительно отрендерил некоторые страницы с помощью SSG, но если он не найден в кеше CDN, он вернется к SSR, чтобы сгенерировать страницу по запросу?

getStaticProps вернется к SSR и добавит результат в кеш,

getStaticProps вернется к SSR и добавит результат в кеш,

@lfades , если я вас правильно понял, то я в восторге от этого, потому что это означает, что я могу предварительно отрендерить несколько популярных страниц, вместо того, чтобы искать и генерировать несколько тысяч страниц заранее.

Но просто чтобы убедиться, что я понимаю ... Допустим, у меня есть страница динамического пути /products/[productId].js . Если я предоставлю getStaticProps и ограниченное количество результатов из getStaticPaths , тогда вы говорите, что /products/123 не найден в кэше CDN (потому что его не было) t в getStaticPaths ), он вернется к SSR, запустит getStaticProps , а затем кэширует результат как статическую страницу?

Последующий вопрос: будет ли это работать, если я вообще не поставлю getStaticPaths ?

@flintinatux Да и да 👍

getStaticProps вернется к SSR и добавит результат в кеш.

Это проблема, потому что нет способа выполнить 404, поскольку getStaticProps не позволяет изменять объект res - либо 200, либо 500, если во время вызова функции произошла ошибка.

Планируется ли это изменить?

@ davidbailey00 при создании статических веб-сайтов страницы 404 уже не имеют кода состояния 404.

Конечно, если я выполняю полный статический экспорт, нет возможности делать коды состояния, поскольку все это просто файл. Я говорю о развертывании гибридных сайтов с использованием getStaticProps в ZEIT. Теперь похоже, что он должен уважать getStaticPaths и обслуживать страницы 404, а не принудительно отображать все страницы, соответствующие динамическому пути, независимо от этого.

Это работает не только в Now, но и в next start .

Я повторю, как было сказано ранее: это экспериментально, и все может измениться в поведении.

Но можно обслуживать 404 страницы с getServerProps или getInitialProps - если getStaticProps игнорирует getStaticPaths при рассмотрении кода ответа, то это совершенно нежизнеспособно для любого сайта, который заботится о хорошее SEO.

Мы, вероятно, представим больше способов обработки кодов состояния, но имейте в виду, что большинство статических сайтов (например, CRA) направляют /* на index.html где 404 по-прежнему равно 200.

Привет, ребята, у меня прямой вопрос, я создаю простой веб-сайт, используя новый [unstable_]getStaticProps для SSG некоторых страниц. Все работает пока нормально, за исключением amp .

Если страница содержит [unstable_]getStaticProps , то amp отключено. Вот простой пример работы со следующей версией v9.2.1, где вы можете это проверить:

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;

Любая помощь, чтобы понять, как работают страницы SSG с данными и amp ?

Привет, как насчет поддержки getStaticProps для App component ( _app.tsx ), то есть для таких случаев, как выборка общих данных для всех компонентов страницы на этапе сборки?

Привет, как насчет поддержки getStaticProps для App component ( _app.tsx ), то есть для таких случаев, как выборка общих данных для всех компонентов страницы на этапе сборки?

@ pkral78 Я могу сказать вам, как я

Я создал макет с подходом «Макет как компонент высшего порядка (HOC)» (больше не в учебной документации 🤷‍♂️).

В любом случае, я создал такой макет (просто пример):

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;

А затем на странице, на которой вы хотите использовать этот подход, вы можете просто добавить HOC (вы должны явно экспортировать [unstable_]getStaticProps и amp, не работающие вместе), но я нашел "хороший способ" получить высокоуровневый запрос. и запросы SSG на странице.

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;

Хотелось бы скрыть, если это хороший подход. В моем случае я использую эту технику для запроса ссылок в родительском содержимом и содержимого страниц в страницах. Я надеюсь, что это помогает.

@robertovg Вы должны экспортировать на уровне модуля, так как код имеет древовидную структуру. То, как вы это смоделировали, приводит к тому, что на стороне клиента отправляется больше кода.

@timneutkens Не могли бы вы предложить лучшее решение для этого небольшого примера ? Я просто пытался каким-то образом иметь как «запрос SSG уровня макета», так и «запрос SSG уровня страницы», и я подумал об этом подходе к макету HOC.

Основным ограничением для меня было явное «экспорт [unstable_] getStaticProps», которое необходимо иметь на каждой странице, чтобы пометить как страницу SSG.

Я также был бы очень признателен за дополнительную информацию о том, будет ли совместим amp + SSG , о чем я спрашивал ранее.

Спасибо 🙏

@robertovg Во-первых, отделите макет от данных, поэтому для общего макета у вас будет что-то простое, например:

import Layout from '../components/layout'

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

export default Page

А затем для getStaticProps получить общие данные с помощью метода из другого модуля, поэтому полный пример может выглядеть так:

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 Во-первых, отделите макет от данных, поэтому для общего макета у вас будет что-то простое, например:

import Layout from '../components/layout'

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

export default Page

А затем для getStaticProps получить общие данные с помощью метода из другого модуля, поэтому полный пример может выглядеть так:

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

Я вижу и понимаю это решение, но проблема, которую я пытался решить, заключалась в том, как масштабировать использование общих данных.
Например, если у вас есть <Header /> который использует sharedData для получения ссылок, и они поступают из Headless CMS. Вы должны ввести <Header /> как дочерний элемент <Layout /> с помощью props или другого решения. И вам нужно повторить инъекцию <Header /> на все страницы, которые вы хотите использовать.

При подходе HOC вы просто добавляете <Header /> один раз в HOC.

Вот почему я подумал, что это хороший аргумент , поднятый

Вот почему я подумал, что это хороший аргумент , поднятый

Это было у меня на уме. Страница _app должна иметь свой getStaticProps который вызывается один раз во время рендеринга первой страницы, а затем передает сохраненный props на следующие обработанные страницы. Но я все еще думаю, правильная ли это концепция.

Не уверен, что такие вещи являются предполагаемым вариантом использования, но, похоже, это не работает:

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

Даже если это не предполагаемый вариант использования, он регистрирует ошибку, которая кажется немного подозрительной:

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

Редактировать:

О, хорошо, когда я это сделаю, это разрешится.

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

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

Это жалоба на то, что ваш путь к файлу импорта является динамическим

В чт, 30 января 2020 года, в 00:29, Ян Потомс [email protected] написал:

Не уверен, что такие вещи
https://codesandbox.io/s/nifty-cache-jspqr - это предполагаемый вариант использования, но
похоже, не работает:

// /pages/[...slug ].jsximport ReactDOMServer из "response-dom / server";
экспортировать асинхронную функцию unstable_getStaticProps ({params: {slug}}) {
// насколько это безопасно?
const filePath = "../content/" + slug.join ("/") + ".mdx";
const {по умолчанию: компонент} = ждать импорта (путь к файлу);
const content = ReactDOMServer.renderToStaticMarkup (Компонент);
возвращение {
реквизиты: {title: slug.join (""), content}
};
}
экспортировать функцию по умолчанию Page ({title, content}) {
возвращение (


{заглавие}




);
}

Даже если это не предполагаемый вариант использования, он регистрирует ошибку, которая кажется ошибочной.
немного подозрительно:

[предупредить] ./pages/[...slug ].jsx
Критическая зависимость: запрос зависимости - это выражение

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/zeit/next.js/issues/9524?email_source=notifications&email_token=AAADKRKOL34WKTG7J5QFRJ3RAIGPBA5CNFSM4JRPBEL2YY3PNVWWK3TUL52-5DFVREXWWK3TUL52HS4DFVREXWWK3TUL52HS4DFVREXWG43
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AAADKRIWNA2DSMWFRGD453DRAIGPBANCNFSM4JRPBELQ
.

Вот почему я подумал, что это хороший аргумент , поднятый

Это было у меня на уме. Страница _app должна иметь свой getStaticProps который вызывается один раз во время рендеринга первой страницы, а затем передает сохраненный props на следующие обработанные страницы. Но я все еще думаю, правильная ли это концепция.

@ pkral78 , это может быть потому, что на большинстве сайтов SSG, которые я представляю реализованными с помощью Next, я хотел бы иметь "общую часть" (верхний колонтитул, нижний колонтитул, боковые панели ...). И почему бы просто не сделать запрос для этой общей части в _app, если вам нужно, и сделать ее доступной на дочерних страницах без необходимости вручную на каждой странице.

Меня беспокоит только то, что если вы поместите его в _app.js , мы не сможем иметь более одного «общего элемента» в зависимости от страницы. С помощью идеи, которую я создавал прототип, я хотел иметь возможность иметь ее в макете, потому что это позволило бы нам иметь несколько макетов в зависимости от типа страницы, которую вы хотите отобразить, "поэтому я назвал withSSGLayout чтобы мой HOC, потому что я планировал иметь не только страницы SSG, но и SSR, и полностью клиентские, или даже более одного SSGLayout. Я мог бы сделать это, если бы Layouts также мог отвечать за родительский метод getStaticProps .

В любом случае, наличие SSG в Next сделает его инструментом для любого веб-сайта 🙌

@Janpot относительно https://github.com/zeit/next.js/issues/9524#issuecomment -580012327

Настоятельно рекомендую никогда не использовать динамические пути в import() . Он объединит все возможные файлы по пути в пакет JS и значительно снизит производительность сборки при этом.

@timneutkens Конечно, имеет смысл. getStaticProps предназначен только для запроса внешних API, а не файловой системы?

@Janpot, который вы можете читать из файловой системы, часто в конечном итоге вы запрашиваете некоторый внешний API.

@timneutkens Хорошо, тогда лучше использовать @mdx-js/runtime , вместо того, чтобы полагаться на @next/mdx я полагаю.

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 ага ! вы также можете использовать обычную уценку, это то, что мы делаем для nextjs.org/docs.

Что касается https://github.com/zeit/next.js/issues/9524#issuecomment -580207073, это точно так же, как я сейчас использую Next с SSR. У меня есть запрос GraphQL, который выполняется на уровне макета, и его содержимое используется совместно с общими компонентами приложения (панель навигации, нижний колонтитул и динамические дочерние элементы). Затем динамические дочерние элементы обычно делают еще один запрос GraphQL для содержимого конкретной страницы.

Таким образом, наличие способа повторного использования кажется важным, я бы не хотел дублировать код на каждой странице для получения этих общих данных.

Привет!
Я здесь совсем новенький. Только начал работать над переносом приложения на NextJS.

Существует базовый вариант использования, который может значительно выиграть от этой функции - несколько языковых версий. Веб-приложение, над которым я работаю, имеет около 16 языковых версий с более чем 100 000 просмотров страниц в день, и возможность просто статически сгенерировать, например, целевую страницу, была бы фантастической, но проблема заключается в маршрутизации.

С рендерингом на стороне сервера я могу читать заголовки запросов или файлы cookie и отображать правильную языковую версию, но без нее это единственное решение для создания путей для каждой версии, например / en, / de, / fr и на "/", чтобы NextJS просто перенаправлял?

Узнав о ReactDOMServer.renderToStaticMarkup я добавил его в свою функцию unstable_getStaticProps и обнаружил, что он улучшил мою (мобильную) оценку PageSpeed ​​с 96 до 100 благодаря значительному увеличению времени до взаимодействия и максимальной потенциальной задержки первого ввода .

Я могу посещать страницу без JavaScript, и она загружается нормально, поэтому кажется, что React работает над загрузкой страницы, несмотря на использование SSG.

Возможно, это недостаток моего понимания React, но я ожидал, что производительность с JavaScript и без него будет такой же, и я не ожидал, что предварительный рендеринг компонентов поможет (я думал, что это то, что делает SSG).

Ожидается, ошибка или что-то я делаю не так?

Предварительная фиксация: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2F5e310826bcf5030008a91209--josephduffynextjs.netlify.com%2Fposts%2Fgasted-1-0-1&tab=mobile
Фиксация: https://github.com/JosephDuffy/josephduffy.co.uk/pull/54/commit/d23898b874e5088ebcfabf577ee396b476ed97e4
После фиксации: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2F5e3371beda1b8f0009368ef9--josephduffynextjs.netlify.com%2Fposts%2Fgolated-1-0-1&tab=mobile

@JosephDuffy

Таким образом, похоже, что React работает над загрузкой страницы, несмотря на использование SSG.

Это увлажняет DOM. По сути:

  1. ваш браузер загружает SSR html в DOM браузера
  2. React перестраивает всю виртуальную DOM
  3. React просматривает эти DOM и синхронизирует их (гидратация)

Если ваш контент действительно статичен, и в нем нет побочных эффектов или обработчиков событий, то шаги 2 и 3 не нужны. С помощью вашего метода вы в основном уменьшаете свое дерево компонентов до 1 компонента с 1 атрибутом, что очень быстро для React для рендеринга и гидратации. (+ dangerouslySetInnerHTM игнорируется во время гидратации)

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

Имейте в виду, что обработчики событий и побочные эффекты не будут работать с этим методом.

Редактировать:

Одна из идей может заключаться в том, чтобы разрешить исключение экспорта по умолчанию на странице, если getStaticProps возвращает статический HTML. т.е.

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

Поскольку ничего не нужно отображать на стороне клиента, next.js может исключить свою среду выполнения со страницы и просто встроить html, который вернул getStaticProps . И это будет работать так же, как если бы dangerouslySetInnerHTML использовалось на корневом узле next.js.
Думаю, это было бы проще реализовать, чем частичное увлажнение, хотя и менее мощное. Повторное использование терминологии самого React здесь может уменьшить путаницу в том, как эта функция будет работать.

Я пытаюсь перенести статический сайт на Next.js и хочу перенаправить все варианты сообщений блога .html на версии, не заканчивающиеся на .html. Похоже, что getStaticProps настоящее время не получает контекста, поэтому я не могу выполнить проверку входящего слага и перенаправления. Было бы полезно, если бы у getStaticProps был полный контекст, чтобы я мог делать с ним некоторые условные вещи.

@nodabladam, похоже, вы ищете RFC для пользовательских маршрутов: # 9081.

Этот RFC позволит вам определить что-то вроде этого:

// 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
      }
    ];
  }
};

В настоящее время вы можете попробовать эту функцию с помощью ключа experimental :

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

Я реализовал getStaticProps и getStaticPathNames в своем проекте (около 8К страниц).

Однако выходные файлы учитываются при ограничении 10 КБ файлов на развертывание. Со страницами 8K вы получаете 16K выходных файлов, поскольку каждая страница также получает файл json.

Есть ли планы увеличить этот лимит? Или я могу обойти это ограничение?

У меня точно такая же проблема.
Я понимаю, что они хотят снять этот предел, но не знаю, когда он будет развернут.

Поэтому я использую getStaticProps на всех страницах и getStaticPaths только на некоторых из них, и это работает (моя страница продукта генерирует 70% от общего числа страниц, поэтому я не помещал в нее getStaticPaths). Я остаюсь ниже лимита, но он не идеален, первая загрузка довольно долгая и с трудом справляется с ошибками 404.

У меня точно такая же проблема.
Я понимаю, что они хотят снять этот предел, но не знаю, когда он будет развернут.

Поэтому я использую getStaticProps на всех страницах и getStaticPaths только на некоторых из них, и это работает (моя страница продукта генерирует 70% от общего числа страниц, поэтому я не помещал в нее getStaticPaths). Я остаюсь ниже лимита, но он не идеален, первая загрузка довольно долгая и с трудом справляется с ошибками 404.

Я надеюсь, что они скоро поднимут лимит, но я надеюсь, что это не будет 20K ... этого мне будет недостаточно в долгосрочной перспективе.

Я хочу избежать первой загрузки с помощью getStaticPaths .. Мне, возможно, придется искать другие решения помимо Zeit Now

Next.js также автоматически предоставит конечную точку API, которая возвращает результат вызова getServerProps. [...] Next.js будет извлекать эту открытую конечную точку API для получения данных JSON, которые превращаются в реквизиты, необходимые для рендеринга страницы на стороне клиента.

Next.js будет извлекать данные из этой конечной точки, прежде чем выполнять фактическое изменение маршрута и рендеринг компонента страницы (по крайней мере, по умолчанию он не может сделать это каким-либо другим способом). Таким образом, пользователь может столкнуться с чрезвычайно быстрым взаимодействием с сайтом из-за того, что определенные страницы генерируются статически, но если он щелкнет ссылку на страницу SSR, сайт внезапно «зависнет» на некоторое время, прежде чем маршрут изменится.

Есть ли рекомендуемый способ загрузки компонента _first_, чтобы он мог быть заполнен индикаторами загрузки, анимированными заполнителями и т. Д.? (Вместо того, чтобы добавлять их на текущую страницу.) Если нет, может ли это иметь отношение к новым предлагаемым функциям? Я добился этого, используя комбинацию getInitialProps и хуков внутри метода рендеринга, но это выглядит беспорядочно.

Я бы подумал, что этот шаблон UX (мгновенное переключение страниц) предпочитают многие (большинство?), Но я еще не видел его примеров с использованием Next.js. Я использовал фреймворк всего пару дней, так что поправьте меня, если я ошибаюсь.

Очень рад новым функциям! Спасибо за вашу работу.

@nicoqh , ваши опасения по поводу переходов страниц не относятся к SSG, поскольку зависание происходит с текущим getInitialProps . Я использую nprogress чтобы, по крайней мере, показывать вверху индикатор выполнения во время загрузки следующей страницы, но я также вижу этот пример легальных переходов между страницами, которые звучат ближе к тому, что вы описываете. Я сам не пробовал, но надеюсь, что это поможет с тем, что вам нужно:
https://github.com/zeit/next.js/tree/canary/examples/with-next-page-transitions

Похоже, что возвращаемый json-файл /_next/data/BUILD_ID/<file>.json не поддерживает assetPrefix. Это приводит к тому, что в моей производственной среде файл для меня имеет значение 404, поскольку у меня есть настройка, которая ожидает, что все _next будет активом, который проходит через CDN. Эти файлы json должны в конечном итоге маршрутизироваться через assetPrefix (CDN), верно?

У меня точно такая же проблема.
Я понимаю, что они хотят снять этот предел, но не знаю, когда он будет развернут.
Поэтому я использую getStaticProps на всех страницах и getStaticPaths только на некоторых из них, и это работает (моя страница продукта генерирует 70% от общего числа страниц, поэтому я не помещал в нее getStaticPaths). Я остаюсь ниже лимита, но он не идеален, первая загрузка довольно долгая и с трудом справляется с ошибками 404.

Я надеюсь, что они скоро поднимут лимит, но я надеюсь, что это не будет 20K ... этого мне будет недостаточно в долгосрочной перспективе.

Я хочу избежать первой загрузки с помощью getStaticPaths .. Мне, возможно, придется искать другие решения помимо Zeit Now

@erhankaradeniz и @ziltosh, мы должны очень скоро адресу [email protected], и они разберутся с вами.

У меня точно такая же проблема.
Я понимаю, что они хотят снять этот предел, но не знаю, когда он будет развернут.
Поэтому я использую getStaticProps на всех страницах и getStaticPaths только на некоторых из них, и это работает (моя страница продукта генерирует 70% от общего числа страниц, поэтому я не помещал в нее getStaticPaths). Я остаюсь ниже лимита, но он не идеален, первая загрузка довольно долгая и с трудом справляется с ошибками 404.

Я надеюсь, что они скоро поднимут лимит, но я надеюсь, что это не будет 20K ... этого мне будет недостаточно в долгосрочной перспективе.
Я хочу избежать первой загрузки с помощью getStaticPaths .. Мне, возможно, придется искать другие решения помимо Zeit Now

@erhankaradeniz и @Ziltosh, мы должны очень скоро адресу [email protected], и они разберутся с вами.

Спасибо @kvangundy
Я связался с вами в Твиттере по поводу этой проблемы ;-)

@erhankaradeniz Можете ли вы вместо этого адресу [email protected] ? Таким образом, он правильно попадает в нашу систему.

@flintinatux , спасибо за подсказку. Я видел пример, и он не помогает с загрузкой компонента страницы перед загрузкой данных, поэтому заполнители на странице и т. Д. Невозможны. Тем не менее, это интересный пример, спасибо!

Думаю, в этом выпуске он не будет рассматриваться, а это значит, что он не по теме, поэтому я найду где-нибудь еще, чтобы обсудить это :)

Я думаю, что подход разделения getInitialProps на getStaticProps & getServerProps намного чище! У меня есть вопрос, как это влияет на наш вариант использования:
Мы хотим создать 2 отдельные сборки: одну статическую версию для нашего сайта prod и одну версию с использованием SSR для среды редактирования.

Я думал, что могу условно прикрепить getStaticProps vs getServerProps как статические методы в зависимости от сборки (аналогично https://github.com/zeit/next.js/issues/9524#issuecomment- 558617056), но я не уверен, удастся ли условно экспортировать их как есть. Есть идеи, можно ли будет поддерживать динамическую / статическую в зависимости от сборки?

Что касается:

RFC будет обновлен, чтобы отразить изменения позже, но все еще повторяется для реального использования в наших приложениях.

Интересно, есть ли способ использовать какой-то маршрут с подстановочными знаками для перехвата маршрутов, которые неизвестны во время сборки. Замечательно, что я могу отображать статические страницы, например, из данных CMS, но что, если кто-то добавит новый элемент? У меня нет для этого статической страницы. Этот вопрос уже давно чешет меня в затылке.

Я настроил динамический маршрут для отображения статических страниц _pages / [slug] .js_. _getStaticPaths_ получает все страницы, которые я хочу отображать статически. У меня есть _getStaticProps_ для запроса данных и передачи их функции рендеринга. Все страницы, указанные в _getStaticPaths_, отображаются как файлы HTML внутри _.next/server/static_ при сборке. Большой!

Теперь я запускаю npm run start и эти страницы так, как должны. Но запрос отсутствующего URL-адреса (например, _ / foo_) создает новые статические файлы HTML и JSON внутри _.next/server/static_. Это не хорошо. Как я могу заставить сервер перенаправлять все остальные URL-адреса на _pages / _error.js_?

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

Мы тоже это освещаем.

Теперь я запускаю npm run start и эти страницы так, как должны. Но запрос отсутствующего URL-адреса (например, / foo) создает новые статические файлы HTML и JSON внутри .next / server / static. Это не хорошо. Как я могу заставить сервер перенаправлять все остальные URL-адреса на страницы / _error.js?

Это все еще в полете и на данный момент не является неожиданным поведением.

Еще раз напоминаем, что вы используете экспериментальную функцию и поведение может измениться в любой момент. Что-то изменится и, возможно, возникнет разрыв между всеми версиями, пока вы используете это, когда оно нестабильно.

@timneutkens Спасибо! Я понимаю нестабильность. Ты хоть представляешь, как с этим справиться? Просмотрел код и заметил, что выдача ошибки внутри _unstable_getStaticProps_ отображает страницу с ошибкой. Это могло бы быть хорошим способом пойти. Мне просто нужен способ передать ошибку, как в _pages / _error.js_. Я хотел бы отправить его 404. Теперь он идет как 500.

Я уже много раз публиковал это в других потоках, но «переход к _error» - это неожиданное поведение, так как сейчас ваша страница должна отображать состояние 404. Проще говоря if(!data.something) { return <My404Component /> } , а затем My404Component должен установить метатеги noindex .

Действительно? В документации четко указано использовать _pages / _error.js_ для 404.

См. Https://nextjs.org/docs/advanced-features/custom-error-page

@ jiv-e - это ошибка 404, вызванная:

  • Страница не найдена
  • Файл не найден

Если у вас есть динамические маршруты, вы должны обработать случай «404», как я уже сказал, например, https://nextjs.org/docs/advanced-features/custom-error-page#reusing -the-built-in-error- страница

Понятно! Спасибо!

Я хотел бы использовать getStaticProps для получения ключей перевода / языка во время сборки, потому что они, скорее всего, будут меняться 1-2 раза в месяц или даже в год. Также они не нужны как JSON / props в DOM. Проблема в том, что я не хочу передавать ключи вниз по дереву компоненту, где я их использую. Какие подходы подходят для моего варианта использования?

useTranslation () (или HOC) с контекстом?

Было бы неплохо, если бы AppTree был бы частью контекста NextGetStaticProps ( getStaticProps({ AppTree }) ). В противном случае невозможно будет запустить такие вещи, как apollos getDataFromTree на ssg.

На данный момент мы не планируем разрешать обход AppTree в getStaticProps, поскольку это очень плохо сказывается на производительности (постоянная обратная связь от компаний). Когда вы добавляете getStaticProps на страницу, он по-прежнему проходит через getInitialProps из _app, чтобы обеспечить постепенное внедрение, поэтому он все равно действительно будет работать с Apollo.

Было бы неплохо, если бы мы могли одновременно иметь amp: 'hybrid' и функциональность SSG .
Этого можно добиться, создав два файла для такой страницы, например:

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

Это позволит прокси-серверам разрешаться в документ amp на основе параметра запроса ?amp=1 .

Было бы неплохо, если бы мы могли одновременно иметь amp: 'hybrid' и функциональность SSG .
Этого можно добиться, создав два файла для такой страницы, например:

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

Это позволит прокси-серверам разрешаться в документ amp на основе параметра запроса ?amp=1 .

Точно @Dacturne , это единственный недостаток, который я вижу, чтобы начать использовать SSG уже в проектах, как я комментировал в этой ветке некоторое время назад.

🤞

@jansedlon Я сделал сообщение в блоге, отвечая на ваш вопрос:

Интересно, есть ли способ использовать какой-то маршрут с подстановочными знаками для перехвата маршрутов, которые неизвестны во время сборки. Замечательно, что я могу отображать статические страницы, например, из данных CMS, но что, если кто-то добавит новый элемент? У меня нет для этого статической страницы. Этот вопрос уже давно чешет меня в затылке.

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

(не размещать здесь, потому что он слишком большой)

@ ivan-kleshnin Я быстро посмотрел, и это выглядит супер захватывающе! Ты мог бы сэкономить мне сотни часов! Большое вам спасибо, я рассмотрю более подробно позже сегодня.

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

@jansedlon, как было сказано ранее, мы работаем над чем-то в связи с этим, что не описано в блоге @ ivan-kleshnin. Надеюсь, очень скоро удастся рассказать об этом больше.

@timneutkens Мне нравятся изменения 🙏 Есть ли у вас какие-либо планы по улучшению / поддержке полной статики + интернационализации?

Мы использовали новые API getStaticProps / getStaticPaths при миграции tinacms.org с Gatsby на Next.js, и до сих пор это было здорово!

У нас был один камень преткновения - создание RSS-канала. В идеале мы хотели бы генерировать его статически, поскольку контент, на который он ссылается, генерируется статически. В настоящее время я не вижу способа сделать это, поэтому вместо этого мы просто обрабатываем это на стороне сервера, запрашивая контент и записывая XML в ответ.

Обсуждалась ли поддержка статической генерации для типов контента, отличных от HTML?

К вашему сведению, сейчас мы начали использовать getStaticProps на zeit и выпусках с использованием флага --prod и кеш не очищался для файлов json в новых выпусках. Переключение нашего производственного выпуска обратно на использование функции псевдонима сработало, и кеш был очищен.

Мы использовали новые API getStaticProps / getStaticPaths при миграции tinacms.org с Gatsby на Next.js, и до сих пор это было здорово!

У нас был один камень преткновения - создание RSS-канала. В идеале мы хотели бы генерировать его статически, поскольку контент, на который он ссылается, генерируется статически. В настоящее время я не вижу способа сделать это, поэтому вместо этого мы просто обрабатываем это на стороне сервера, запрашивая контент и записывая XML в ответ.

Обсуждалась ли поддержка статической генерации для типов контента, отличных от HTML?

Я думал об этом для себя и только что узнал об этом. Вот мои сценарии:

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

Перед next build вызывается yarn sitemap который генерирует статическую карту сайта. Вы можете использовать ту же технику, например, для кэширования всех данных в json, которые вам понадобятся в getStaticProps и вы можете повторно использовать их на нескольких страницах.

Обновлен RFC, немного изменено поведение getStaticPaths (вам нужно вернуть ключ paths сейчас, это отражает getStaticProps где нужно вернуть props . Это изменение еще не попало в Next.js.

Также добавлено объяснение поведения fallback (фоновое создание страниц по запросу, которые не были экспортированы во время сборки).

Сделано еще одно обновление RFC, добавлено объяснение изменений в клиентской навигации в отношении состояния Loading .

Возможно, мы захотим добавить способ, позволяющий пользователям узнать, отображается ли состояние загрузки с помощью хука React 🤔

Отличный материал! Мне просто было интересно, будет ли способ для статически сгенерированных страниц обмениваться данными между несколькими маршрутами с использованием одного файла JSON (например, с разделением кода, но для данных)?

Я поднялся до последней сборки canary и сразу понял, что новое состояние Loading . В прошлом было приятно предположить, что у меня уже есть нужные данные до того, как слой представления начнет рендеринг. Принудительная асинхронная загрузка - большой отход от этого. Мне очень понравилось извлекать все стандартные конечные точки, которые заменят новые автоматически сгенерированные конечные точки SSR, но я не планировал переделывать каждую страницу, чтобы включить новые состояния Loading .

Я понимаю желание более быстрого TTFB, и в будущем это может быть полезно для моего приложения. Но это было бы возможно сделать Loading состояние неавтоматического или Блокировщика функцию, аналогичную fallback: false за getStaticPaths ? Возможно, export const enableLoadingState = false на странице или всего сайта в next.config.js .

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

Еще раз напоминаем, что вы используете экспериментальную функцию и что мы экспериментируем с ее поведением в настоящее время.

Я развернул свой (экспериментальный) веб-сайт SSG в Now (используя настройку по умолчанию). Он работает нормально, но я вижу ошибку 404 на вкладке сети при просмотре сайта. Все ошибки 404 указывают на _next/static/pages/[slug].js .

Это ожидаемое поведение, пока оно экспериментальное? Или мне нужно поменять какие-то настройки?

@joostmeijles похоже, что вы не предоставляете правильные href и as для next/link . Для динамических страниц href должен быть страницей href='/[slug]' а as должен быть URL as='/slug-1'

Я получаю 3 лога в консоли во время сборки, это ошибка?

// 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" } },
        ]
    }
}

Нет, это ожидается согласно fallback в RFC.

Нет, это ожидается согласно fallback в 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" } },
        ]
    }
}

Я пытался отказаться, но получаю эту ошибку.

Ошибка: дополнительные ключи возвращены из unstable_getStaticPaths в / [год] (резерв) Единственное допустимое поле в настоящее время - paths

Еще раз напоминаем, что вы используете экспериментальную функцию, и что мы экспериментируем с ее поведением в настоящее время, но не все реализовано.

Будет ли эта функция getStaticProps доступна только для страниц?
Было бы интересно также для приложения / документа, например, получить некоторую глобальную конфигурацию для приложения?

Я «успешно» реализовал это и пока доволен результатами ... но мне интересно, есть ли способ сделать последующие сборки «быстрее»? Например, проверьте, не изменились ли страницы, сгенерированные SSG, и не создавайте их повторно? (Вероятно, принятие желаемого за действительное от меня)

@timneutkens Есть ли планы добавить генератор sitemap.xml для страниц SSG? Я даже не говорю о динамических маршрутах, так как считаю, что пока проще реализовать это только для статических страниц.

@timneutkens Есть ли планы добавить генератор sitemap.xml для страниц SSG? Я даже не говорю о динамических маршрутах, так как считаю, что пока проще реализовать это только для статических страниц.

Да, это был бы отличный вариант. В настоящее время создаю один с SSR. (но файл sitemap.xml загружается долго)

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

Первоначально только для страниц, потому что после его приземления будет другая работа, которая повлияет на getStaticProps.

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

Да, но не в рамках этого RFC. После этой земли будет продолжение.

@timneutkens Я думаю, что реализация страниц SSG проста, потому что вы можете вставлять URI в массив каждый раз, когда Next создает статическую страницу, а затем, когда она заканчивается, просто сопоставляйте массив с каждым тегом XML, присоединяйтесь и вставляйте его в середину тега <sitemapindex> . getStaticProps может иметь другой ключ в возвращаемом объекте с именем excludeFromSitemap поэтому по умолчанию все страницы будут включены в sitemap.xml но с возможностью отказа.

Если бы это было так, разработчики могли бы точно контролировать, какая статическая страница будет помещена в карту сайта (например: если страница [foo] getStaticPaths функция возвращает пути с foo params 'abc' и 'xyz' но в карте сайта должен быть только файл 'abc' , разработчик сможет установить excludeFromSitemap на true если параметр ==='xyz' в getStaticProps .

Кроме того, для SSR и статических страниц можно было бы экспортировать константу (например, export const excludeFromSitemap = true; ) из файла страницы, как getServerProps , getStaticPaths и getStaticProps экспортируются.

На страницах SSG, если существует экспортированная константа excludeFromSitemap (по умолчанию для страницы) и этот ключ также находится в объекте, возвращаемом функцией getStaticProps (для конкретного пути), экспортированное значение должно действовать как значение по умолчанию. значение для всех путей на этой странице и конкретный путь excludeFromSitemap , если он присутствует в объекте getStaticProps , должен переопределять значение страницы по умолчанию (чтобы страница могла выполнять export cosnt excludeFromSitemap = true а затем добавьте ключ excludeFromSitemap к объекту, возвращаемому из getStaticProps со значением false чтобы исключить все пути из карты сайта, кроме этого конкретного).

Код для добавления в массив будет примерно таким (я вычислил таблицу истинности и получил минимальное логическое выражение с картой Карно):

//...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);

Превратить массив в карту сайта было бы так же просто (при условии, что URI в массиве уже закодированы и отфильтрованы по !excludeFromSitemap ):

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

Я думаю, что эта функция будет хорошо вписываться в Next.JS, потому что часть его миссии - дать пользователям оценку 100 SEO, и наличие sitemap.xml очень поможет! ( robots.txt потенциально также может быть сгенерировано добавлением else к условию, которое добавляет пути к массиву карты сайта, чтобы добавить этот путь в другой массив запрещенных страниц)

В текущей версии выпуска при использовании unstable_getStaticPaths вместе с функцией unstable_getStaticProps нельзя выполнять вызовы api для функций, находящихся в /api/ .
Поскольку сервер не работает, невозможно сделать соответствующие запросы и таким образом сгенерировать статические реквизиты.
Вам либо нужно не предоставлять функции путей (что в основном делает этот SSR с кешем, что по-прежнему приятно!), Либо полагаться на SSR вместо SSG.

Может быть, это было бы хорошим дополнением к этой функции? Я не уверен, что здесь лучше всего. Я читал где-то еще предложение, в котором предлагалось сократить http-запрос с помощью SSR и маршрутов /api , здесь это тоже пригодится.

Но все это, конечно, означало бы запуск кода в среде сборки, который будет вызывать другие службы / вызовы db или аналогичные. Это должно быть ясно сказано, когда это будет реализовано, но это было бы отличным дополнением к этой функции.

@reckter Ага, я и сам делал нечто подобное. Мне приходилось подключаться к моей базе данных для каждого отдельного запроса страницы, пока они генерировались статически. Было очень странно ...

Я надеюсь, что это не последний вариант использования

Было бы неплохо иметь какой-то сценарий инициализации, который вы можете настроить из файла next.config или чего-то еще ...

@reckter Способ сокращения HTTP-запросов к маршрутам API из SSG / SSR был бы настолько хорош! Мне кажется странным делать сетевой запрос самому себе в любом из этих сценариев.

В любом случае, возможным решением для доступа к маршрутам API во время SSG было бы иметь локальный сервер, на котором выполняются только маршруты /api перед компиляцией статических страниц! Итак, шаги сборки будут следующими:

  1. Запустите сервер (может быть, он называется "сервер компиляции api" или что-то в этом роде), обслуживающий только маршруты /api
  2. Запустить unstable_getStaticPaths
  3. Запустить unstable_getStaticProps
  4. Скомпилируйте статические страницы

@reckter в основном вам не нужно вызывать маршруты API, вы можете напрямую вызывать функцию, которую он реализует, это также позволяет избежать большого количества накладных расходов, связанных с причинами http.

В основном, если в настоящее время у вас есть маршрут API, который выглядит следующим образом:

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

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

Вы бы изменили его на:

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

А потом на вашей странице:

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

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

Было бы сложно сделать то же самое для API GraphQL. А также для большинства REST.

Вызов API! = Выборка из БД (в общем)
На уровне API почти всегда есть бизнес-логика, такая как переименование полей, переформатирование данных и т. Д.

Я уверен, что у вас есть причины запретить вызовы pages/api ... но обход реального API не будет простым и дешевым. И пара сэкономленных миллисекунд не перевесит плату за дополнительный код / ​​сложность IMO.

Также странно, что запросы к любому API будут разрешены. Кроме твоего собственного 🤷‍♂

использование unstable_getStaticPaths вызывает перезагрузку страницы, например, потерю текущего состояния в redux. Изменится ли это поведение в будущем?

изменить: похоже, это поведение можно обойти, используя параметр as в ссылках или маршрутизаторе

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

@meesvandongen всегда было так. Если ваш <Link> недействителен, вы перейдете к бэкэнд-части, в основном работая как <a> . Динамические фрагменты, такие как [key] должны быть связаны с соответствующими значениями.

@reaktivo pages/[lang]/blog/[id].js -> в getStaticPaths предоставляет все URL-адреса для статической визуализации.

https://github.com/zeit/next.js/issues/9524#issuecomment -562625858
в этом случае необходимо добавить функцию getStaticPaths и getStaticProps для каждой страницы, кроме index.js.
Если есть несколько mdx-страниц, проект сложнее поддерживать

рассмотреть возможность изменения или совместимости со статическими методами getStaticPaths getStaticProps . https://github.com/zeit/next.js/issues/9524#issuecomment -558617056
Если это так, страница может быть обернута функцией высшего порядка или компонентом высшего порядка (HOC).
Таким образом, код более удобен в сопровождении и для typesscript.


встряхивание деревьев vs динамическое. Какой компромисс с головной болью.

С 9.2.3-canary.13 я попытался использовать fallback: false в getStaticPaths следующим образом:

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

но это не удается со следующей ошибкой:

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

С 9.2.3-canary.13 я попытался использовать fallback: false в getStaticPaths следующим образом:

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

но это не удается со следующей ошибкой:

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

Я думаю, вам нужна карта на уровень выше, поэтому карта возвращает объект, который у вас есть, но с уникальным слагом. вместо отображения в путях.

Я еще не обновил свою версию на nextjs, но она должна быть похожей:

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

@jorngeorg это открытый пиар: https://github.com/zeit/next.js/pull/10701

Фантастический вклад! Это действительно улучшает статический процесс рендеринга.

Я рекомендую добавить в документацию, что на динамических маршрутах «резервный» будет сгенерирован без какого-либо вызова getStaticProps - это означает, что вы должны закодировать свой компонент, чтобы учесть случай, когда props пуст.

В качестве альтернативы вы можете изменить поведение для вызова getStaticProps без контекста при создании резервной копии. Это согласуется с тем, как в настоящее время работает next export (например, /p/[id].js экспортируется в /p/[id].html путем запуска getInitialProps без контекста).

  • getStaticProps - включение статической генерации (SSG) в next build time.
  • getServerProps - Включите рендеринг на стороне сервера (SSR), который рендерится по запросу.

10722

Переименуйте getServerProps в getServerSideProps.

Я рекомендую добавить в документацию, что на динамических маршрутах «резервный» будет сгенерирован без какого-либо вызова getStaticProps - это означает, что вы должны закодировать свой компонент, чтобы учесть случай, когда props пуст.

Хороший момент, чтобы упомянуть об этом! У меня также были ошибки сборки / развертывания, потому что я их пропустил.

Обновлен RFC, чтобы отразить изменения.

@timneutkens

  • Последующий запрос по тому же пути будет обслуживать сгенерированную страницу.

Я предполагаю, что это означает, что Next.js будет кэшировать сгенерированную страницу? Это кеш в памяти? Ограничен ли этот кеш лимитами или это может привести к утечкам памяти?

Когда вы используете next start он использует lru-cache, аналогичный текущему примеру кеширования, в настоящее время ограничение по умолчанию составляет 50 МБ, мы можем сделать его настраиваемым позже: https://github.com/zeit/next.js/ blob / канарейка / пакеты / следующий / следующий-сервер / сервер / spr-cache.ts # L90

Когда вы размещаетесь на ZEIT. Теперь генерация и кэширование происходят на CDN / прокси, поэтому он работает немного иначе, и вам никогда не придется беспокоиться об утечках памяти или превышении лимита lru.

👍 окей, кажется разумным. Это более или менее то, что я имел в виду как разумное поведение по умолчанию.

  • getStaticProps - включение статической генерации (SSG) в next build time.
  • getServerProps - Включите рендеринг на стороне сервера (SSR), который рендерится по запросу.

10722

Переименуйте getServerProps в getServerSideProps.

Зачем же переименование? IMHO getServerProps достаточно точен и короче для ввода, добавление Side кажется мне излишним.

Мне было интересно, внесены ли какие-либо изменения в метод getStaticPaths? Мои динамические страницы больше не создаются как статические, теперь они экспортируются как лямбда-функции?

Правильно ли я, когда поведение по умолчанию теперь таково, что страницы сначала отображаются как лямбда-выражения, и только после посещения определенной страницы страница создается как статическая? (точно так же, как упомянуто в резервной копии)

@erhankaradeniz В getStaticPaths не было внесено никаких изменений, которые привели бы к тому, что ваши страницы были бы лямбдами. Вероятно, это ошибка использования.

Не могли бы вы показать свой код, чтобы мы могли определить проблему?

@Timer на данный момент я вернулся к [email protected], где я все еще могу использовать параметры, пока не

вот как я сейчас генерирую свои пути:

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

а на другой странице я делаю:

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

не удалось преобразовать его в новую канареечную версию с путями. Я, должно быть, делаю что-то не так, потому что console.logs даже не запускается в getStaticPath

У меня проблемы с предварительной отрисовкой вложенного пути и 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("/"),
        }
      }
    }),
  }
}

приводит к

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.

для домашней страницы. По какой-то причине NextJS не соответствует

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

к

/[lang]/[...slugs]

Если я предоставлю {lang: "en", slugs: ["/"]} он будет построен, но с неправильным URL:

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

Для записи, getServerSideProps отлично работает с аналогичной настройкой.

Я знаю, что это экспериментально, но эта ветка предназначена для обратной связи, верно?

pages/[lang]/[...slugs].js соответствует /en/abcdef а не /en , для этого в настоящее время необходимо создать pages/[lang]/index.js .

Для этого открыт запрос функции: https://github.com/zeit/next.js/issues/10488

Во-первых, это круто. Я надеялся иметь что-то подобное в Next.js, чтобы я мог наконец отказаться от Gatsby.js и иметь гибридное приложение (статическое + динамическое).

🚀 Я пробовал канарейку, и сложная наполовину запеченная версия приложения работала нормально. Признаюсь, я не прочитал здесь все комментарии, но не уверен, что уже реализовано встряхивание дерева.

🤔 getStaticPaths больше похоже на setStaticPaths где мы определяем статический путь для поведения SSG. Это меня немного смутило.

🧐 Интересно, сможем ли мы сократить время сборки за счет категорий сборки? Я знаю, что это усложнит настройку, но оно того стоит. Позволь мне объяснить:

Что, если у нас есть что-то вроде setBuildCategory которое устанавливает его в blog или pages или что-то еще, что кто-то хочет 2020-content . Затем построитель SSG ищет категорию страницы, которая была изменена, и пытается восстановить эту категорию только из комбинации кеша + нового рендеринга. Что-то вроде этого может помочь нам сделать SSG быстрым и избежать огромных затрат времени на сборку вещей, которые не склонны к значительным изменениям, но все же могут измениться, поэтому не могут быть заархивированы.

Если в этом есть смысл; Я счастлив позвонить и поговорить об этом.

Как справиться с getServerSideProps с пользовательской реализацией сервера?

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

В приведенном выше примере при посещении /a отображается страница pages/b.js . Но перенаправление на стороне клиента на /a пытается загрузить файл a.json , которого в данном случае не существует.

Должны ли мы иметь аналогичные условия для запросов к /_next/data/{BUILD_ID}/{PAGE}.json для рендеринга разных файлов JSON?

Как получить объект req при использовании fallback: true в getStaticPaths? В настоящее время кажется, что я не могу. Причина, по которой мне это нужно, - это получить некоторые файлы cookie из браузера для аутентификации маршрута.

@tylermcrobert, как вы себе представляете захват файлов cookie, когда вообще нет запроса ?!
Маршруты с бэкэндом, зависящие от запросов реальных посетителей, не могут быть статическими по определениям «статический» и «динамический». Нельзя сказать, что вы не можете комбинировать статику и аутентификацию ... просто часть аутентификации будет принадлежать API и клиентскому коду, а не страницам.

Как справиться с getServerSideProps с пользовательской реализацией сервера?

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

В приведенном выше примере при посещении /a отображается страница pages/b.js . Но перенаправление на стороне клиента на /a пытается загрузить файл a.json , которого в данном случае не существует.

Должны ли мы иметь аналогичные условия для запросов к /_next/data/{BUILD_ID}/{PAGE}.json для рендеринга разных файлов JSON?

Next.js поддерживает параметры динамического маршрута, поэтому переназначение на настраиваемом сервере больше не требуется: https://nextjs.org/docs/routing/dynamic-routes

Подход, который вы уже описали, не работает с <Link> (вызовет полный переход страницы), поэтому getServerSideProps уже работает.

@tylermcrobert, как вы себе представляете захват файлов cookie, когда вообще нет запроса ?!
Маршруты с бэкэндом, зависящие от запросов реальных посетителей, не могут быть статическими по определениям «статический» и «динамический». Нельзя сказать, что вы не можете комбинировать статику и аутентификацию ... просто часть аутентификации будет принадлежать API и клиентскому коду, а не страницам.

Может быть, в таком случае я неправильно понимаю запасной вариант. То, что вы говорите, имеет смысл в контексте времени сборки.

Разве fallback: true для случая, когда нет предопределенного маршрута? В этом случае откат будет доступен из браузера, не так ли?

@tylermcrobert да fallback: true case имеет запрос, но API должен быть объединен "наименьшим общим знаменателем". Я не могу представить себе работающую систему, в которой все построено с одним набором помещений, а затем постепенно обновляется с помощью совершенно другого набора помещений. Поддерживать это будет катастрофой.

Я думаю, вы упускаете тот момент, что эти инкрементные сборки все равно будут кэшироваться между сборками. Таким образом, роль первого посетителя будет влиять на результат сборки для всех последующих пользователей! Похоже на плохую идею.

@ ivan-kleshnin Я понимаю и, конечно, согласен. Причина, по которой я спрашиваю, связана с моим конкретным вариантом использования.

Я использую автономную CMS, которая позволяет выполнять предварительный просмотр, поэтому страницы, которые необходимо предварительно просмотреть, не будут включены во время сборки (поскольку просматриваемая запись на этом этапе не существовала). Я подумал, что это тот случай, когда пригодится запасной вариант.

Чтобы получить доступ к этому предварительному просмотру, мне нужен доступ к ссылке предварительного просмотра api, которая предоставляется через cookie.

Это тот случай, когда я должен полностью отказаться от useStaticProps ? Я бы не хотел потерять преимущества статических сборок, потому что я не могу предварительно просмотреть свои документы.

Привлекательность этого RFC по сравнению с чем-то вроде gatsby заключается в том, что он дает нам «гибридный контроль» с генерацией статических сайтов, что упрощает работу с безголовыми CMS.

Я использую автономную CMS, которая позволяет выполнять предварительный просмотр, поэтому страницы, которые необходимо предварительно просмотреть, не будут включены во время сборки (поскольку просматриваемая запись на этом этапе не существовала). Я подумал, что это тот случай, когда пригодится запасной вариант.

Следите за обновлениями, скоро еще

Итак, если я правильно понимаю, мы можем использовать резервное значение true, когда, например, в моем случае пользователь регистрируется (статическая страница не создается, поскольку это новая страница / пользователь), но когда профиль получает посещение, он создается автоматически?

Эрхан Карадениз
http://www.erhankaradeniz.com

4 марта 2020 года в 20:25 Тим Нейткенс [email protected] написал:


Я использую автономную CMS, которая позволяет выполнять предварительный просмотр, поэтому страницы, которые необходимо предварительно просмотреть, не будут включены во время сборки (поскольку просматриваемая запись на этом этапе не существовала). Я подумал, что это тот случай, когда пригодится запасной вариант.

Следите за обновлениями, скоро еще

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub или откажитесь от подписки.

Пользовательские данные - плохой пример, так как вы хотите получить эту клиентскую сторону. Резервный вариант существует для статически генерируемых страниц по запросу, которые не были созданы во время сборки. Например, вы можете захотеть создать 100 лучших сообщений в блоге во время сборки, а не создавать другие с меньшим трафиком.

Документы будут опубликованы в ближайшее время.

Да, я имел в виду страницу-заполнитель ... Я бы действительно получил данные пользователя на стороне клиента.

@timneutkens Будет ли какой-либо способ удалить или перестроить определенные статически сгенерированные страницы?

Привет!!! Звучит как оптимальное приложение. Мне очень нравятся и React, и Next !!! Сделано все так элегантно и просто для нас !! Но в пример входит понятие блога. Я хотел бы увидеть пример реализации при запросе Headless CMS и сделать выборку для каждой страницы / публикации как экспорт как статический элемент.

// ура, скоро пятница !!!

@timneutkens, это интересно 👌

Один сценарий, который мы часто встречаем, и у меня пока нет идеального решения с next.js или gatsby, кроме динамических маршрутов или генерации проектов в цикле:

По историческим причинам нам приходится иметь дело с несколькими доменами (и нет желания это менять), которые обслуживают одни и те же / точные страницы, за исключением цен, валюты, номеров телефонов службы поддержки и языковых переключателей. По своей природе большинство этих маркетинговых страниц довольно статичны, и их будет достаточно создавать ежедневно или еженедельно (вместо того, чтобы отображать их по каждому запросу).

Мой вопрос / мысль: видите ли вы способ (в будущем?) getStaticPaths может генерировать страницы на основе чего-то, что не является параметром маршрута, но может использоваться на уровне запроса для переключения между ними (например, без сервера функция возвращает статический, предварительно созданный результат на основе locale )

Конкретно это будет означать, что https://mysite.com/my-product и https://mysite.co.uk/my-product будут обслуживать две разные статические страницы, но без необходимости создания нашего следующего приложения 50 раз или необходимости обращения к CMS при каждом запросе😅

Заранее благодарим и желаем услышать ваши мысли, особенно если это что-то на будущее, которое можно решить / обойти ❤️

Я думаю о сценарии использования, когда я хочу использовать SSG для целевых страниц с высоким трафиком для SEO и для снижения нагрузки на сервер, но все же хочу, чтобы текущие данные использовались после гидратации и для маршрутизации на стороне клиента на эту страницу. Возможно ли это?

Таким образом, в основном при маршрутизации на стороне клиента к этой странице поведение должно быть похоже на getInitialProps (текущие данные извлекаются до того, как страница станет видимой). А при маршрутизации на стороне сервера на эту страницу статический html должен обслуживаться и гидратироваться, а затем (необязательно) извлекаться некоторые ответы api для обновления некоторых данных на странице.

Я просто играл с unstable_getStaticProps просто чтобы попробовать, и столкнулся с забавным конфликтом: сложно использовать маршруты API с getStaticProps .

Не обращайте внимания на семантику кода, а только на поток выборки данных:

// 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())
    },
  };
}

Сборка страницы завершится сбоем во время сборки, потому что сервер не запущен. Я не уверен, что это допустимый вариант использования, поскольку getStaticProps не следует использовать с чем-либо слишком динамичным, но я подумал, что это интересный крайний случай, которым можно поделиться (я полностью могу представить конечную точку API Route, отвечающую за получение данные из другого API и переформатировать их.

@martpie Возможно, вы захотите проверить этот комментарий: https://github.com/zeit/next.js/issues/9524#issuecomment -589772756

Поддержка генерации статических сайтов следующего поколения (SSG) стала стабильной в Next.js 9.3!

Этот выпуск также включает поддержку «режима предварительного просмотра» или возможность обхода статически предварительно отображаемой страницы и визуализации страницы по запросу для авторизованных пользователей .

Вы можете прочитать об этом в нашем блоге . Если у вас больше возможностей, сразу переходите к нашей документации !

Отправляйте любые вопросы в

Это так круто! Спасибо за тяжелую работу!

Эта новая функция, похоже, сейчас не работает с saga и redux

Была ли эта страница полезной?
0 / 5 - 0 рейтинги