SUPER_OLEG_DEV Telegram 69
Привет!

Про обработку ошибок рендеринга при SSR.

Сразу начну с примеров обработки таких ошибок.

Во многих мета-фреймворках (Next.js, Remix, SvelteKit, Nuxt.js) есть простой способ отобразить UI при ошибках в компонентах. Там где поддерживается вложенный роутинг, этот error компонент можно добавлять на уровне конкретных страниц, и таким образом рендерить error UI локально (поиграться с примером на Next.js можно тут - https://app-dir.vercel.app/error-handling/books). Как правило, дополнительно всегда есть общий для всех дефолтный компонент - страница ошибки, который будет использован в том числе если ошибка произошла вне React (например в любом месте в серверном обработчике запроса).

Какие именно ошибки вообще можно и нужно обрабатывать? Если мы говорим про роуты, вот два основных кейса:

- expected ошибки, связанные с загрузкой данных для роута - когда надо программно выбросить 404 или 500 ошибку и отобразить подходящий UI, это область ответственности meta-фреймворка, ошибку легко поймать
- unexpected ошибки, по сути любой throw внутри React компонента страницы, и такую ошибку достаточно сложно обработать

Кажется, что кейсы unexpected ошибок должен решать React, но тут очень много подводных камней.

У нас же есть Error Boundary и все ок? - к сожалению нет, он поймает только ошибки в рантайме браузера, если например throw произошел при обработке клика от пользователя.

Остаются ошибки при серверном рендеринге и ошибки гидрации.

Так, мы копнули глубже (https://github.com/reactjs/rfcs/blob/main/text/0215-server-errors-in-react-18.md, и узнали что с 18 версии реакта Suspense тоже обрабатывает ошибки, как раз на сервере и при гидрации.

Если коротко, Suspense при ошибке вложенного компонента на сервере отрисует fallback компонент, сериализует ошибку для передачи на клиент, затем на клиенте, если этот же компонент снова выкинет исключение, Suspense не будет его обрабатывать, и оно попадет в ближайший Error Boundary.

Тут тоже есть нюансы:

- Если используем renderToString на сервере - никак не сможем залогировать ошибку, изменить код ответа, все произойдет “молча”. Только на клиенте, если использовать hydrateRoot, можно залогировать серверную ошибку в onRecoverableError
- С renderToPipeableStream все уже лучше, есть обработчики ошибок, у нас почти полный контроль, но мы все-равно не знаем в каком именно компоненте произошла ошибка (парсить стек-трейс этой ошибки неблагодарное дело), и в fallback UI не имеем прямого доступа к объекту этой ошибки
- Не все пользователи перешли на React 18, мета-фреймворки еще не могут завязаться на этот механизм
- В идеале хочется рендерить один и тот же fallback и в Suspense, и в Error Boundary - но как минимум у Suspense фаллбэка нет доступа к ошибке, уже не получится отрисовать аналогичный UI

По итогу, Suspense в связке с Error Boundary вполне подойдет для повышения надежности и производительности (Selective Hydration) каких-нибудь островков на страницах, таких как микрофронтенды (хотя и тут много чего надо учитывать вне реакта, например падение запроса за JS кодом микрофронта на сервере - надо отрендерить фаллбэк, перезапросить на клиенте, будет много кастомного кода), но реализовать полноценный Page Error Boundary только с этими механизмами не получится.

Так как же устроен этот механизм у Next.js, или у Remix?

Я первый раз исследовал эту тему когда добавлял Page Error Boundary в tramvai в прошлом году - https://tramvai.dev/docs/features/error-boundaries#specific-fallback, и смотрел как раз в исходники Remix, которые порадовали своей простотой и комментариями, в отличие например от некста.
👍10🔥1



tgoop.com/super_oleg_dev/69
Create:
Last Update:

Привет!

Про обработку ошибок рендеринга при SSR.

Сразу начну с примеров обработки таких ошибок.

Во многих мета-фреймворках (Next.js, Remix, SvelteKit, Nuxt.js) есть простой способ отобразить UI при ошибках в компонентах. Там где поддерживается вложенный роутинг, этот error компонент можно добавлять на уровне конкретных страниц, и таким образом рендерить error UI локально (поиграться с примером на Next.js можно тут - https://app-dir.vercel.app/error-handling/books). Как правило, дополнительно всегда есть общий для всех дефолтный компонент - страница ошибки, который будет использован в том числе если ошибка произошла вне React (например в любом месте в серверном обработчике запроса).

Какие именно ошибки вообще можно и нужно обрабатывать? Если мы говорим про роуты, вот два основных кейса:

- expected ошибки, связанные с загрузкой данных для роута - когда надо программно выбросить 404 или 500 ошибку и отобразить подходящий UI, это область ответственности meta-фреймворка, ошибку легко поймать
- unexpected ошибки, по сути любой throw внутри React компонента страницы, и такую ошибку достаточно сложно обработать

Кажется, что кейсы unexpected ошибок должен решать React, но тут очень много подводных камней.

У нас же есть Error Boundary и все ок? - к сожалению нет, он поймает только ошибки в рантайме браузера, если например throw произошел при обработке клика от пользователя.

Остаются ошибки при серверном рендеринге и ошибки гидрации.

Так, мы копнули глубже (https://github.com/reactjs/rfcs/blob/main/text/0215-server-errors-in-react-18.md, и узнали что с 18 версии реакта Suspense тоже обрабатывает ошибки, как раз на сервере и при гидрации.

Если коротко, Suspense при ошибке вложенного компонента на сервере отрисует fallback компонент, сериализует ошибку для передачи на клиент, затем на клиенте, если этот же компонент снова выкинет исключение, Suspense не будет его обрабатывать, и оно попадет в ближайший Error Boundary.

Тут тоже есть нюансы:

- Если используем renderToString на сервере - никак не сможем залогировать ошибку, изменить код ответа, все произойдет “молча”. Только на клиенте, если использовать hydrateRoot, можно залогировать серверную ошибку в onRecoverableError
- С renderToPipeableStream все уже лучше, есть обработчики ошибок, у нас почти полный контроль, но мы все-равно не знаем в каком именно компоненте произошла ошибка (парсить стек-трейс этой ошибки неблагодарное дело), и в fallback UI не имеем прямого доступа к объекту этой ошибки
- Не все пользователи перешли на React 18, мета-фреймворки еще не могут завязаться на этот механизм
- В идеале хочется рендерить один и тот же fallback и в Suspense, и в Error Boundary - но как минимум у Suspense фаллбэка нет доступа к ошибке, уже не получится отрисовать аналогичный UI

По итогу, Suspense в связке с Error Boundary вполне подойдет для повышения надежности и производительности (Selective Hydration) каких-нибудь островков на страницах, таких как микрофронтенды (хотя и тут много чего надо учитывать вне реакта, например падение запроса за JS кодом микрофронта на сервере - надо отрендерить фаллбэк, перезапросить на клиенте, будет много кастомного кода), но реализовать полноценный Page Error Boundary только с этими механизмами не получится.

Так как же устроен этот механизм у Next.js, или у Remix?

Я первый раз исследовал эту тему когда добавлял Page Error Boundary в tramvai в прошлом году - https://tramvai.dev/docs/features/error-boundaries#specific-fallback, и смотрел как раз в исходники Remix, которые порадовали своей простотой и комментариями, в отличие например от некста.

BY SuperOleg dev notes


Share with your friend now:
tgoop.com/super_oleg_dev/69

View MORE
Open in Telegram


Telegram News

Date: |

But a Telegram statement also said: "Any requests related to political censorship or limiting human rights such as the rights to free speech or assembly are not and will not be considered." When choosing the right name for your Telegram channel, use the language of your target audience. The name must sum up the essence of your channel in 1-3 words. If you’re planning to expand your Telegram audience, it makes sense to incorporate keywords into your name. Clear Channel login must contain 5-32 characters Administrators
from us


Telegram SuperOleg dev notes
FROM American