🍪 Мы используем cookie-файлы, в том числе для аналитики и рекламы. Продолжая использовать сайт, вы соглашаетесь на обработку персональных данных. Подробнее — в политике конфиденциальности.
OK
Блог
Статьи

Колесо сансары в поиске решения бага «белый экран» в SPA приложении на React

Колесо сансары в поиске решения бага «белый экран» в SPA приложении на React
В этой статье расскажем, как мы решили проблему так называемого «белого экрана», вызванного «не определенным» методом в старых версиях webView (размонтирование всего дерева React) в SPA приложении на React, внутри мобильного приложения написанного на Flutter.
Наша статья на Хабре: https://habr.com/ru/articles/745416/
Всем привет! Меня зовут Иван Вахаев, я Frontend-разработчик digital-интегратора 5 УГЛОВ.

Мы специализируемся на продуктовой разработке и развитии сложных интерфейсных проектов, к которым относятся: кросс-платформенные мобильные приложения, e-com и маркетплейсы, корпоративные порталы и CRM на базе Битрикс24 и др.

В этой статье я расскажу, как мы решили проблему так называемого «белого экрана», вызванного «не определенным» методом в старых версиях webView (размонтирование всего дерева React) в SPA приложении на React, внутри мобильного приложения написанного на Flutter. В момент, когда пользователь переходил с экрана авторизации на экран регистрации или после успешной авторизации переходил на главную страницу, то юзера встречал «белый» экран. Данный баг поймали, к сожалению, не на стадии разработки и не на стадии тестирования, а когда приложение уже вышло в свет и попало на прилавки всеми известных магазинов приложений:( , но, как всегда, сроки были сжатыми, поэтому решение пришлось искать очень быстро.
Консоль ошибок при баге белого экрана в React-приложении
Расскажу, какие способы мы рассматривали и по какой причине выбрали итоговый (спойлер: пришлось написать собственный полифил).

Структура статьи, чтоб вам было поудобнее:

— В чем причина бага
— Какие варианты решения мы рассматривали
— Наш способ — полифил
— Итог.

Причина бага: использование метода at()

Причина была довольно интересной, всему виной был метод at(). Данный метод применяется как на строки, так и на массивы, принимает индекс и возвращает значение по этому индексу. Если мы внимательно обратимся к документации (массивы,строки), то увидим, что метод очень новый и поддерживается только обновленными версиями браузеров и версиями webView.
Конфигурация tsconfig.json для устранения ошибки библиотеки Sansari
Открыв VSCode, я сделал поиск по проекту, и НИЧЕГО не нашел По сути, все эти версии браузеров и версии webview выпущены в июле 2021 года и позднее. Данный метод во время написания кода (разработки) не использовался, поскольку в разработке внутри компании мы сразу используем «старые» методы.

Самое интересное, что 92 версия webView на Android была обновлена на 5+ версию самой операционной системы, т. е. они являются старыми устройствами, и если они обновлялись, то данной проблемы у них не наблюдалось. В связи с этим во время проведения тестирования эта проблема не была обнаружена, потому что тестировалось начиная с 8 версии Android, и на iOS была версия, которая уже получила эти обновления (15.4).

На вопрос: «А как вы узнали, что именно ЭТО послужило ошибкой, вы ведь ее как то нашли?», мы ответим — поскольку вопрос стоял не в приоритете, то список устройств, на которых приложение не работало, сначала узнали, к сожалению, у живых пользователей. Оказалось, что это в основном устройства с iOS.

По всем собранным комментариям мы поняли, что это версии начиная с 15.2 (15.3 в обращениях не было) и ниже.

Написав всему своему окружению, я нашел версию только 15.3. Попросил устройства на время и начал опыты.

Взял устройство, разрешил для Safari доступ к консоли и JS в настройках телефона. Подключив его к Mac, открыл devtools Safari данного устройства в консоли. Зашел в Safari на наш домен (т.к. версия webView что у Safari, что у приложения будет одинаковой и зависеть от OS) и, не успев увидеть даже загрузку, сразу понял, что ошибка воспроизвелась.

В девтулз Safari на MAC я вижу нашу виновницу. Сама по себе ошибка достаточно банальна, а именно — «Uncaught TypeError:.at() is not a function». Первым делом я подумал, что, возможно, это действительно есть в коде. Открыв VSCode, я сделал поиск по проекту, и НИЧЕГО не нашел.
Код полифилла, написанный для библиотеки колесо Сансары
Выводы простые — дело в билде. Открываю папку с билдом, ищу в ней, и нахожу то, что искал. К сожалению, скринов старых билдов не осталось, но единственную связь которую нашел — это лицензия MIT, и подумал что дело в какой‑то из библиотек.

Варианты решений, которые нам не подошли

Начнем с того, что нужно понять, что же можно делать с полученной информацией.

Итак, варианты решения:

  1. Tsconfig.json — это первое, о чем нужно и стоит подумать.
  2. Настройка сборщика.
  3. Узнать что за библиотека, а далее принять решение о замене или отказе.
  4. Библиотека с полифилами.
Стоит начать по порядку и рассказать, почему эти варианты не подошли.

  1. Tsconfig.json — самое верное решение — в первую очередь обратиться к нему, ведь в нем мы можем задать настройки для компиляции TS в JS. Зайдя в файл, обнаружил, что настройка стоит на ESnext, что как раз и приводит к тому, что наш метод не заменяется на что‑то более давно известное. Помним, что в нашем коде не было использовано данного метода, поэтому настройку «target» в этом файле трогать особого смысла нет. Пишем на всякий случай ES5 — все собирается, но в билде мы снова увидим наш неподдерживаемый метод. Поэтому стоит смотреть на настройку «lib» и «module», вижу, указан ESnext, ставлю ES6 — на выходе получаю кучу ошибок. Одна из них — это ошибка на динамический импорт, который мы используем для codesplitting‑a. А значит настройка нашего tsconfig нам уже не подходит.
Сравнение сборки до и после исправления бага библиотеки Sansari
2.Второй вариант — возможность дополнительно настроить сборщик. На тот момент это казалось очень разумной идей. Перебрав возможные плагины для webpack, я осознал, что это не поможет. Решил переехать на модный Vite+Rollup. В дальнейшем лишь смог ускорить время сборки, но основную проблему это не решило и дело было не в сборщике.
3.Поиск библиотеки занял большее количество времени, чем я думал. В этом проекте открыл для себя колесо сансары — комментируя одно, делал билд, снова встречал метод. Пройдя так по кругу несколько раз и не найдя проблему, ушел думать над следующим пунктом. (На момент написания статьи я нашел эту библиотеку, у нас установлена версия 6.2.2 и в документации указано что она поддерживает более поздние версии).
4.Тянуть целую библиотеку не было в наших интересах, ведь это дополнительный вес к приложению. А по ТЗ разрабатывали приложение, в котором учитывалась низкая скорость интернета.

Наш вариант и почему мы его выбрали

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

Консоль ошибок при баге белого экрана в React-приложении
Как мы видим, возвращается значение под данным индексом или же undefined. Нам этого достаточно для написания нашего полифила.

Итак, готовый код:

Консоль ошибок при баге белого экрана в React-приложении
В созданном файле я просто определяю метод. В данном случае нам обязательно нужно использовать function declaration, чтобы иметь возможность обращаться к this. Ведь здесь мы можем обратиться к свойствам нашего массива или строки. Как мы уже видели в документации, метод at(0) эквивалентен вызову элемента с индексом array[0].

Далее я лишь определил, что если не передается никакой аргумент при вызове, определить его как 0 (это следует из задачи), в дальнейшем нам просто нужно определить не выходит ли наш индекс за пределы нашего массива, а значит он должен всегда быть в диапазоне от 0 до array.length -1, как для положительных, так и для отрицательных значений индекса.

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

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

Данный файл c полифилом подключается в html до подключения основных скриптов самого приложения.

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

Могли сделать иначе

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

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

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