Telegram Web
#статья дня

Можно ли заменить стейт-менеджеры — простым localStorage?

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

Давайте подумаем:

> Не всё должно быть постоянным. Допустим, у тебя открыто модальное окно. Перезагрузил страницу — и оно снова открыто, потому что значение сохранилось в localStorage. Абсурдный UX.

> Нет реактивности. Если просто читать из localStorage, React не узнает, что данные изменились, и не перерендерит компонент. Придётся вручную дёргать setState.

> Событие storage работает не так. Оно срабатывает только в других вкладках, а не в той, где ты вызвал localStorage.setItem(). То есть синхронизацию внутри приложения оно не решает.

> Ограничения. Только строки, лимит около 5 МБ, возможные ошибки при парсинге JSON, коллизии ключей. Всё это требует дополнительных костылей.

> SSR недоступен. На сервере localStorage просто не существует, и код падает с ошибкой.

localStorage и, частично, sessionStorage отлично подходят для мелочей:

> выбор темы,
> сохранение введённых данных формы,
> открытая вкладка меню,

Но как только речь заходит о данных, которые должны синхронно обновляться в разных компонентах и вызывать ререндер — нужен Context или полноценный state-менеджер.

Итак: localStorage — это удобное дополнение к Context/Redux/Zustand, но не замена. Он решает задачу «сохранить между сессиями», а не «синхронизировать состояние внутри React».

А если хотите подробностей — собственно, статья от Нади Макаревич: https://www.developerway.com/posts/local-storage-instead-of-context

Не думаю, что олды что-то найдут новое (разве что лишний раз поржать над событием storage), но у новичков вопросы такого плана возникают постоянно.

#react #localstorage
10🫡1
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

И #тред дня, и #статья дня... Сегодня всё и сразу от Джоша Комо.

И речь пойдёт о недооценённом хуке в React: useDeferredValue.

Итак, некоторое время назад Джош выпустил свой инструмент для создания красиво выглядящих теней (да-да, drop-shadow просто уже недостаточно). И одной из проблем инструмента стала... дёрганая реакция на движение ползунков. Как будто мало FPS.

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

Но что нам нужно? Нам ведь сначала нужен результат, а уже потом — код. Так почему бы не заполнить код чуть позже, не нагружая систему?

И именно для этого и нужен хук useDeferredValue. Данные молучим только когда основной процесс рендеринга завершится. Буквально ленивое выполнение.

Собственно, тред и статья если кто предпочитает подробности. Там, как всегда, шикарно.

Будьте разумно ленивыми, котаны!

#react #hook #бородач
21
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня

Вот мало было нам хороших статей по SVG, нужно больше!

Джош Комо продолжает свою серию про SVG. Начав со статьи про базовые принципы, пришло время объяснить, как работает механизм формирования кривых, контуров, aka path: https://www.joshwcomeau.com/svg/interactive-guide-to-paths/

Вы можете заметить, что у нас так-то уже огромное количество интерактивных обучающих ресурсов, начиная от чего-то похожего на ЛогоМиры, до более сложных инструментов.

Но Джош это Джош! Как всегда потрясающая любовь к деталям, интерактивные примеры и понятные объяснения по ходу.

Фишка его подхода в этот раз — пошаговый разбор алгоритма отрисовки кривых. Проигрывает его по кадрам, как будто вы очень медленный компьютер :)

Залипательно!

P. S. розыгрыш билета на конференцию от подлодки открыт до утра, если что.

#svg #path #tool
13👍3
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня

Ну чо, котаны, есть занятная история с GitHub.

Исследователь Шерон Бризинов решил проверить, что вообще происходит с коммитами, которые мы с вами удаляем через git reset и force push: https://trufflesecurity.com/blog/guest-post-how-i-scanned-all-of-github-s-oops-commits-for-leaked-secrets

Спойлер — никуда они не исчезают.

GitHub продолжает хранить все те ваши коммиты с ключами и секретами бесплатных и не очень API, даже если нам кажется, что мы всё подчистили.

Собственно, идея исследования простая: если коммиты не пропадают, значит, в них вполне могут оставаться секреты — ключи, токены и прочие радости.

Шерон пошёл и просканировал архив GitHub за несколько лет. Нашёл он там немало интересного, включая утечки, которые потом оценили на баг-баунти в 25 тысяч долларов.

Чтобы процесс не был ручным, он вместе с Truffle Security сделал инструмент Force Push Scanner.

Этот сканер вытаскивает пуши, достаёт зависшие коммиты и прогоняет их через TruffleHog, чтобы поймать секреты. Получился вполне практичный open source, которым можно пользоваться прямо сейчас.

Вывод в итоге грустный, но очевидный: удалить коммит — не значит избавиться от проблемы. GitHub всё хранит, и если секрет уже засветился, его надо менять, а не надеяться на «забывчивость» платформы.

Лучше, конечно, не допускать таких ошибок вовсе, но если уж случилось — придётся действовать радикально.

P. S. у этой статьи есть не менее занятная предыстория, которая дополняет общую картину: https://medium.com/@sharon.brizinov/how-i-made-64k-from-deleted-files-a-bug-bounty-story-c5bd3a6f5f9b

#github
1👍23🤩1
#фишка дня

Иногда встаёт задача не просто проиллюстрировать статью, но обрезать (кропнуть) исходное изображение. И желательно так, чтобы результат был адаптивен и адекватно реагировал на масштабирование.

Джейк Арчибальд предлагает решение на SVG и foreignObject: https://codepen.io/alinaki/pen/KKLXvwz

Вообще, весьма красиво. Да, можно генерировать кропы на сервере, но это, как минимум, лишние телодвижения. А тут – одна картинка, чистый и понятный код.

#svg #img #foreignObject #crop #бородач
15
#новость дня

Ой, а вчера-то Linux исполнилось 34 года. Хотите вы этого или нет, но плодами этих трудов вы все пользуетесь прямо или косвенно.

Лично я на Linux как на основной ОС сидел с 2006 года по 2018. Фотошоп и игры через WINE, а потом и Фотошоп стал не нужен с приходом Figma.

Ну почему перестал использовать, пожалуй, понятно 🍏

Ну что, ещё, как минимум, 34 года впереди?

Что на ваших машинах, котаны? В комментарии я скину пару скриншотов старых со своих.

#linux #birthday
👍15
#фишка дня

Сидишь такой и не вдупляешь, что происходит в пулл или мёрдж-реквесте?

GitHub и GitLab соответственно

Или, возможно, пытаешься вспомнить, а как ты вообще задачу решил? Надо же описание внести какое-то, а в голове туман...

Современный ответ: так проведи ревью от Copilot!

Но а) не везде он включён б) не везде разрешён к применению в PR/MR в) в GitLab вообще ничего нет.

Ничего страшного, на это есть решение!

Кто-то из олдов наверняка помнит, что вот этот раздельный вид в веб-интерфейсе с удалёнными и добавленными строками — штука сравнительно новая. Ещё во времена царя-гороха царило понятие diff- или patch-файлов. Вот ссылка на вики: https://en.wikipedia.org/wiki/Patch_(Unix)

Формат простой до безумия:
++++ добавлено
---- удалено


Я думаю, людям, прошивающим всякие там андроиды и ардуинки процесс хорошо известен: скачиваешь исходники библиотеки или конфига, скачиваешь patch-файл от анона с форума и накладываешь его командой, буквально, patch. Я так делал с Rockbox для iPod недавно, например.

Ладно, к чему этот экскурс вообще?

А к тому, что изменения из PR/MR легко можно получить в таком же виде! Все добавления и изменения в одном файле.

Просто берите ссылку на ваш реквест и добавьте к нему .patch. Вот так: https://patch-diff.githubusercontent.com/raw/edvardchen/eslint-plugin-i18next/pull/145.patch

А что делать потом? Cкормить это ChatGPT или Gemini или что там в вашей компании разрешено конечно же!

LLM-ки отлично справляются с разбором таких вещей! И на понятном языке и объяснят, что происходит, и найдут косяки, и напишут описание.

Вкусно? Не то слово! Пользуемся.

#git #patch #ai
👍273🤩2
#статья дня

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

И под капотом такой системы — полноценная big data-инфраструктура: события пишутся в логи, проходят обработку и попадают в key-value хранилище, откуда их читает рантайм показа рекламы. 

Причем система должна работать так надежно, чтобы каждое событие обработалось ровно один раз (exactly-once), и так быстро, чтобы уложиться в миллисекунды на весь цикл. 

Как этого добиться — рассказал в статье Руслан Савченко, разработчик динамических таблиц YTsaurus: https://habr.com/ru/companies/yandex/articles/939078/

Из интересного:

— События шардируются по хешу идентификатора. Это гарантирует, что все события одного пользователя обрабатываются одним воркером в рамках локальной транзакции.

— Дошли до низкоуровневой оптимизации аллокатора памяти и работы с ядром Linux, чтобы убрать провалы на высоких перцентилях.

— Вместо перезаписи всего protobuf-профиля система пишет бинарные дельты (через xdelta). Агрегатные колонки накладывают все накопившиеся дельты на оригинальный protobuf — получаем актуальную версию объекта

Все решения, на самом деле, можно применять не только к профилям. Прикольно, что в статье куча графиков — помогают разобраться. Советую почитать на досуге

#highload #db #database
👍54🫡3
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня

А нет такого, что новые технологии фронтенда нет смысла изучать, пока их не разжуют Шадид, Комо или Вес Бос? :)

Не, ну серьёзно. Вот читаешь ты блоги разработчиков Хрома или, простите, Вебкита. Что получаешь?

Получаешь нечто слишком рано, слишком мало, слишком сухо и сложно. Ну, буквально, посмотрите на статью про якорное позиционирование в блоге WebKit aka Safari: https://webkit.org/blog/17240/a-gentle-introduction-to-anchor-positioning/

A gentle introduction... куда уж более gentle: ни одного интерактивного примера, код минимален.

И тут давайте Шадида возьмём, буквально утром сегодня выпустил: https://ishadeed.com/article/anchor-positioning/

Уже начиная с шапки становится понятно о чём речь!

Каждый пример как всегда снабжён интерактивом, а если браузер не поддерживает пока якоря — всегда есть переключатель на видео.

Как всегда, глубокое почтение Шадиду за работу и рекомендация к прочтению! Якоря — уже не за горами, как минимум, можно заполифиллить.

#css #anchor
👍144🤩2👎1
Будни разработчика
#фишка дня Сидишь такой и не вдупляешь, что происходит в пулл или мёрдж-реквесте? GitHub и GitLab соответственно Или, возможно, пытаешься вспомнить, а как ты вообще задачу решил? Надо же описание внести какое-то, а в голове туман... Современный ответ:…
С полей сообщают, что добавление .diff к адресу пулл-реквеста делает то же самое, но в формате .diff, который чуть менее многословный, чем .patch!

А чем меньше символов — тем дешевле и быстрее обработка.

Вот бы всё можно было представить в таком виде...

P. S. На BitBucket тоже работает!
7
Media is too big
VIEW IN TELEGRAM
#заметка дня

Эпопея с пультом на Flutter продолжается! И в этот раз мне захотелось реализовать трансляцию фото (ну и видео) на телевизор.

Да, в 2025 году есть Chromecast, MirrorLink и AirPlay. Но хоть MirrorLink моим телевизором 2018 года выпуска и поддерживается, основной мой телефон — iPhone, а в AirPlay телевизор не умеет.

Да и задачи у этих троих чуть-чуть иные, нежели просто галерею фотографий посмотреть. Трансляция экрана это совсем не то же самое, что показать картинку или видео.

Потому на помощь нам приходит технология двадцатилетней давности, которая до сих пор поддерживается везде — DLNA!

В 2003 году тогдашние гиганты индустрии объединились и создали Digital Living Network Alliance, описав соответствующие стандарты и протоколы. В духе индустрии, использовались основанные на XML протоколы обмена данными и уже расмотренный когда-то мной SSDP.

Как это всё работает?

Когда мы сканируем сеть по SSDP, устройства сообщают в ответ поддерживаемые протоколы, схемы работы порты. И одна из таких схем работы — /MediaRenderer/AVTransport/Control.

Ну и мы отправляем телевизору запрос:

POST /MediaRenderer/AVTransport/Control HTTP/1.1
HOST: 192.168.1.42:1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<InstanceID>0</InstanceID>
<CurrentURI>http://192.168.1.10:8000/picture.jpg</CurrentURI>
<CurrentURIMetaData></CurrentURIMetaData>
</u:SetAVTransportURI>
</s:Body>
</s:Envelope>


В этот же момент роли меняются. Ваш компьютер или телефон становятся сервером, а телевизор — клиентом. Телевизор (или другой плеер) скачивает переданный в CurrentURI файл. Естественно, надо этот самый сервер у себя на телефоне или компьютере запустить!

А уже второй командой посылаем Play:

POST /MediaRenderer/AVTransport/Control HTTP/1.1
HOST: 192.168.1.42:1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#Play"

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:Play xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<InstanceID>0</InstanceID>
<Speed>1</Speed>
</u:Play>
</s:Body>
</s:Envelope>


И всё, всё работает. Главное, чтобы телевизор понимал, что ему передали. Заодно ещё метадату можно накинуть.

Да, в 2017 году альянс распустили, но DLNA работает буквально везде, где нужно. Просто называть стали по разному: Samsung AllShare, LG SmartShare, Sony Video/Music/Photo. А так, телевизоры, NAS-ы, куча приложений для всех платформ... Это очень простой, хоть и избыточный, протокол.

Да и реализовать это было весьма просто и интересно.

Кстати, можете сами попробовать побаловаться, есть минимальная имплементация DLNA с названием nano-dlna: https://github.com/gabrielmagno/nano-dlna

А большего и не надо.

#flutter #dart #dlna
120👍10🫡1
This media is not supported in your browser
VIEW IN TELEGRAM
#такое дня

Когда вам в очередной раз станет стыдно, что вы сделали какой-то костыль, вспомните, что бегущую строку в CSS ещё совсем недавно нельзя было сделать без дублирования элементов: https://www.tgoop.com/htmlshit/3721

А если и это не помогает, вспомните, что где-то там есть компания Apple, которая не осилила сделать «бесконечный» (или хотя бы автовозвратный) список часов и минут в будильнике, поэтому продублировала 0-23 на часах (0-12 в AM/PM) и 0-59 на минутах много-много раз. Очень. Много. Раз.

Кого-то, впрочем, это только больше расстроит. Ведь и платят им больше.

#apple #ios #бред
🤩147🫡4
#заметка дня

На связи glebcha, который иногда с большим удовольствием предлагает идеи новых статей автору канала (старому другу) и, с недавнего времени, пишет сам в канал.

Недавно появилась интересная задача - отображать список вкладок редактора вне области скролла как в любом редакторе кода, например в IDEA.

Сразу же составил список технологий себе в помощь и в их списке оказалось событие scrollend для более эффективного формирования списка вкладок вне области прокрутки.

И вроде бы все отлично, но как обычно "есть один нюанс"....и это Safari. Ссылка на активный баг.

Но не стоит расстраиваться, решение нашлось в виде полифилла (не идеального, но отличного).

Проверяйте доступности браузерного api перед использованием и помните - "нет нереализуемых задач, всё лишь вопрос мотивации и времени".

#safari #scroll #scrollend
👍12
Media is too big
VIEW IN TELEGRAM
#фишка дня

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

Итак, выделяете какой-то элемент на вкладке Elements, потом идёте в консоль — и этот элемент становится доступен под алиасом $0!

Более того, в $0-$4 по порядку хранится история этих выделений! А в $_ — последнее вычисленное в консоли выражение.

Есть ещё $(selector) — это шортхенд для querySelector, косящий под jQuery.

А есть $$ — это querySelectorAll...

В общем, вот документация: https://developer.chrome.com/docs/devtools/console/utilities

Из очень удобных штук — шортхенд keys() для получения ключей объекта. И monitorEvents() — чтобы узнать обо всех слушателях переданного события без ковыряния в UI.

Да, документации и фишкам сто лет в обед, но я как-то туда не особо заглядывал. А стоило бы!

И да, для чистоты эксперимента: в Firefox тоже есть подобное, но сильно поменьше: https://firefox-source-docs.mozilla.org/devtools-user/web_console/helpers/index.html

$0 там есть, а $1 уже нет. keys() есть, а monitor() — нет. В общем, сойдёт.

#chrome #devtools
1👍272🤩2
Media is too big
VIEW IN TELEGRAM
#инструмент дня

Чем вы тестируете проекты и продукты? Наверняка, большинство из вас пишут или собираются писать веб-приложения и E2E-тестирование построено на Playwright.

Если вы в компании постарее, там может быть Cypress, Selenium, WebDriverIO... Да их десятки.

Если вы как и я в Финляндии, возможно, ещё и Robot Framework.

Я, честно скажу, умею работать только с Playwright и немного с Robot Framework (ну вот были у нас воршкопы, что делать). Что как бы очевидно для веб-разработчика, JS он и в Африке JS.

Но понадобилось мне тут прикинуть, а что делать, когда вы пишете проект на React Native или Flutter под 2-3 платформы, включая веб, или вообще — пишете нативно под мобилы? Чем тестировать-то?

Даже мой пульт уже чуток больше, чем пара кнопок.

И тут я открыл для себя Maestro. Сравнительно новый (с 2022) года тулкит. Поддерживает все основные платформы: Android, iOS, Web Views и браузеры, React Native, Flutter.

Как видно на видео, все действия описываются в YAML! Очень лаконично и понятно, ты не тонешь в бесконечных await, не зарываешься в fixtures. Тестовая среда понимает, что всё, что происходит на экране, подвержено флейку, что способы взаимодействия пользователя с приложением различаются от устройства к устройству, что у платформ есть свои нюансы работы.

И всё это в опенсорс и прекрасно запускается локально!

А в дополнение к этому они ещё и свою IDE для тестировщиков пишут. Инфраструктура разрастается и это прекрасно.

Кажется, для кроссплатформенного E2E тестирования на данный момент ничего более интересного нет.

#testing #maestro #ios #android
22👍6👎3🤩3
This media is not supported in your browser
VIEW IN TELEGRAM
#codepen дня

Кому в детстве нравилось крутить в руках всякие цепочки и кисточки для велосипедов?

Сегодня ваш шанс вспомнить то самое чувство!

Очередной прекрасный пример анимации по скроллу от Stijn Van Minnebruggen (я хз как произнести, это что-то из Евротура)

Тут: https://codepen.io/donotfold/pen/ZYYYJRV

Работает в Chrome и Safari TP.

Кто переведёт на GSAP? Он, кстати, недавно официально бесплатным стал, даже для коммерческого использования.

#css #scroll #animation #бородач
5🤩2
#игра дня

Ну что, JavaScript никто из вас не знает, мы это выяснили не так давно. А что насчёт валидации адресов электропочты?

Вашему вниманию очередной квиз: https://e-mail.wtf/

Вооружайтесь RFC 3522 и вперёд!

Inb4: проверка на собачку и валидация письмом — единственный рабочий способ.

У меня — 13 / 21 🫠

#email #quiz
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84🤩1
#новость дня

Как вам такое: взломать npm, получить доступ к пулу пакетов, которые скачивают по два миллиарда раз в неделю и всё ради чего? Ради призрачного шанса попасть в UI какой-нибудь крипто или NFT-биржи и украсть эфирчик-другой.

Звучит как плохая серия сериала Скорпион? А нет, это вот буквально вчера случилось. Да-да, я опоздал с новостью.

Итак, некто с помощью фишингового письма с требованием обновить 2FA-токены умудрился обмануть ментейнера нескольких пакетов для работы с командной строкой (chalk, например, чтобы эту самую строку красить. Очень полезно.) Джоша Джунона.

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

В выпущенные атакующими обновления пакетов был подставлен вредоносный код, выполняемый на системах пользователей, работающих с сайтами или приложениями, использующими скомпрометированные версии пакетов. Вредоносная вставка для браузеров осуществляла перехват трафика и активности Web API, прикрепляя свои обработчики к функциям fetch и XMLHttpRequest, а также вмешивалась в работу типовых интерфейсов криптокошельков для скрытой подмены реквизитов получателя при переводе. Подмена осуществлялась на уровне модификации значений в запросах и ответах, незаметно для пользователя (в интерфейсе пользователя показывались корректные реквизиты). Поддерживались форматы транзакций Ethereum, Bitcoin, Solana, Tron, Litecoin и Bitcoin Cash.

В общем, технические подробности и список пакетов есть тут: https://www.aikido.dev/blog/npm-debug-and-chalk-packages-compromised

Очень рекомендую проверить установленные версии даже если вы не держите у себя на сайтах кошельки и биржи. А если держите — тем более.

И вообще, котаны, проверяйте, откуда письма и их смысл. Вы прочитайте письмо с иллюстрации — ну курам на смех.

Впрочем, такое письмо может кого угодно застать врасплох, да.

#npm #security
9🫡5🤬3🤡3
Проект от подписчика!

Напоминаю, что я без проблем выкачу любую статью и любой проект от вас, не стесняйтесь писать.

Презентация? Выступили на митапе? Создали свой канал и хотите поделиться интересной статьёй — добро пожаловать!
👍101
Привет! Меня зовут Дастан, я фуллстак разработчик с 3.5 годами опыта работы и я делаю проект в соло.

Я делаю проект Hack Frontend - платформа для подготовки к собесам для фронтов.

Как это мне в голову пришло:
Осенью 2024 года, я помогал родной сестренке с поиском работы на позицию фронта. И вот тогда я столкнулся с небольшой проблемой:
При подготовке к собесам, нужно постоянно переходить из одного ресурса в другой, тратя на это кучу времени. По теории ты ищешь инфу а одном месте, по тех части(решение задач) в других. В СНГ пространстве не было единой платформы куда можно зайти и выйти уже оттуда полностью подготовленным к собесу.

Так вот, я понял что нужно как то решать эту проблему и принял решение разработать такую платформу.

На первое МВП по времени ушло примерно 20 дней. Использовал такой стек технологий:
Next, prisma, postgresql.
При разработке делал очень сильный упор на SEO оптимизацию.

После того как я разработал первое МВП, 26 января я задеплоил его и начал делиться им своим друзьям, знакомым, по разным чатикам в тг, в линкедин. Примерно за пару дней я набрал 100+ пользователей, и тут я понял, что нужно его развивать.

На текущий момент статистика такая:
- ежедневное посещение ~500-700 людей в день
- 1200+ зареганных пользователей
- 50-100 кликов в поисковиках

Ни разу не делал платной рекламы, только органический рост.

https://www.hackfrontend.com
4👍3414👎1🫡1
2025/10/22 02:35:27
Back to Top
HTML Embed Code: