Можно ли пропустить создание страницы во время сборки, если эта страница в конечном итоге выдает во время рендеринга? - PullRequest
2 голосов
/ 24 января 2020

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

Эта страница создана программно через gatsby-node createPage и возможно, что данные из запроса страницы (из нашей CMS) являются плохими, вызывая их выброс.

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

Любые идеи о том, как этого добиться?


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

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

Например, допустим, я создаю много страниц для все продукты на моем сайт. Компонент ожидает, что каждый продукт имеет imagesSizes и вызывает imagesSizes.split(',') во время рендеринга. Поскольку imagesSizes - это null из запроса страницы , весь компонент выдает ошибку и прерывает сборку.

Как и предложил @EliteRaceElephant, Я пытался использовать React Error Boundaries и, к сожалению, они не работают для SSR (который используется Gatsby во время сборки). Таким образом, даже если я заверну свой компонент в границу ошибки, он все равно будет нарушать сборку.

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

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


Исторически, когда я делал SSR за пределами Гэтсби, я просто упаковывал весь вызов в ReactDOMServer.renderToString в блоке try catch и просто возвращал свою резервную страницу в catch block.

Что такое эквивалент Гэтсби?

1 Ответ

3 голосов
/ 26 января 2020

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

Из документации по API узла Гэтсби :

const path = require(`path`)
exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  const blogPostTemplate = path.resolve(`src/templates/blog-post.js`)

  return graphql(`
    query loadPagesQuery ($limit: Int!) {
      allMarkdownRemark(limit: $limit) {
        edges {
          node {
            frontmatter {
              slug
            }
          }
        }
      }
    }
  `, { limit: 1000 }).then(result => {
    if (result.errors) {
      throw result.errors

      // ##### Handle your ERROR here #######
      // send to sentry, try another query, etc
      // or pass an empty result object so no pages are created but the build continues

    }
    result.data.allMarkdownRemark.edges.forEach(edge => {
      createPage({
        path: `${edge.node.frontmatter.slug}`,
        component: blogPostTemplate,
        context: {},
      })
    })
  })
}

РЕДАКТИРОВАТЬ # 1

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

<PageTemplate>
  <ErrorBoundary>
    <YourContent />
  </ErrorBoundary>
</Page Template>

РЕДАКТИРОВАТЬ # 2

Теперь я понимаю проблему и могу предложить некоторые предложения. Я не думаю, что есть простое решение, поскольку оно касается внутренней работы как React, так и Gatsby:

попробуйте поймать не являющиеся React части вашего шаблона. Используйте функции-обертки, которые пытаются перехватывать ошибки.

Я предполагаю, что у вас внутри кода JSX есть что-то вроде этого:

<PageTemplate>
  { imagesSizes.split(',') // do whatever and break the build }
</PageTemplate>

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

let pageThrows = false;

const imageSizesSplitCheck = (images) => {
  try {
    imagesSizes.split(',') // throw error
  } catch {
    pageThrows = true; // outside of the JSX flow you can still catch errors while serverside renddering
  }
}
// more try catch functions

if (pageThrows) {
  // render error page
} else {
  // render default page 
}


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

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