Будни разработчика
14.6K subscribers
1.14K photos
319 videos
7 files
1.96K links
Блог Lead JS-разработчика из Хельсинки
Автор: @bekharsky

По рекламе: https://telega.in/channels/htmlshit/card?r=GLOiHluU или https://t.me/it_adv

Чат: https://t.me/htmlshitchat

№5001017849, https://www.gosuslugi.ru/snet/679b74f8dad2d930d2eaa978
Download Telegram
#ссылка дня

Чем отличается alt от title? А border от outline? А *.d.ts от *.ts? А for..in от for..of? А display: none от visibility: hidden? А slice от splice?

Как же я задолбался форматирование применять.

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

И тут нам поможет проект https://thisthat.dev/. Он буквально проходится по таким скользким определениям или сущностям и разбирает каждый из них.

Проект открытый, предлагайте ваши == и ===.

#javascript #html #css #this
#инструмент дня

Миграции с JavaScript на TypeScript часто заходят не туда. Или не заканчиваются. Или откатываются. Зачастую в лучшем случае весь новый код начинает писаться на TypeScript и всё на этом.

Да, ещё не факт, что оно вам надо вообще, но это тема иной беседы.

Итак, с чего же начать вашу миграцию если автоматизированные средства, расставляющие везде any, вам не подходят, а //@ts-nocheck — для быдла?

Начните с модулей с наибольшим числом зависимостей, говорит нам Matt Pocock, а он в общем-то в курсе, о чём утверждает, он учит людей тайпскрипту фулл-тайм :)

А как найти эти самые модули? Очень просто, возьмите построитель диаграмм зависимостей. Madge вполне подойдёт: https://github.com/pahen/madge

Ну и никто не мешает весь новый код писать сразу на TS.

#typescript #javascript #ts #js #diagram #deps
#драма дня

Итак, сообщество опять бомбит. Вот вы спите, а там происходит ого-го какая драма!

Короче, TL;DR: Создатель Ruby on Rails, Давид Хейнемейер Ханссон (David Heinemeier Hansson) заявил, что TypeScript не нужен.

Подробнее: https://world.hey.com/dhh/turbo-8-is-dropping-typescript-70165c01

Суть ситуации в том, что (в основном в мире RoR) есть фреймворк Turbo. По факту, он успешно конкурирует с Astro, HTMX и прочими React Server Components и просит ещё. Бесшовная интеграция фронтенда с бакендом через передачу HTML различными способами: https://turbo.hotwired.dev/

Идея не нова, что-то похожее есть и в Drupal, и в October CMS, можно повторить и в Laravel и так далее.

Так вот Turbo до 7 версии включительно был написан на TypeScript, а сейчас Давид психанул. Из его сообщения можно сделать вывод, что ООП (а Turbo пишется в ООП-стиле) в современном JS вполне себе развилось до состояния, в котором с ним можно работать.

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

Сообщество бурлит, ссылается на State of JS 2023, мол, 70% разработчиков использует TS. Проблема только в том, что не 70% разработчиков, а 70% поучаствовавших в опросе.

К слову, ситуация не нова. React как был на JS написан, так и остаётся. Правда, без громких заявлений.

Upd. там фейсбучный Flow, про который я забыл совсем. И определения TS-типов поставляются в отдельном пакете.

Ну и ещё лично я замечал, когда мне надо поэкспериментировать, я точно не выберу TS: в экспериментах типобезопасность это последнее, что меня волнует, а в рантайме тебя TS не особо спасает от дурацких решений (inb4 гигиена, тайпгарды и и контракты).

Интересно, скоро ли появится turbo.d.ts в пакете types? По-моему, Давид и определения поставлять не собирается. Что-то это уже ну такое 🙂

А как ваши дела с TS, котаны?

P. S. мне тут напомнили, что самая мякотка-то происходит в обсуждении PR с удалением TS: https://github.com/hotwired/turbo/pull/971

Там просто полыхают костры из ягодиц.

#typescript #javascript #ruby
#ссылка дня

Чем отличается alt от title? А border от outline? А *.d.ts от *.ts? А for..in от for..of? А display: none от visibility: hidden? А slice от splice?

Как же я задолбался форматирование применять.

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

И тут нам поможет проект https://thisthat.dev/. Он буквально проходится по таким скользким определениям или сущностям и разбирает каждый из них.

Проект открытый, предлагайте ваши == и ===.

#javascript #html #css #this #бородач
#статья дня

Давно не было интерактивных статей от кого-то, кроме Шадида и Комо :)

Время исправлять.

Сегодня — статья про концепцию и варианты реализации Drag&Drop-интерфейсов от Амита Пателя и Red Blob Games: https://www.redblobgames.com/making-of/draggable/

Давайте сразу: Red Blob Games это не компания, это сайт, собственно, Амита, где он объясняет используемые в играх и интерфейсах концепции: от поиска пути и генерации шестиугольной карты, до простейшего ИИ для игр.

Так вот, возвращаясь к статье: рассмотрены варианты реализации на мыши, тач-девайсах, скроллинг и различные сопутствующие проблемы (ну чтобы вам не пришлось разбираться, как, например, отключить выделение текста, пока тащишь элемент).

Прекрасная статья и проект вообще, моя горячая рекомендация.

#javascript #games #drag #drop
#фишка дня

Что, котан, поймал ошибку CORS aka Cross-origin resource sharing error? В переводе на русский — ошибка совместного использования ресурсов между разными источниками.

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

В Википедии очень простое и понятное объяснение, что это такое. А нам же с тобой нужно как-то эту проблему обойти, пусть и временно.

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

Кстати, именно поэтому первым решением проблемы с CORS могут быть специальные прокси: https://nordicapis.com/10-free-to-use-cors-proxies/

Если хотите, я подробнее потом о них расскажу. И о CORS тоже.

Но что делать если использование прокси не представляется возможным?

Всё просто, открываем Chrome DevTools и меняем заголовок Access-Control-Allow-Origin на *, нажав на карандашик рядом.

Естественно, таким образом можно менять и добавлять любые заголовки.

А ещё можно создать файлик с заранее прописанными заголовками — .headers — и включить его как правило через Add overrrde rule в Sources 👉 Overrides.

Всем безоблачной разработки, котаны!

#javascript #network #cors
#заметка дня

Иногда полезно спорить с мэтрами по поводу разных штук. Не стоит всё подряд принимать на веру.

Вот, например, Кори Хаус, весьма известный консультант по React, предложил буквально следующее: чтобы не запутаться в бесконечных хуках useEffect в React, вместо неименованной функции передавайте именованную.

То бишь, вместо:

useEffect(() => {
// do stuff
}, [...deps]);


Предлагается
useEffect(function doSomething() {
// do stuff
}, [...deps]);

На первый взгляд выглядит разумно, не правда ли?

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

Так вот, товарищи. Это далеко не самое лучшее решение, да ещё и многословное. Гораздо более разумно будет создать свой собственный хук.

Что такое свой собственный хук? Вы не поверите, это буквально тот же самый useEffect, но вынесенный в функцию:
function useDoSomething(deps) {
useEffect(() => {
// some effect
}, [...deps]);
}


Да, внутри функции кастомного хука можно держать useState, обращаться к внешним источникам данных и возвращать что угодно. Это, например, рекомендуемый способ использования того же React Query и официальная рекомендация команды React для переиспользования логики: https://react.dev/learn/reusing-logic-with-custom-hooks

Почему такой подход лучше?

Потому что, обладая всеми преимуществами варианта, предложенного Кори, он не только сокращает размер основного компонента но и легко тестируется!

Да, представьте себе, вы задолбаетесь правильно тестировать компонент с даже двумя-тремя встроенными хуками. А вынесенные отдельно — не только легко мокаются и подменяются, но и прекрасно тестируются сами по себе.

Так что команда React могла бы назвать раздел документации не "как переиспользовать", а "как тестировать". Это важнее.

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

#react #javascript #hooks
#фишка дня

Как получить последний элемент массива?

Можно посчитать длину массива минус один, чтобы получить нужный индекс.

Можно сделать array.slice(-1) и взять нулевой элемент получившегося массива.

А можно воспользоваться сравнительно новым методом Array.prototype.at! Ну, уже два года как в продакшене. И полифилл давно есть.

Весьма удобно, я считаю.

#javascript #array
This media is not supported in your browser
VIEW IN TELEGRAM
#библиотека дня

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

Компания Evil Martians и Андрей Ситник конкретно известны своим скурпулёзным подходом к интерфейсам и их оптимизации. Если кто-то ещё не в курсе существования их блога, настоятельно рекомендую: https://evilmartians.com/chronicles

Ну конкретно по теме канала — тег Frontend, конечно же.

Так вот, одной из их достаточно новых специализаций является разработка интерфейсов профессиональных утилит, в том числе для десктопа. Например, UI для HTTPie.

А без чего нельзя представить себе профессиональное приложение? Правильно, без хоткеев. Да и вообще нынче доступность без хоткеев — не доступность вовсе.

И вот Андрей Ситник на днях выкатил обновление своей библиотеки KeyUX: https://github.com/ai/keyux

Пример её работы на видео. А что умеет?

1. Добавлять горячие клавиши по aria-keyshortcuts
2. Возвращает на место :active у кнопок при использовании клавиатуры
3. Превращает списки в навигационные элементы
4. Правильно отрабатывает стрелки, табуляцию и Esc.
5. Показывает подсказки если нужно.

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

#javascript #a11y #hotkeys
#ссылка дня

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

Погоди, в смысле, никто? Вот же, целый репозиторий: https://github.com/ufocoder/javascript.memory-leaks

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

Не позволяйте памяти утечь, котаны! И дополняйте примеры :)

#javascript #memory
#новость дня

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

Итак, какой-то никакой-то React 19 Beta!

Вокруг этого релиза было слишком много разговоров. И причина проста: React Compiler.

TL;DR: React Compiler это особый инструмент сборки кода на React, автоматически мемоизирующий нужные данные в нужный момент. Никаких больше раздражающих useCallback, useMemo и memo не требовалось бы.

Собственно, блог разработчиков: https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024

И нет, этого в релизе React 19 не будет. Почему-то все кругом решили наоборот.

А что будет? Да много всего: https://react.dev/blog/2024/04/25/react-19

Наборы хуков и API для Suspense это нечто потрясающее. Я крайне рекомендую посмотреть хотя бы на use и useOptimistic. С такими нововведениями, можно даже думать об отказе от React Query.

И давайте пройдёмся по руководству к обновлению:

0. react-test-renderer объявлен устаревшим! Теперь официально: используйте React Testing Library.
1. ref как проперти. Дождались!
2. Возможность обрабатывать ошибки разных категорий: пойманные ErrorBoundary и пропущенные им же.
3. Наконец-то удалены propTypes и defaultProps. Висели с 2017 года как Deprecated.
4. Удалён ReactDOM.render. Вот тут мне стало больно, но я выживу: я абьюзил эту штуку чтобы рендерить реакт-виджеты в легаси-части кода.
5. Удалён ReactDOM.findDOMNode (кому-то тоже будет больно, да)
6. Сборок UMD больше нет. Если вам очень нужно работать без сборки прямо в браузере — используйте сервисы вроде esm.sh. На канале был пост об этом сервисе.

В общем, изменений достаточно. Но сначала надо обновиться до 18.3.0 хотя бы 🙂

#react #javascript
Media is too big
VIEW IN TELEGRAM
#фишка дня

Когда я наткнулся на этот твит в обсуждении утилиты работы с цветами Андрея Ситника, я не сразу примерил его на себя. Но, как оказалось, стоило бы.

Итак, давайте поясню для тех, кто по ссылкам не ходит.

В азиатских иероглифических языках почти весь ввод с клавиатуры происходит в аккордном режиме или же в режиме т. н. композитинга, общее название — Input Method Editor.

TL;DR: На экране всплывает окошко с символами или их группами и пользователь может что-то выбрать.

На каких-то ОС оно вызывается долгим зажатием клавиши, где-то — по хоткею, а где-то — автоматически и сразу.

Так вот, одно дело азиатские языки (я очень рекомендую посмотреть сам твит), а другое — разные европейские. И речь о диакритических знаках: умляуты, акуты, ударения, птички и шапочки.

Так вот, я не имею финской раскладки, потому буквы ä, å и ö ввожу как раз в режиме композитинга, долгим зажатием «материнской» клавиши.

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

Кстати, выбор Emoji из всплывающего окошка — туда же.

В JavaScript-событиях для этого режима имеется флаг isComposing. Поэтому если вы, как и я в примере на видео, решили реализовать ввод групп символов подобным образом — циклически перебирая поля ввода — стоит об этом подумать :)

Собственно, давайте и пример: https://codepen.io/alinaki/pen/MWMpdvO?editors=1010

И напишите в комментариях, как вы решаете проблему редкого ввода букв с диакритикой у себя в системе. Например, я не помню, как это происходит в Windows, а в Linux я использую клавишу Compose, она работает чуть иначе.

#javascript #composing #event
How Google handles JavaScript throughout the indexing process

Интересная статья от Vercel про то, как работает краулер сайтов гугла. Эта тема окружена кучей мифов разной степени зрелости. Когда то говорили, что краулер не умеет запускать JS, затем говорили что научился, но не дольше 5 секунд и на старой версии хрома. Ребята из Vercel решили поэкспериментировать с отдачей контента и выяснили интересные особенности работы гугл краулера

Самое важное, что можно выделить: краулер умеет работать с современным синтаксисом JS, а также отлично индексирует сайты, сделанные с применением серверных компонентов (и соответственно стриминга хтмл контента).

В целом в исследовании также много других интересных пунктов (как например тот факт, что индексируются только страницы с 3хх и 2хх кодами. Т.е. если вам необходимо отрендерить экран с ошибкой - лучше его отрендерить на отдельном урле или с помощью 4хх или 5хх кода хттп).

Рекомендую к прочтению, если вы работаете с SEO



https://vercel.com/blog/how-google-handles-javascript-throughout-the-indexing-process

#development #javascript #SEO
#фишка дня

Автор твита с картинкой выше буквально написал: «It's official. I don't understand URL.canParse 🫠»

Ну, давайте разбираться, что же тут не так. Или всё так?

И надо ли это вообще понимать?

Для начала, подумаем, зачем нам может понадобиться URL.canParse. А нужно это для случаев, когда отбросить токенизацию aka URL.parse и выполнение запроса дешевле и быстрее, чем упасть в ошибку или городить try-catch. Например, в работе с микросервисами, с БД.

Если внимательно оценить все случаи и глянуть на документацию, наблюдаются два паттерна:

1. Если есть порт, протокол не нужен
2. IP-адресам всегда нужен протокол

Ну, собственно, это и есть ответ на вопрос, как же работает canParse и особо больше понимать там нечего.

Другое дело, что URL.parse и URL.canParse в принципе как-то странно реализованы... Попробуйте в консоли сделать URL.parse("google.com:80").

Так что история ещё не закончена. Понять canParse — можно. А стоит ли применять — вопрос.

#url #parse #static #javascript
#инструмент дня

Из-за моей профдеформации — работа над расширением для Google Sheets — мне очень нравятся различные виджеты таблиц.

От экселеподобных до обычных таблиц aka гридов с фильтрами и сортировкой.

И естественно, моё внимание не мог не привлечь проект с говорящим названием fast-grid: https://github.com/gabrielpetersson/fast-grid

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

Ну и, в общем-то, это правда :) Даже на тринадцатилетнем ноутбуке (с 4 ядрами и 16 гигами оперативы, впрочем) мне удалось загрузить 2 миллиона строк и радоваться жизни (Chrome, Linux).

5 миллионов, впрочем, не получилось ни на нём, ни на MacBook Pro M2 с 24 гигами. На первом вкладка съела 7 гигабайт и рухнула, на втором — съела 4 и ничего не произошло. Вообще.

И тут, конечно, встаёт вопрос целесообразности всех оптимизаций. Иметь по 5-10 миллионов строк в таблице это практически норма для Google Sheets (да, если навесить туда фильтры — всё станет очень плохо, но работает же). Заявленная плавная и бесконечно умное переиспользование DOM это хорошо, но грамотная подгрузка частями и виртуализация всё же выглядят более разумным решением.

Но если вам нужно переварить до миллиона строк — по-моему, вариант отличный.

#javascript #grid #sheets
#статья дня

В заметке про работу с отменой запросов в React Query я лишь косвенно упомянул такую потрясающую штуку, как Abort Controller.

Зачем он вообще нужен?

Можно перестать слушать события, отменить ненужный запрос на сервер (и даже в девтулзах он пометится как canceled), отменить транзакцию, отменить вообще всё, что отменяется, да ещё сделать это стандартным способом!

Документация на MDN крайне скудна и не описывает и половину вариантов применения. Поэтому, нужно что-то ещё.

Про отмену событий мы уже писали, про React Query я упомянул выше... так что давайте для остальных примеров возьмём свежую статью Артёма Захарченко: https://kettanaito.com/blog/dont-sleep-on-abort-controller

1. Уже ставшие классическими примеры отмены событий и запросов
2. Отмена чего угодно вообще
3. AbortSignal.timeout для отработки, внезапно, таймаутов
4. AbortSignal.any для ситуаций, когда сигнал может поступить от разных контроллеров.

Учитывая, что для работы с Google AppsScript API у меня имеется самописный преобразователь коллбэков в промисы, мне и самому стоит дополнить реализацию поддержкой Abort Controller.

Так что статья как раз вовремя.

#javascript #abortcontroller
#рекомендация дня

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

Есть ребята из компании 53xapps, занимаются созданием сайтов и автоматизацией бизнеса. Ну и вот они решили запилить свой собственный курс по Frontend разработке.

Конкретно: введение в алгоритмы, HTML/CSS, JavaScript и Vue.js.

Разработка курса заняла около полугода. Большое количество видео и практики.

Подход к обучению немного отличается от других курсов: сперва несколько уроков вас учат понимать алгоритмы и рисовать блок-схемы. После этого обучение становится более осмысленным.

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

Освоите JavaScript, HTML/CSS, Vue.js. Познакомитесь с несколькими популярными библиотеками. Для старта во фронте вполне достаточно.

Есть несколько бесплатных уроков, можно попробовать и пощупать.

Итак, цена. 5000 рублей. А подписчикам канала промокод HTMLSHIT даст 1000 рублей скидки.

Программа курса и бесплатные уроки доступны по ссылке.

#frontend #HTML #CSS #JavaScript
Media is too big
VIEW IN TELEGRAM
#фишка дня

Когда я наткнулся на этот твит в обсуждении утилиты работы с цветами Андрея Ситника, я не сразу примерил его на себя. Но, как оказалось, стоило бы.

Итак, давайте поясню для тех, кто по ссылкам не ходит.

В азиатских иероглифических языках почти весь ввод с клавиатуры происходит в аккордном режиме или же в режиме т. н. композитинга, общее название — Input Method Editor.

TL;DR: На экране всплывает окошко с символами или их группами и пользователь может что-то выбрать.

На каких-то ОС оно вызывается долгим зажатием клавиши, где-то — по хоткею, а где-то — автоматически и сразу.

Так вот, одно дело азиатские языки (я очень рекомендую посмотреть сам твит), а другое — разные европейские. И речь о диакритических знаках: умляуты, акуты, ударения, птички и шапочки.

Так вот, я не имею финской раскладки, потому буквы ä, å и ö ввожу как раз в режиме композитинга, долгим зажатием «материнской» клавиши.

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

Кстати, выбор Emoji из всплывающего окошка — туда же.

В JavaScript-событиях для этого режима имеется флаг isComposing. Поэтому если вы, как и я в примере на видео, решили реализовать ввод групп символов подобным образом — циклически перебирая поля ввода — стоит об этом подумать :)

Собственно, давайте и пример: https://codepen.io/alinaki/pen/MWMpdvO?editors=1010

И напишите в комментариях, как вы решаете проблему редкого ввода букв с диакритикой у себя в системе. Например, я не помню, как это происходит в Windows, а в Linux я использую клавишу Compose, она работает чуть иначе.

#javascript #composing #event #бородач
This media is not supported in your browser
VIEW IN TELEGRAM
#заметка дня

Ну что, будем долбиться в холст и аналитическую геометрию?

Продолжаем разработку D-pad'а aka крестовины. И сегодня на повестке дня — определение попадания координат клика в нужный нам сектор. Ну и подсветка сектора заодно.

В прошлый раз мы нарисовали крестовину (я честно не знаю, как d-pad ещё называть), а сегодня пришла пора по нему покликать. Ссылка для тех, кто забыл: https://t.me/htmlshit/3279

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

Заодно мы получили бесконечно возможное число секторов.

Математику отрисовки мы обсудили в прошлом посте. Итак, что же делаем по клику?

Для зануд: мы тут в декартовых координатах работаем.

1️⃣Определяем, не ткнули ли мы в центральную кнопку.

Это довольно просто: уравнение окружности у нас (х – х0)² + (y – y0)² = R², где x0 и y0 — координаты центра, а R, соответственно, радиус.

Ну и получается, что пока левая часть меньше правой, мы ткнули в центр. Тут всё просто.

2️⃣ Если попали не в центр, то уже однозначно, в какой-то из секторов.

Здесь задача сводится, опять же, к двум вещам: провести луч из центра окружности в точку, чтобы определить его угол относительно оси абсцисс (горизонтали) и простым сравнением определить, в какой же из секторов попали.

Не забыв про то, что мы повернули окружность на 45° влево, чтобы задать верное направление крестовины.

И для этого существует функция Math.atan2 (Википедия на английском или на русском вот тут): арктангенс для заданных координат, в радианах.

Радианы — просто всё умножается на π.

Ну и всё, перерисовали с учётом нового цвета.

Как всегда, демка на CodePen: https://codepen.io/alinaki/pen/Yzmoyyr?editors=0010

Что делаем в следующий раз, анимируем?

#canvas #javascript #remote
Please open Telegram to view this post
VIEW IN TELEGRAM
#инструмент дня

Когда я недавно вас спросил, какие бы вы посоветовали вопросы для собеседования, были, ожидаемо, предложения поспрашивать про Event Loop и microtask queue.

Я, честно, редко вижу людей, которые на подобные вопросы отвечают с лёгкостью. Но это не значит, что проблемы не существует и знать процесс не надо :)

Слишком много частиц не

К счастью, есть инструменты, которые помогают легче понять происходящее! И вот один из них буквально так и называется: Event Loop Explorer.

https://vault-developer.github.io/event-loop-explorer/

Кстати, там в примере как раз то задание, что так любят спрашивать на собеседованиях :)

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

#javascript #eventloop #tool