Будни разработчика
14.7K subscribers
1.18K photos
334 videos
7 files
2.01K 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
📣 Масштабное исследование по использованию Kubernetes — накануне дня рождения оркестратора

Kubernetes, одному из самых популярных Open Source-проектов, совсем скоро исполнится 10 лет. Накануне этой даты мы в VK Cloud хотим выяснить, как оркестратор помогает решать задачи маленьких и крупных компаний и поделиться результатами исследования со всем сообществом.

Если вам не безразличен Kubernetes, вы можете внести вклад в развитие общего дела: пройдите небольшой опрос — он займёт примерно 10 минут.

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

Приглашаем поучаствовать техлидов и тимлидов, разработчиков, тестировщиков, девопсов, админов, CTO, CIO, CDTO и всех, кто работает с K8s.

Заполнить анкету можно тут: https://bit.ly/3MeMQwZ
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
#библиотека дня

Близятся рождественские и новогодние праздники, а значит, скоро каждый третий сайт получит снег.

Поскольку это неизбежно, давайте сразу скину нормальную библиотеку, которая не заставит ноутбуки ваших посетителей выть: https://github.com/tsparticles/tsparticles

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

А парни развивались! Демок какое-то дикое количество теперь: https://particles.js.org/samples/index.html

Ну и адаптеры есть буквально под все фреймворки.

Да, снег там тоже имеется.

#particles #effect
👍16🤩2
#такое дня

Эта картинка, с презентации NextJS 14 обошла весь твиттер и все ресурсы для разработчиков. Естественно, со скандалом.

Что тут происходит?

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

Почему произошёл скандал? Ну, по мнению уважаемых и разных людей это всё возвращение к PHP4 и его спагетти-шаблонам.

Ну это когда вы сначала к базе данных подключились, а потом <!DOCTYPE HTML> и поехали.

Я не совсем с этим согласен и у меня такое чувство, что все эти уважаемые люди под камнем жили последние 20 лет и пропустили Ruby On Rails, Hotwire, Turbolinks, October CMS, Drupal AHAH, интеграцию Laravel и Vue.js и далее везде.

Камон, мы целую карточную игру на October CMS писали без единой строчки JS, только на директивах и атрибутах, переданных в PHP-шаблон. Да, максимально простую, но зато минут за пять, кроме шуток. Эти вещи не вчера появились, их хотели всегда.

Конечно, код с картинки выглядит убого. Да, директивы "use server" и "use client" — явный костыль. Я сейчас не буду поддаваться истерии и писать о том, что там sql без валидации — откуда вы, блин, знаете? Там же буквально теговый шаблон, sql это функция, которая может делать что угодно. Ну да не суть.

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

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

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

Вы можете воротить нос, а можете творить :)

#nextjs #react
👍25👎1🤩1🤡1
У меня сегодня день рождения. 36 лет.

По этому поводу уже вполне осознанно и намеренно рекомендую вам доклад Вадима Макишвили: 36.

https://youtu.be/nIFClfBXuIQ

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

Рекомендую я его на самом деле каждый год, но сегодня, получается, официально.

Не выгорайте, котаны.
61👍20🤩6
#инструмент дня

Я много обещал рассказать о сетапе для разработки веба, но руки не доходили. Так что приходится кусочками 🙂

Если кто общался со мной в чате, знает: первая рекомендация для работы — это Node Version Manager, nvm.

Зачем управлять версиями ноды? Oh, sweet summer child...

Ну, как минимум, проекты не всегда переводят на поддержку самых последних версий, даже всеми любимые фронтенд-утилиты. Да и legacy strikes back.

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

И тут на сцену выходит Volta: https://volta.sh/

Написана на Rust, быстро инициализируется, позволяет задать нужную ноду прямо в package.json! В итоге переключился на новый проект — и у тебя уже другая версия Node.js

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

#js #node #nvm #volta #бородач
15
#библиотека дня

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

Поэтому многие до сих пор предпочитают axios, просто чтоб не связываться.

Мой друг и, какое совпадение, подписчик решил эти вопросы реализовав библиотеку extended-fetch, о которой я даже писал, с этим же введением: https://t.me/htmlshit/1290

Слово автору:
если очень обобщенно - это попытка вынести в абстракцию над fetch наиболее востребованный функционал axios
цели просты - максимально возможное следование спецификации, "сквозная" типизация, ноль зависимостей, изоморфный код (да, в nodejs сейчас undici как имплементация fetch)


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

https://github.com/glebcha/extended-fetch/tree/master#custom-response-type

то есть чтобы можно было делать так

const api = createHttpClient();

interface Book {
id: string,
description?: string,
}

api.get<Book>('/api/books/12’)

Если не передавать ничего в дженерике и выполнять api.get('/api/books/12'), то вернется объединение типов

Promise<string | Record<string, unknown> | RequestInit | Blob | ArrayBuffer | FormData>

Песочница: https://codesandbox.io/s/extended-fetch-react-typescript-ryxrdj?file=/src/App/App.tsx


По-моему, хорошая альтернатива axios-у, если неохота тянуть лишнего.

Камон, котаны, как ещё опенсорсу пиариться?

#fetch #axios #pr
👍24🤡7
#такое дня

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

Я приношу свои извинения. Это не первый раз, когда команда телеги совершает подобное, и явно не в последний :(
#инструмент дня

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

Ванильный JS — мелкий размер, но поддерживаемо — вряд ли. React — один только DOM-слой займёт 40kB, Preact — 4kB, уже очень хорошо, Svelte свернётся в 1.6kB, но учить птичий язык шаблонов — это надо иметь причину...

И тут выходит VanJS со своими 0.9kB: https://vanjs.org/

Сразу пример кода:

const Hello = () => div(
p("Hello"),
ul(
li("World"),
li(a({href: "https://vanjs.org/"}, "VanJS")),
),
)

van.add(document.body, Hello())


Максимально нативно и понятно, не правда ли? И логика построения UI сохраняется. Есть управление стейтом, поддержка TS. Не нужно никакой сборки, садись пиши. Прекрасная документация, включая примеры от сообщества!

А его шаблонный движок вообще может быть использован отдельно. Назвали Mini-Van :)

#van #framework #js #бородач
👍14🤡5
#инструмент дня

Полку API-клиентов прибыло! Я уже рассказывал про GUI для HTTPie, который делали Злые Марсиане, а теперь пришло время рассказать ещё об одном. Почему пришло? Ну потому что Postman борзеет просто по часам и работает отвратительно.

Итак, Bruno: https://www.usebruno.com/

Хранит все запросы и коллекции в простых текстовых файлах (разрабы придумали язык разметки Bru специально для этого). Правда, я знаю как минимум одного человека-пользователя PhpStorm, который на этом месте презрительно хмыкнул.

Как следствие, все ваши коллекции запросов хранятся просто на диске. Нужно облако — используйте Git. Вот так просто. Планов на своё облако у команды нет.

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

Кажется мне, для многих профессиональных пользователей Postman основной причиной всё ещё будут скрипты, но они и в Bruno есть. Посмотрим, куда вывезет.

#api #client
👍16
#такое дня

Сегодня на работе обновили проект до последней стабильной Node.js и была сказана немного неаккуратная фраза:
— Next on our list is Next.js 14.

И понеслась...

— I have remixed feelings about this
— You are being so reactive
— Not a good move from my vue
— Tired of this, I'll rest on my nest
— Bun intended
— I hate you all I want to underscore this. You’ve ruined everything I believe is good with humanity.
— I'll go
— This conversation is full of solid puns

Продолжим в комментариях? Или ну такое?
👍14
#заметка дня

В чём разница между селекторами :disabled и [disabled]?

Вот вы не знали (наверное), а она есть!

Псевдокласс :disabled выберет любой элемент, находящийся в отключённом состоянии.

Селектор атрибута [disabled] выберет любой элемент, имеющий атрибут disabled.

Например, <input type="text" disabled/> подпадёт под оба селектора, вне зависимости от того, случилось это на этапе прямого рендера или через установку свойства disabled узлу.

Да не томи уже!

Короче, суть дела в том, что атрибут disabled может быть установлен на fieldset, в таком случае поля будут недоступны, но в селектор input[disabled] не попадёт ничего.

Сложно? Вот пример: https://codepen.io/alinaki/pen/VwgKOPE

Короче, аккуратнее.

#css #disabled
👍11
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

Одна из самых недооценённых возможностей CSS-анимаций, это функция steps(n).

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

Почему недооценена? Потому что SVG, Lottie и Rive-анимации предоставляют чуть больше возможностей, но ценой подключения скриптов или целого рантайма. А всего-то надо подготовить лист спрайтов-кадров.

Поэтому сегодня я дам вам два примера. Первый — анимашка шагающего пиксель-артного Локи: https://codepen.io/alinaki/pen/GRPrYdv

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

И наглядно от мэтра Джея: https://codepen.io/jh3y/pen/KKbpeBQ

Если концепция спрайтов вам совсем не знакома, в этом примере можно включить раскадровку.

Никаких рантаймов, красота.

#css #sprite #animation #бородач
👍17
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

Стопудово вы делали эффекты как на видео через три div-а или span-а. Ну просто потому что трансформации на SVG это абсолютная боль.

Типа такого: https://codepen.io/alinaki/pen/abXpvyQ

Да, пример очень простой, но даже это на SVG бывает проблемно санимировать.

Хотя, казалось бы, для этого и предназначено.

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

Первый, от Аны Тюдор: исправить viewBox, поставив вместо 0, 0 (левый верхний угол) — -width/2,-height/2, соответственно, исправив остальные координаты.

Второй, интереснее, от Джея: указать следующие правила в CSS:

transform-box: fill-box;
transform-origin: 50% 50%;


Правило transform-box исправит положение координатной сетки, от которой мы уже сменим дефолтную точку отсчёта для преобразований — transform-origin.

По-умолчанию, кстати, transform-box установлен как view-box. То есть, в нашем примере, заполняет лишь 24 пикселя по каждой стороне 🤡

А вот и, собственно, пример:
https://codepen.io/alinaki/pen/YzBNyEz

Не бойтесь анимировать SVG, котаны. Просто не полагайтесь на дефолт.

#css #transition #svg
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25
#заметка дня

Что делать, если нужная вам библиотека не предоставила типы для всех публичных методов?

Ну вот такое вот архитектурное решение: метод экспортирован из модуля, а тип или интерфейс — нет?

Делать unknown или any? Копировать и переопределять с помощью as?

Ни в коем случае! Вам нужен простой советский... ReturnType: https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype

Пример использования — на иллюстрации. Ну или ещё можно так:

const createPerson = () => ({
firstName: 'John',
lastName: 'Doe'
})

type Person = ReturnType<typeof createPerson>

Не делайте ерунды, котаны. Читайте документацию.

#typescript #ts #types #бородач
👍191
А вот в комментариях к предыдущему посту ещё полезное :)
Более того, что делать если вам нужно создать тип, параметры которого служат для передачи в функцию, которая является библиотекой и вам нужно передать все required параметры, не делайте это ручками, используйте Parameters

const createPerson = ({
firstName,
lastName
}: {
firstName: string,
lastName: string
}) => ({
firstName,
lastName
})

type CreatePersonParams = Parameters<typeof createPerson>[0];

const params: CreatePersonParams = {
firstName: 'John',
lastName: 'Doe'
};
👍14
#инструмент дня

Каждый разработчик за свою жизнь должен сделать следующее: написать музыкальный плеер, тетрис, игру Жизнь. Если ты веб-разработчик, то ещё свою CMS, PHP-фреймворк, стейт-менеджер и... и уведомления.

Если тебе 14 лет, то ещё и криптобиржу.

Короче, уведомления вообще штука раздражающая. Всегда чего-то не хватает в существующих решениях. Но в любом случае, сегодня вашему вниманию React Hot Toast: https://react-hot-toast.com/

Отличаются маленьким весом, возможностью отмены скрытия пока наведена мышь, поддержкой промисов и JSX-содержимого, стилизуются, прости господи, через Tailwind. Не думал, что внесу это в плюсы, но после UI-китов на Emotion это уже очень хорошо.

Ещё бы туда диалоги добавить, было бы уапще.

Всем тостов, котаны! За мой счет :)

#react #toast #бородач
👍10🤩1
#фишка дня

Накидали секций, поставили к ним якоря, поставили ссылки вида #anchorName в навигацию, включили scroll-behavior: smooth; чтобы плавненько все было и...

...и ваша секция уехала под шапку ко всем чертям. Что же делать?

Спокойно. Есть три варианта.
1. Если ты живешь в 2012, можно подвинуть якорь вверх с помощью position: relative и отрицательного top. Или всячески играть полями. Но мы живем в 2023, так что...
2. scroll-padding-top на html (а часто, на родителя секций) или...
3. scroll-margin-top на любую из секцию, за которой якорь закреплен.

В чем отличие 2 от 3?

Ну, очевидно, в области применения. Разом на всех во 2 случае или индивидуально в 3.

Важно понимать, что на обычный скролл это не распространяется. Только якоря или snap: https://getpublii.com/blog/one-line-css-solution-to-prevent-anchor-links-from-scrolling-behind-a-sticky-header.html

#css #scroll #snap #anchor #бородач
👍16
#баг дня

Вчера вечером коллега пришла с проблемой: бесконечная загрузка на паре проектов. И если на одном проекте подобное казалось логичным — он сильно зависит от платформы — то для второго это уже был перебор.

Попробовал повторить проблему, воссоздал все условия — не вышло. Утром взял её ноутбук и сел отлаживать.

Ни одной ошибки в консоли нет. На вкладке Network тоже всё чисто...

...подозрительно чисто.

Полез в дебаггер и обнаружил, что хуки загрузки данных, основанные на React Query, не вызываются вообще. Ни разу.

Сетевые операции без React Query работают прекрасно — приложение состоит их микрофронтендов, какие-то из них легаси, какие-то нет.

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

И тут коллега сообщает, что в Safari всё прекрасно работает.

Отчаявшись понять, что происходит, я вбил в гугл банальный запрос вида: "react query not working in chrome"

И нахожу золото.

Я понимаю, что к этому моменту уже мог вас утомить, но попробуйте понять происходящее. Это слишком хорошо.

1. Google Chrome на macOS неверно определяет состояние сети и поднимает флаг "офлайн" на navigator.onLine.
2. React-Query считывает этот флаг и ставит все ваши запросы на паузу. Без уведомлений, без ошибок. Молча.

Всё, вы в ловушке.

Как исправить? Передёрнуть wi-fi на ноутбуке. Я щас не шучу даже.

Проблеме в Chrome 7 лет! Создатели React-Query знали об этой проблеме и ничего не сделали!

Они исправили поведение на "всегда считать, что мы онлайн" только в 5 версии своего продукта, которая ломает совместимость!

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

Я ничем кроме как "горе от ума" это описать не могу. React-Query в принципе делает слишком много спорных настроек по-умолчанию, но после этого случая мы буквально пересмотрим своё решение по альтернативам.
🤡14👍4🤬2🤩21
#заметка дня

Давайте продолжим про React Query aka TanStack Query нынче.

В комментариях писали, мол, использовать React Query (возьму старое название) это плохая привычка, современные браузерные API прекрасно справляются, надо всего лишь немного их расширить.

Немного в моём случае это:
1. Состояния isLoading, isSuccess, isError
2. Сообщение об ошибке
3. Отмена запроса через AbortController
4. Глобальное состояние загрузки (на всё приложение)
5. Нормализация данных
6. Инициация повторной загрузки
7. Поллинг
8. Кеширование данных в едином слое и решение об инвалидации.

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

Уследить за всем непросто, но это полбеды. Тесты писать кто будет на ваши обёртки?

Да, React Query и ему подобные SWR-решения (stale-while-revalidate в клиентских приложениях превратился в целый концепт) не являются вечнозелёными. Термин "вечнозелёный" я принёс сюда из CMS Drupal: там это означало модули, поставляющиеся с ядром системы. Это значит, вероятность их удаления или радикального изменения API крайне мала. В нашем случае вечнозелёными являются браузерные API.

Но вы забываете об одной крайне немаловажной фишке React Query и SWR: они могут работать с любыми промисами. Не только с сетью и fetch!

И вот тут начинается прекрасное. Долгие вычисления? Промис! Забрать картинку с холста? Промис! Обработать загруженный на клиенте файл? Тоже промис! Написать расширение для браузера и обратиться к данным со страницы или результату парсера? Промис! Обратиться к прослойке между Google Sheets и твоим расширением? Промис! То же самое в Excel. То же самое в Figma. Далее вообще везде.

Вы понимаете, к чему я клоню? Хватит думать сетью, начинайте думать операциями!

И вот тут у React Query в моём случае из конкурентов разве что Effector. Но есть одна проблема... его концепты мало того, что сложны, так и обзорных статей не на русском очень мало. Но об этом потом.

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

Если React Query принимает на вход любой промис, то что вам нужно для того, чтобы протестировать своё приложение? Поднимать Mock API Server? Вы уверены?

Замокайте вызов промиса! Всё, вы прекрасны. Остальное уже протестировано за вас.

Задавайте ваши ответы, котаны.

#react #query #development
👍191👎1