Фронтендеры
Выскажу тезис в отношении фронтендеров. Может, он не самый приятный, но неплохо упрощает дело. Тезис следующий: фронтендер мыслит npm-пакетами. В мире фронтендера любая задача, любая проблема решаются одним способом — пакетом из npm.
У тезиса несколько следствий. Во-первых, когда есть несколько способов решить задачу, фронтендер выбирает тот, для которого есть npm-пакет. При этом не важно, насколько способ оптимален и удобен другим участникам, например бекенду или пользователями. Есть пакет — дело в шляпе.
Во-вторых, если нужного пакета нет, берется максимально близкий к нему и задача подгоняется так, чтобы ему удовлетворять.
Стоит только принять тезис и следствия, как многое становится очевидным. Например, нелепые решения, особенности передачи данных, требования коллег.
Доказательств этому я повидал много, вот хотя бы одно.
Есть SPA-приложение для сотрудников. По нажатию кнопки нужно скачать с бекенда CSV-файл. Как его передать, если на сервере только REST и JSON? Как скачать файл, чтобы он не открылся в текущей вкладке?
Фронтендер загуглил “javascript csv on client” и нашел npm-пакет. Он принимает массив словарей, записывает их в CSV-строку и заставляет браузер ее “скачать”, то есть сохранить на диск. Бекендер пожал плечами, мол как скажешь — и отдал на фронт список мап. Это не его дело, фронтендер так попросил, пусть и разбирается.
Все это работало, пока строчек было сто-двести. Но однажды мне велели сделать выгрузку на двести тысяч записей. Я сделал по образцу, и тут-то браузер накрылся. Вкладка окирпичивается, ничего не работает.
Далее, я был единственным, кто задался вопросом: что делают люди с этим файлом? Оказалось, открывают в Экселе. Как я уже рассказывал, открывать CSV в Экселе — это играть в русскую рулетку. Эксель вечно путает разделитель полей — запятую или точку с запятой — и даже больше: эта опция зависит от локали. Поэтому открывая файл, половина людей видели слипшиеся поля и матерились.
У Экселя есть костыль: если в первой строке CSV написать sep=;, то будет
использоваться именно этот разделитель. Но оказалось, npm-пакет ничего про это
не знает. Нужно контрибьютить и пинать автора, чтобы принял изменение и выкатил
версию.
Наконец, я спросил прямо: если пользователи открывают файл в Экселе, уж наверное им нужен файл xlsx, а не CSV? Так-то да, но пакета в npm, чтобы собрать эксельку на клиенте, нет, поэтому пролетаем.
В итоге я сделал вот что. На бекенде пишу нормальный Эксель-файл. Кладу его в S3 и получаю подписанный урл, который действует 15 минут. В HTTP-ответ отдаю джейсончик с этим урлом:
{"url": "https://acme.amazonaws.com/path/to/file.xlsx?...", "expires_at": "..."}
На клиенте: получаю джейсончик, достаю урл. Потом:
- создаю невидимый элемент
<a href="...">с этим урлом - добавляю этот элемент в тело так, что его не видно
- имитирую клик по нему методом
.click()
В результате файл загружается автоматом. Ну или может появиться окно с вопросом, что делать с файлом.
Тот npm-пакет я к черту выбросил, потому что он банально не нужен.
Как я и говорил, все упирается в тезис из начала заметки. Фронтендер не понимает проблему, которую решает. Он не понимает в целом как обмениваться данными, как делать удобно другим — коллегам, пользователям. Он мыслит npm-пакетами и подгоняет условия задачи под те пакеты, которые нагуглил.
Я, кстати, вообще считаю, что фронтенд — это не программирование. Современный фронтендер занят тем, что передает результат из пакета А в пакет Б. Это не хорошо и не плохо, это просто факт. Примерно как сборка изделия из готовых частей.
Знание этого принципа, на мой взгляд, полезно в следующем. Выбирая решение,
нужно проверить, что у фронта есть для него пакет. Нужно следить, чтобы коллеги
выбрали максимально адекватный их них. Такой, чтобы не повесил браузер, не
скачал 100 зависимостей вроде is_number, leftpad и так далее.
Короче, следить за ними, как за перспективными детьми, которые в любой момент могут попасть в дурную компанию.
Ну и порой подсказать фронтендерам, что задача решается не пакетом, а пятью строчками на чистом js. Часто они этого не знают.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter