Как человек, написавший несколько проектов на react-query за последние полгода, опишу реальные проблемы это библиотеки. Первое это невозможность иметь несколько представлений для одних и тех же данных. Например мы отрисовали 2 списка в разных компонентах через хук и теперь нужно отсортировать список. Чтобы сортировка одного списка стриггерила сортировку другого нужно либо обновлять данные глобально:
queryClient.setQueryData(['projects'], newOrder);
и тогда мы имеем лишь одно представление для данных, что на больших проектах будет ограничивать
либо используем функцию сортировки в двух компонентах, но как-то костылями триггерим перерисовку второго. В Mobx же всё просто - сущности это observable, а разные представления сущностей - это computed. И computed'ов можем быть сколько угодно:
class ProjectStore {
projects = []
sortOrder = 'default'
get sortedProjects() {
return this.sortOrder === 'alphabetical'
? this.projects.slice().sort((a, b) => a.name.localeCompare(b.name))
: this.projects
}
Второе что react-query это всё-таки просто кеш. Он не даёт вообще никаких удобств для написания интерактивных приложений. Чтобы жить только на react-query приходится использовать React Context с хуками, а это перерисовка лишних компонентов на каждый чих + невозможность использовать эту бизнес-логику вне реакт компонентов. По моему опыту чем больше в проекте интерактива, тем сильнее код превращается в лапшу из хуков дёргающих друг друга. Поэтому для меня react-query - классно для неинтерактивных приложений где больше чтения чем записи, либо запись примитивная. А для сложной клиентской логики нужен стейт-менеджер.
Если у вас половина кода это ручной фетчинг данных через MobX, то можно было вынести это в библиотеку с кэшем и перестать перезапрашивать одно и то же. К тому же есть и библиотеки вроде mobx-persist-store, где можно в пару строчек сделать синхронизацию observable с sessionStorage / localStorage / IndexedDB. И наследование не обязательно:
class DashboardStore {
products = new RequestStore(api.users.get)
products = new RequestStore(api.products.get)
orders = new RequestStore(api.orders.get)
}
Один такой RequestStore тоже заменил бы вам половину проекта. Даже классы не обязательны:
С отдельными сторами можно загружать только нужные части приложения, например при переходе пользователя на конкретную страницу через динамический импорт. Представим сервис с сотней различных разделов. Пользователь заходит на одну страницу, а вместе с ней загружается глобальный стор целиком: весь код, логика, все зависимости. Даже если пользователь никогда не откроет 90% остальных разделов, лишний код уже в бандле.
Согласен, такое тоже бывает. Но тут сообщество может подхватить, так как весь код открыт. Например, пакет для автоматической генерации документации к API: https://github.com/trpc/trpc-openapi
Написано, что заброшен. У него есть несколько форков, один из которых я и использую. Хуже когда платный сервис, который использовался внутри вашей компании, перестаёт чинить баги по вашему запросу. Тут приходится вообще искать альтернативу и адаптировать код под новый сервис.
Хороший вопрос. Если исправление касается инструмента, который используется на работе и без этого фикса нельзя выполнить рабочую задачу - делаю в рабочее время. В готовой библиотеке уже написан почти весь код, остаётся поправить небольшую деталь. Работодателю это выгоднее, чем если бы разработчик писал решение с нуля. Многие разработчики просто делают локальный патч для себя без пулл реквеста, так быстрее. Но если решение уже найдено - оформить пулл реквест не занимает много времени.
Если же это проект для души, то тут уже вопрос приоритетов - как например с чтением книг, занятиями спортом или пет проектами. Главное чтобы было интересно, тогда время найдётся. Для меня Open Source отличается от работы - нет дедлайнов и больше свободы. Можно найти интересную задачу или отложить её на потом.
То есть простой try / catch теперь называется "Graceful Degradation / Fail‑safe вместо Fail‑Fast Crash"? Можно было просто показать как делать и как не делать. Сейчас объяснения примеров сделаны через AI и надуманы, статью было тяжело дочитать.
Разница между данным случаем и любого другого проекта на гитхабе (пусть даже телеграм) в том, что второе -- изначально было опенсорсом. Так и задумывалось авторами.
В статье написано что злоумышленник, имея исходники, может создать копию приложения и разместить в Play Market / AppStore. Аргумент несостоятелен - есть примеры фронтендов / клиентов которые публикуют исходный код клиентов в Open Source. Телеграм упоминался не в контексте готовности кода к публикации в Open Source, а в контексте сборки фишингового приложения из исходников.
Одно дело разобрать какой-то небольшой кусочек кода, метода, или даже файлика.
Злоумышленнику ничего не мешает отформатировать весь минифицированный код или использовать ИИ с гигантским контекстом вроде Gemini. Основной посыл статьи в том, что нужен security through obscurity. А в комментариях ответили про принцип Керкгоффса и что для хакера минификация это незначительная преграда. Более того, даже обфусцированный JS-код можно читать и понимать. На этом я своё обсуждение статьи закончу :)
Половина статьи это общение с поддержкой, а вот полноценного объяснения почему доступность фронтенд кода является утечкой нет.
Например у Телеграм веб весь фронтенд код доступен на GitHub. У них даже код мобильных приложений доступен. По вашей логике нужно создавать статью с кричащим заголовком об утечке? Ведь кто угодно может пересобрать и разместить.
Даже миницифированный фронтенд без сорс-мапов можно отформатировать, опционально скормить LLM и понять что происходит в коде. Поэтому есть специальные утилиты для обфускации фронтенд кода: https://obfuscator.io/
Интересно, всегда пишу на ES-модулях и даже не смотрю что импортировано и в каком порядке, автоматическим импортом занимается IDE. Звучит как "Недавно я столкнулся с проблемой: сотрудники в офисе ставили кружки в шкафу не по размеру ручки, и мне пришлось написать инструкцию по правильному размещению офисной посуды."
1) Тут же явное дублирование информации - ручная синхронизация totalItems и totalPrice и как следствие возможные баги. Если сделать totalItems / totalPrice селекторами (или computed в терминологии Mobx), то не нужно будет при добавлении / удалении из корзины вручную синхронизировать. Must have для сложных приложений, где содержимое корзины может поменяться из 5-10 разных мест.
2) Классно что благодаря Immer код стал более читабельный. Это позволяет писать
Другое дело, что на Mobx люди так пишут лет 8 уже. Может проще сразу на Mobx?
Redux идеален, если у вас сложное приложение с кучей состояний
3) Как раз таки в сложном большом приложении Redux создаёт проблемы. Представьте админку на 100 страниц. Централизованный стор означает, что код бизнес-логики для всех страниц инициализируется сразу. Из коробки нет возможности сделать ленивое создание сторов под страницы. Я бывал на проектах, где разработчики пытались изворачиваться и делали Redux стор с динамическими ключами, чтобы не держать 100 ключей в глобальном сторе. Работало это плохо, и были проблемы с типизацией. У модульных сторов этой проблемы нет.
То есть конкретно тут разница в размере незначительная. Попытка сэкономить на размере понятна, просто когда в проекте есть аналитика, библиотеки для графиков, анимаций, онлайн-чаты, скрипты для оплаты, то странно что возникает желание чуть-чуть сэкономить на стейт-менеджере, который является ядром приложения. Конечно если бы мне нужно было разрабатывать встраиваемый виджет или проект для страны с плохим интернетом и кнопочными телефонами, то тогда был бы смысл пересмотреть стейт-менеджер. Однако ещё больше смысла в этом случае - сменить реакт на исчезающий фреймворк вроде Solid (реакт весит ~43кб)
Мне нравится пример из мира шахмат: компьютерные программы постепенно побеждали лучших шахматистов мира. Но если взять в одну команду лучшего шахматиста и компьютер, то с таким тандемом справится или играть на равных практически не реально
Не понял аналогию. Компьютер давно играет сильнее любого шахматного чемпиона. Шахматы не потеряли популярность лишь потому что людям интереснее смотреть за людьми, видеть эмоции и их борьбу. Самые продвинутые движки в игре между собой могут делать настолько неочевидные для человека ходы, что обычному зрителю это неинтересно.
IT компаниям нужно развивать бизнес и код с программистами лишь один из способов это достичь. Если появляется ИИ, выполняющий такую же задачу быстрее и лучше, то зачем держать программиста? Никого не интересует его борьба с кодом и эмоции. Не утверждаю что всех программистов заменят, но аналогия с шахматами не совсем точная.
Любой опыт от большой компании полезен, неважно позитивный или негативный. Такие статьи хорошо отрезвляют после десятков других с примитивными примерами на todo-списках. Однако верно, что негативный опыт действительно может быть объяснён по-разному - либо не разобрались, либо действительно неудачный выбор. Тогда в ход должны идти аргументы и примеры. Например в статье есть "Задача на порядок подписок", которая хорошо иллюстрирует что понимать такой код тяжело, больше похоже на птичий язык, а не JavaScript.
Случаи когда большие компании публично отказываются от инструментов нередки, например в блоге Basecamp есть статьи о причинах ухода от облачных провайдеров вроде AWS и Google Cloud.
Если у вас вдруг используется Vite, то он в дев режиме для каждого модуля делает отдельный файл, соответственно HTTP запрос. Это нужно для HMR и увеличения скорости за счёт того что браузер нативно поддерживает модули. C ngrok это приводит к быстрому исчерпанию лимитов. Если у вас действительно в этом причина, то думаю можно отключить минификацию если запуск через Ngrok (например если проверять переменную окружения в конфиге): https://vitejs.dev/config/build-options#build-minify
В статье не описано, что ngrok даёт бесплатно 1 стабильный URL: https://docs.telegram-mini-apps.com/platform/getting-app-link#ngrok (c ограничением 20000 запросов в месяц)
Это важно, потому что при разработке вы не будете каждый раз генерировать новый URL и идти менять его в настройках BotFather
По всей видимости реальность очень прозаична. Чтобы предотвратить ошибку нужно было всего-то обновлять зависимости, так как статья написана в 2024-м, а решение на GitHub было влито в 2020-м: https://github.com/moment/moment/pull/4561
Думаю, что раз нашлись умники, которые стали ставить себя первыми в очереди, то найдутся и умники, которые через SQL-инъекции в коде получат доступ к БД и будут продолжать ставить себя на первое место. Автору рекомендую ознакомится с основами веб-безопасности раз в универе этому не учат. Статья как будто пятнадцатилетней давности - $_GET параметры передаются напрямую в запрос, MD5 пароли которые подбираются по радужным таблицам, вёрстка на clearfix'ах и смешивание слоёв логики и отображения.
Примечательно, что люди в общем случае радуются увеличению продолжительности жизни, при этом часто не считают себя счастливыми. Например согласно этому рейтингу уровень счастья в РФ 5.6/10. Есть только 12 стран, где рейтинг выше 7.
Может есть смысл думать над тем как наполнить счастьем те дни, что отведены вместо продлевания не самой счастливой жизни? Более того, увеличивается продолжительность жизни в престарелом возрасте, а это менее комфортное время чем молодость.
Базовая интеграция с redux-devtools есть в этом пакете. Правда в большинстве случаев хватает обычного логгера, который вместо [Proxy, Proxy] полноценно форматирует объекты. Такая функция в пакете выше тоже есть.
Как человек, написавший несколько проектов на react-query за последние полгода, опишу реальные проблемы это библиотеки. Первое это невозможность иметь несколько представлений для одних и тех же данных. Например мы отрисовали 2 списка в разных компонентах через хук и теперь нужно отсортировать список. Чтобы сортировка одного списка стриггерила сортировку другого нужно либо обновлять данные глобально:
и тогда мы имеем лишь одно представление для данных, что на больших проектах будет ограничивать
либо используем функцию сортировки в двух компонентах, но как-то костылями триггерим перерисовку второго. В Mobx же всё просто - сущности это observable, а разные представления сущностей - это computed. И computed'ов можем быть сколько угодно:
Второе что react-query это всё-таки просто кеш. Он не даёт вообще никаких удобств для написания интерактивных приложений. Чтобы жить только на react-query приходится использовать React Context с хуками, а это перерисовка лишних компонентов на каждый чих + невозможность использовать эту бизнес-логику вне реакт компонентов. По моему опыту чем больше в проекте интерактива, тем сильнее код превращается в лапшу из хуков дёргающих друг друга. Поэтому для меня react-query - классно для неинтерактивных приложений где больше чтения чем записи, либо запись примитивная. А для сложной клиентской логики нужен стейт-менеджер.
Если у вас половина кода это ручной фетчинг данных через MobX, то можно было вынести это в библиотеку с кэшем и перестать перезапрашивать одно и то же. К тому же есть и библиотеки вроде mobx-persist-store, где можно в пару строчек сделать синхронизацию observable с sessionStorage / localStorage / IndexedDB. И наследование не обязательно:
Один такой RequestStore тоже заменил бы вам половину проекта. Даже классы не обязательны:
Просто классы удобнее с TypeScript, так как не нужно описывать тип стора вручную. От этой проблемы страдает например Zustand: https://zustand.docs.pmnd.rs/guides/typescript
С отдельными сторами можно загружать только нужные части приложения, например при переходе пользователя на конкретную страницу через динамический импорт. Представим сервис с сотней различных разделов. Пользователь заходит на одну страницу, а вместе с ней загружается глобальный стор целиком: весь код, логика, все зависимости. Даже если пользователь никогда не откроет 90% остальных разделов, лишний код уже в бандле.
Согласен, такое тоже бывает. Но тут сообщество может подхватить, так как весь код открыт. Например, пакет для автоматической генерации документации к API: https://github.com/trpc/trpc-openapi
Написано, что заброшен. У него есть несколько форков, один из которых я и использую. Хуже когда платный сервис, который использовался внутри вашей компании, перестаёт чинить баги по вашему запросу. Тут приходится вообще искать альтернативу и адаптировать код под новый сервис.
Хороший вопрос. Если исправление касается инструмента, который используется на работе и без этого фикса нельзя выполнить рабочую задачу - делаю в рабочее время. В готовой библиотеке уже написан почти весь код, остаётся поправить небольшую деталь. Работодателю это выгоднее, чем если бы разработчик писал решение с нуля. Многие разработчики просто делают локальный патч для себя без пулл реквеста, так быстрее. Но если решение уже найдено - оформить пулл реквест не занимает много времени.
Если же это проект для души, то тут уже вопрос приоритетов - как например с чтением книг, занятиями спортом или пет проектами. Главное чтобы было интересно, тогда время найдётся. Для меня Open Source отличается от работы - нет дедлайнов и больше свободы. Можно найти интересную задачу или отложить её на потом.
То есть простой try / catch теперь называется "Graceful Degradation / Fail‑safe вместо Fail‑Fast Crash"? Можно было просто показать как делать и как не делать. Сейчас объяснения примеров сделаны через AI и надуманы, статью было тяжело дочитать.
В статье написано что злоумышленник, имея исходники, может создать копию приложения и разместить в Play Market / AppStore. Аргумент несостоятелен - есть примеры фронтендов / клиентов которые публикуют исходный код клиентов в Open Source. Телеграм упоминался не в контексте готовности кода к публикации в Open Source, а в контексте сборки фишингового приложения из исходников.
Злоумышленнику ничего не мешает отформатировать весь минифицированный код или использовать ИИ с гигантским контекстом вроде Gemini. Основной посыл статьи в том, что нужен security through obscurity. А в комментариях ответили про принцип Керкгоффса и что для хакера минификация это незначительная преграда. Более того, даже обфусцированный JS-код можно читать и понимать. На этом я своё обсуждение статьи закончу :)
Половина статьи это общение с поддержкой, а вот полноценного объяснения почему доступность фронтенд кода является утечкой нет.
Например у Телеграм веб весь фронтенд код доступен на GitHub. У них даже код мобильных приложений доступен. По вашей логике нужно создавать статью с кричащим заголовком об утечке? Ведь кто угодно может пересобрать и разместить.
Даже миницифированный фронтенд без сорс-мапов можно отформатировать, опционально скормить LLM и понять что происходит в коде. Поэтому есть специальные утилиты для обфускации фронтенд кода: https://obfuscator.io/
Не поверите, LLM и тут справляется превосходно: https://claude.ai/share/64f2498b-9a3f-48ce-a672-6f9f7b5aab6d
Интересно, всегда пишу на ES-модулях и даже не смотрю что импортировано и в каком порядке, автоматическим импортом занимается IDE. Звучит как "Недавно я столкнулся с проблемой: сотрудники в офисе ставили кружки в шкафу не по размеру ручки, и мне пришлось написать инструкцию по правильному размещению офисной посуды."
1) Тут же явное дублирование информации - ручная синхронизация totalItems и totalPrice и как следствие возможные баги. Если сделать totalItems / totalPrice селекторами (или computed в терминологии Mobx), то не нужно будет при добавлении / удалении из корзины вручную синхронизировать. Must have для сложных приложений, где содержимое корзины может поменяться из 5-10 разных мест.
2) Классно что благодаря Immer код стал более читабельный. Это позволяет писать
вместо
Другое дело, что на Mobx люди так пишут лет 8 уже. Может проще сразу на Mobx?
3) Как раз таки в сложном большом приложении Redux создаёт проблемы. Представьте админку на 100 страниц. Централизованный стор означает, что код бизнес-логики для всех страниц инициализируется сразу. Из коробки нет возможности сделать ленивое создание сторов под страницы. Я бывал на проектах, где разработчики пытались изворачиваться и делали Redux стор с динамическими ключами, чтобы не держать 100 ключей в глобальном сторе. Работало это плохо, и были проблемы с типизацией. У модульных сторов этой проблемы нет.
Mobx в gzip 17 + 2 = 19кб, не 30-40:
- https://bundlephobia.com/package/mobx@6.13.5
- https://bundlephobia.com/package/mobx-react-lite@4.0.7
Там же посмотрел Effector 11 + 3 = 14кб.
- https://bundlephobia.com/package/effector
- https://bundlephobia.com/package/effector-react
То есть конкретно тут разница в размере незначительная. Попытка сэкономить на размере понятна, просто когда в проекте есть аналитика, библиотеки для графиков, анимаций, онлайн-чаты, скрипты для оплаты, то странно что возникает желание чуть-чуть сэкономить на стейт-менеджере, который является ядром приложения. Конечно если бы мне нужно было разрабатывать встраиваемый виджет или проект для страны с плохим интернетом и кнопочными телефонами, то тогда был бы смысл пересмотреть стейт-менеджер. Однако ещё больше смысла в этом случае - сменить реакт на исчезающий фреймворк вроде Solid (реакт весит ~43кб)
Не понял аналогию. Компьютер давно играет сильнее любого шахматного чемпиона. Шахматы не потеряли популярность лишь потому что людям интереснее смотреть за людьми, видеть эмоции и их борьбу. Самые продвинутые движки в игре между собой могут делать настолько неочевидные для человека ходы, что обычному зрителю это неинтересно.
IT компаниям нужно развивать бизнес и код с программистами лишь один из способов это достичь. Если появляется ИИ, выполняющий такую же задачу быстрее и лучше, то зачем держать программиста? Никого не интересует его борьба с кодом и эмоции. Не утверждаю что всех программистов заменят, но аналогия с шахматами не совсем точная.
Как считали статистику, почему ей стоит доверять? Вот пример статистики от JetBrains: https://www.jetbrains.com/lp/devecosystem-2023/php/#php_frameworks
JetbBrains каждый год устраивают опросы разработчиков. Цифры там у Laravel / Yii / Symfony совсем другие.
Любой опыт от большой компании полезен, неважно позитивный или негативный. Такие статьи хорошо отрезвляют после десятков других с примитивными примерами на todo-списках. Однако верно, что негативный опыт действительно может быть объяснён по-разному - либо не разобрались, либо действительно неудачный выбор. Тогда в ход должны идти аргументы и примеры. Например в статье есть "Задача на порядок подписок", которая хорошо иллюстрирует что понимать такой код тяжело, больше похоже на птичий язык, а не JavaScript.
Случаи когда большие компании публично отказываются от инструментов нередки, например в блоге Basecamp есть статьи о причинах ухода от облачных провайдеров вроде AWS и Google Cloud.
Если у вас вдруг используется Vite, то он в дев режиме для каждого модуля делает отдельный файл, соответственно HTTP запрос. Это нужно для HMR и увеличения скорости за счёт того что браузер нативно поддерживает модули. C ngrok это приводит к быстрому исчерпанию лимитов. Если у вас действительно в этом причина, то думаю можно отключить минификацию если запуск через Ngrok (например если проверять переменную окружения в конфиге): https://vitejs.dev/config/build-options#build-minify
В статье не описано, что ngrok даёт бесплатно 1 стабильный URL: https://docs.telegram-mini-apps.com/platform/getting-app-link#ngrok (c ограничением 20000 запросов в месяц)
Это важно, потому что при разработке вы не будете каждый раз генерировать новый URL и идти менять его в настройках BotFather
По всей видимости реальность очень прозаична. Чтобы предотвратить ошибку нужно было всего-то обновлять зависимости, так как статья написана в 2024-м, а решение на GitHub было влито в 2020-м: https://github.com/moment/moment/pull/4561
Думаю, что раз нашлись умники, которые стали ставить себя первыми в очереди, то найдутся и умники, которые через SQL-инъекции в коде получат доступ к БД и будут продолжать ставить себя на первое место. Автору рекомендую ознакомится с основами веб-безопасности раз в универе этому не учат. Статья как будто пятнадцатилетней давности - $_GET параметры передаются напрямую в запрос, MD5 пароли которые подбираются по радужным таблицам, вёрстка на clearfix'ах и смешивание слоёв логики и отображения.
Примечательно, что люди в общем случае радуются увеличению продолжительности жизни, при этом часто не считают себя счастливыми. Например согласно этому рейтингу уровень счастья в РФ 5.6/10. Есть только 12 стран, где рейтинг выше 7.
Может есть смысл думать над тем как наполнить счастьем те дни, что отведены вместо продлевания не самой счастливой жизни? Более того, увеличивается продолжительность жизни в престарелом возрасте, а это менее комфортное время чем молодость.
Базовая интеграция с redux-devtools есть в этом пакете. Правда в большинстве случаев хватает обычного логгера, который вместо [Proxy, Proxy] полноценно форматирует объекты. Такая функция в пакете выше тоже есть.