TGViewer
Валя читает ишью Валя читает ишью @valya_reads_issue · 3.01K subscribers
Post #308 5.16K
ReferenceError: a is not defined / Safari class fields implementation is buggy

Напомню, переделывая компиляцию в монорепозитории, мы взяли самый современный таргет компиляции — esnext.

Само собой, у нас есть пользователи, у которых браузеры старее. Особенно сафари, который обновляется только вместе с операционной системой.

В проектах, которые используют такие пакеты, мы просто транспайлим все нод-модули в скоупе @aviasales — это позволяет не париться на счёт обновления таргета тайпскрипта в монорепе и транспайлить через Babel только то, что нужно на основе текущего конфига Browserslist.

Задеплоив, мы увидели всплеск ошибок «a is not defined» в Rollbar’е в сафари с крайне непонятным стек-трейсом.

Ну, начали разбираться. Честно говоря, даже немного стыдно, т.к. проблема оказалось совсем нелепой, а для того, чтобы понять в чём дело понадобилось аж 3 разработчика…

Начали с поиска проблемного места.

Беда в том, что у нас регулярно возникают проблемы с сорсмапами в ролбаре — то они не заливаются, то не подхватываются в веб-интерфейсе. Из-за этого в ролбаре стектрейс частенько указывает на минифицированные файлы, в которых, как вы понимаете, бесполезно что-то искать: 3 строка и 58375 колонка, хех! А в дев-режиме проблема, естественно, не воспроизводилась.

Несмотря на кажущуюся бесмысленность, я всё таки попробовал поискать нужную колонку — никакой переменной «a» там и рядом не было.

Решили попробовать выкатить неминифицированный код, чтобы убедиться, что проблема именно в минифакторе, т.к. это самое большое отличие дев и прод режимов. Выкатили — проблема ушла. Обновляем terser (минифактор, который использует вебпак) — не помогает.

Решаем попытаться отловить проблему локально в прод режиме с включенными сорсмапами, и у одного из нас получается! Но при этом стектрейс абсолютно бесмысленный, указывает чёрт знает куда. А ещё проблема очень плавающая — появляется при первом визите без кеша и то не всегда. Загадка!

Ищем ишью в терсере, бабеле — ничего не находим. Настроение упадническое, т.к. пытаемся разобраться уже дня 4, пробуем переписывать какие-то странные места со смесью UMD, ESM и CommonJS — ничего не помогает.

Я набираюсь сил и отправляюсь на поиски злосчастной переменной «a». Прогоняю минифицированный файл через преттиер включаю в поиске Match Whole Word и нахожу 100+ переменных. Проверяю каждую из них: где объявляется и как используется. Смотрю раз, смотрю два, смотрю три и нахожу подозрительное место — незатранспайленный class field. Примерно в это же время мой напарник скидывает мне ишью Safari class fields implementation is buggy - ReferenceError: Can't find variable. Чудесно.

Проблема выглядит так:
import helper from './helper'

class C {
property = helper(() => {})
}


Т.е. если в class field есть вызов функции, объявленной за пределами класса, то всё взрывается, а стектрейс указывает на абсолютно другое место.

Но почему так в принципе получилось? А всё просто — я забыл добавить ту самую транспиляцию нод-модулей со скоупом @aviasales… Стыдно!

Но ещё более стыдно за сам процесс дебага и сколько времени он занял (напомню, 4 дня).

Ретроспективно становится очевидно, что процесс дебага должен был быть другим:
1. Действительно имело смысл попробовать найти место в коде на основе строки и столбца, хоть этот пункт и не увенчался успехом.
2. Вместо деплоя неминифированного кода, нужно было выключить mangle. Эта опция отвечает за переименование переменных: yourVeryLongVariable → a — и тогда в ошибке мы бы увидели оригинальную переменную и сразу было бы понятно, на какой участок кода смотреть.

Вот так вот просто, да! А ещё мы почему-то не посмотрели на статистику браузеров в Ролбаре — тогда стало бы очевидно, что в 16-ом сафари проблему починили, и именно по этому только у одного из нас проблема иногда воспроизводилась — у него был 15-ый сафари.

В общем, ещё раз стыдно! Вроде бы опытные ребята, а так затупили! В оправдание остается сказать, что это была первая рабочая неделя после новогодних праздников — видимо мозги не включились ещё :D
  • 👍 46
  • ❤ 16
  • 😢 4
More from @valya_reads_issue
  1. Aug 26, 2026Поддержка zip архивов в Node.js Внезапно, в Node.js 26.8.0 появился нативная поддержка для…
  2. Jun 12, 2026Diff: You should be able to just render any diff А пока гитхаб не вывозит как с точки зрен…
  3. Jun 12, 2026Diff: The uphill climb of making diff lines performant Пару лет назад я уже пинал GitHub з…
  4. May 6, 2026Vite выходит из Vitest В Vitest появилась крайне интересная дискуссия — а что если раздели…
  5. Mar 31, 2026Port of React Compiler to Rust Пока что WIP в виде альтернативного плагина для Babel и cra…
  6. Mar 11, 2026Evolving the Node.js Release Schedule Node.js давно загнала себя в странное состояние — чё…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →