Веб-платформа – Telegram
Веб-платформа
2.03K subscribers
4 photos
2 videos
153 links
📍 О том, как всё устроено в веб-платформе и что происходит в индустрии фронтенда

⭐️ Новости, полезные выжимки, находки и напоминания

👨‍💻 Вопросы и предложения @web_platform_support

🔗 webplatform.tech
Download Telegram
#Лаборатория_веб_платформы

Окей, когда что-то нужно перестроить в интерфейсе при изменении разрешения экрана, используется media query в CSS.

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

Первая мысль, как поступить в этой ситуации — подписаться на resize окна и смотреть в хендлере, нужная сейчас ширина окна или нет.



function handleResize() {
if (window.innerWidth >= width) {
// setIsGreaterThanOrEqual whatever
}
}

window.addEventListener('resize', handleResize);


Проблема такого подхода в том, что резайз будет срабатывать на каждом изменившемся пикселе размера окна, и триггерить перерисовку. Что не есть хорошо если нужно отследить только факт условного «сейчас мобилка или нет?».

Триггерить только срабатывание определённого условия ширины можно… теми же mediaQuery, только в JS. Для этого существет API window.matchMedia https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia, который принимает строку с медиавыражением и возвращает объект MediaQueryList, содержащий информацию о медиавыражении, применённом к документу.



const matchQueryList = window.matchMedia("(max-width: 600px)")


Для разовой проверки соответствия используется свойство matches:



matchQueryList.matches // true or false


А для постоянного отслеживания соответствия, есть подписка на событие change:



function handleChange(e) {
// e.matches whatever
}

matchQueryList.addEventListener("change", handleChange)


Для Реакта всё это заворачивается в хук и получается удобное отслеживание медиавыражений в JS:



function App() {
const isMobile = useMatchMedia("(max-width: 768px)");

return <h1>Browsing with {isMobile ? "mobile" : "desktop"}</h1>;
}


Код тут https://codesandbox.io/p/devbox/frosty-mcclintock-93ghzg
🔥11👍8
#Пульс_веб_платформы 26.01.2024

Новости
- состоялось заседание рабочей группы по веб-компонентам W3C, результаты: Declarative Shadow DOM появится в Firefox 123 в конце февраля (эта фича, позволяющая использовать Shadow DOM напрямую в HTML без вызова attachShadow() из JS); начнёт разрабатываться Scoped Element Registries, позволяющий создавать элементы с одинаковым именем в рамках одной страницы; Container Style Queries быть во всех движках в ближайшем будущем 🎉
- грядущие нововведения в «клиентском» Реакте: use(Promise) — саспендинг на клиенте; use(Context) — такой же, как useContext, но можно вызывать в условиях; хуки и апи для работы с формами Form Actions, useFormState, useFormStatus; а также useOptimistic — специальный хук, чтобы смотреть на «классический» Реакт с оптимизмом
- обновления в Chrome 121: появились свойства scrollbar-color и scrollbar-width (раньше работало только в FF, так что если у вас были стили только для FF в Хроме тоже внезапно включится!); font-palette для управления цветовыми шрифтами; псевдоэлементы ::spelling-error и ::grammar-error для стилизации ошибок; Speculation Rules API для программного префетча и пререндера страниц в классических MPA; showPicker() для программного выпадения <select> (кажется, я когда-то ждал этого, но так давно, что уже забыл)
- вышел Safari 17.3: пофикшен @supports и цвет каретки на iOS, закольцовывание медиа с нулевой длиной и другие мелочи

Проекты
- bun shell — возможность запускать shell-скрипты в JS (с помощью и во славу Bun)
- workerpool — централизованный способ выгрузить воркеры (если у вас их много разных) в отдельный пул с очередью выполнения
- partytown — запуск 3d-party скриптов в воркере (для выгрузки Google Tag Manager, Google Analytics, Amplitude из основного потока)

Статьи и демки

JS
- как отделить 0 от null и undefined: напоминание про разницу операторов || и ??
- c AbortController.abort() удаляет разом несколько обработчиков событий (не нужно писать множество removeListener, yay!)
- если вы захотите обновиться на 18 Реакт, возможно вам тоже придётся сделать что-то из того, что уже сделали в команде SonarQube
- Реакт-стартеры в 2024: Vite, Next или Astro?
- возможная замена проп-дриллингу — {children}
- туториал по Next.js App Router от мейнтейнера Node.js и webpack: минималистично и интерактивно
- как уменьшить размер бандла — рецепты с разных сторон: мониторинг через Lighhouse, Sentry; анализ с помощью Webpack Bundle Analyzer, Statoscope, bundlephobia; распространённые приёмы — отключить сорсмапы, оптимизировать импорты библиотек типа lodash, выделение чанков, динамические импорты и фреймворкоспецифичные подходы типа React.lazy

CSS
- частичный фейд текста с помощью градиентов (именно текста, а не покрывающий слой!): способы с mask-image и background-clip: text
- сборник мелких, точных (и злых) «CSS-однострочников», которые уже можно заносить в проекты (и за это не придётся оправдываться): aspect-ratio, object-fit, margin-inline, text-underline-offset…
- ещё одна подборка юзкесов селектора :has(): делаем выборку родителя, предыдущего сиблинга, по количеству элементов, в любом месте или всё, кроме меня
- в догонку к предыдущему пункту демка с плавным переходом между радио-кнопками, которая стала возможна в CSS благодаря :has()
- в 123 Chrome появится свойство field-sizing, авторасширяющее инпуты и текстареа при вводе длинного текста (неужели это когда-нибудь свершится, боже)

HTML,
SVG
- эффект движущейся линии по скроллу на SVG элементах <linearGradient>, <path> и <clip-path>
- чтобы улучшить метрику CLS достаточно просто один раз в день… задавать размеры <img> в атрибутах width и height (и без px)
- aria-hidden в жизни: для сокрытия визуальных декоративных элементов, скрывает интерактивные элементы не всегда, aria-hidden !== aria-hidden="true"

Платформа
- рецепты как выключить браузерное кеширование в серверных заголовках, HTML, htaccess, PHP и других бэкендах
- каталог известных (и не очень) дизайн-систем на случай, если вам понадобится впечатлить коллег проведённым обширным ресёрчем
🔥83
#Лаборатория_веб_платформы

Веб-платформа регламентирована как backwards и forwards совместимая.

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

Работает это так. Вам вдруг приходит задача, что что-то поломалось в коде. Причём в старом коде, который уже давно не менялся и был написан прото-программистами, которые уже давно уволились. Казалось бы, что может пойти не так? А дело в том, что сами браузеры обновляются и в них что-то вдруг начинает работать по-другому. В том числе код, который вам предстоит исправить. Самые «любимые» баги.

Как это такое происходит, ведь платформа должна быть обратно совместима? Главным образом так: далеко не всегда сначала появляются стандарты, а потом браузеры пилят фичи по этим каноническим стандартам. Иногда фичи просто пропушиваются вендорами (яркий пример — префиксы -webkit-feature, -moz-feature), а потом уже под них подгоняются стандарты или же они адоптятся стандартами и… всё это обратной волной докатывается до браузеров. Браузеры немного меняют имплементацию и ваш код, который просто работал, становится как бы сломанным.

Что поделать, ваш код признан устаревшим и приговаривается к утилизации, приговор обжалованию не подлежит!

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

Есть такой метод play() у аудио и видео HTML-элементов. Он появился ещё в Chrome 3. Он просто работал и включал медиа. То есть можно было запустить, например, видео и тут же его поставить на паузу, чтобы оно сразу прогрузилось.


<noscript>
  video.play();
  video.pause();
</noscript>


Потом в Chrome 32 появились Promise. Затем обновились стандарты. И уже в Chrome 50 метод play() стал возвращать промис вместо того, чтобы синхронно выполнить запуск медиа. То есть ваш код сломался и выдаёт эксепшн, который даже даёт ссылку на специальную страничку https://developer.chrome.com/blog/play-request-was-interrupted.

Ещё один пример, немного с другого бока подсвечивает эту же проблему. Люди издревле желали стилизовать скроллбары. Поэтому в Chrome появился целое семейство свойств для стилизации (::-webkit-scrollbar, ::-webkit-scrollbar-track…), в которых можно было задавать ширину или высоту скроллабара (в пикселях!), его цвет фона. Потом это дело ушло вариться в стандарты, ранние черновики были реализованы в Firefox: это были свойства scrollbar-width и scrollbar-color. Причём в scrollbar-width уже нельзя было задавать значения в пикселях (только thin или auto), а scrollbar-color принимал два цвета через пробел (для фонового цвета трека и «таскалки»). И вот так оно и жило где-то с 64 версии FF до наших дней: для стилизации в FF использовался «правильный» вариант с scrollbar-width/scrollbar-color, а в Chrome работали вендорные префиксы.

Что же могло пойти не так? В Chrome 121 завезли (https://developer.chrome.com/docs/css-ui/scrollbar-styling) так же стандартные scrollbar-width и scrollbar-color! И ваш код, хоть и не упал, но начал работать по-другому, так как скроллбары стали другими, и хорошо, если просто стали другими. В целом не то чтобы критично. Но возможно сегодня где-то в далёком офисе одинокий разработчик сдувает пыль с давнего проекта и добавляет хак, чтобы всё оставалось как раньше, и в Chrome по-прежнему применялась только стилизация через вендорные префиксы:


@media screen and (min--moz-device-pixel-ratio:0) {
.scrollable_styled {
scrollbar-width: thin;
scrollbar-color: gray transparent;
}
}

.scrollable_styled::-webkit-scrollbar {
width: 8px;
}

.scrollable_content::-webkit-scrollbar-thumb {
background-color: gray;
}


Directed by robert b weide 🥁

А для тех, кто дочитал до конца, приятный бонус: список задепрекейченых и выпиленных платформенных API: JS, HTML, CSS.
👍10🔥3
#Пульс_веб_платформы 02.02.2024

Новости
- в React 19 появятся нативные custom elements (мама, неужели они решили задепрекейтить jsx?!)
- что в последнее время появилось нового в браузерах: <hr> в <select>, HTMLSelectElement.showPicker, стилизация скроллбаров, анимация font-palette, transfer() и transferToFixedLength() у ArrayBuffer
- анонсирован Typenoscript 5.4 beta: улучшение сужениях типов в замыканиях, новый утилитарный тип NoInfer для запрета вывода типов, Object.groupBy и Map.groupBy, улучшение quick-fix, а также анонс грядущих депрекетов в TypeScript 5.0
- минорно обновлены версии Node 18, 20, 21 для фиксов безопасности
- в V8 v9.1 выпущена поддержка import assertions (это такое import json from './foo.json' with { type: 'json' }, для того, чтобы не запустить зловредное ПО, маскирующееся под JSON)

Проекты
- expressive-code — решение для интеграции блоков кода в контенте сайта (для astro, next)
- unlazy — универсальная либа для ленивой загрузки картинок (с плейсхолдерами)
- веб-компонент авторастягивающейся textarea
- анимация прыгающего мяча кучей возможных способов (без JS, на чистом JS, с либами, на canvas, видео и гифка)
- type-coverage — мониторинг и зачистка (от any) типов в проекте

Статьи и демки

JS
- мнение, что вся React-движуха завела часть индустрии не туда, отзывается: неестественный для браузера DX, в который двигаются React, Next и иже с ними, оказывают медвежью услугу (и, конечно, зарабатывают на этом), и, в целом, во многих случаях не нужны, так как являются легаси из 2013, когда в
браузерах не было шаблонных строк и BFCache
- ещё одно мнение, что система, которая вынуждает переписывать кодовую базу каждые 2-3 года — слабая, и напоминание о «правиле минимальной мощности», когда для решения задачи следует выбирать минимально необходимый по мощности язык/технологию
- не поверите, ещё одно мнение о том, что стоит попробовать Qwik вместо React (по мне так шило на мыло, нужны другие ментальные модели для написания кода для платформы)
- сначала придумывается SSR, потом решается, как же быть, когда нужно узнать что-то из клиентского браузера, а потом придумываются костыли — надёжный план!
- попытки замерять Core Web Vitals не только на первой загрузке SPA, но и на последующей клиентской навигации — спец событие soft navigation для PerformanceObserver
- pnpm поддерживает страницу с бенчмарками npm, pnpm, yarn (они поддерживают страницу, потому что pnpm быстрый или следят за быстротой pnpm из-за поддержки страницы 🤔)
- современный стартер для либы: TS, тесты нативные node:test, билд npm-скриптами, конфиг для CI на GitHub Actions в yml, автодеплой в npm, provenance и секреты
- event loop – мифы и реальность: браузерные и небраузерные среды исполнения, почему понятия нет в спеке ECMA-262, макротасков не бывает, а task queue это не очередь, а set
- улучшаем качество кода React-приложения с помощью Compound Components

CSS
- блюрная backdrop-тень с помощью mask, backdrop-filter и box-shadow
- если вы всё ещё убираете обводку (outline: 0), то это можно уже не делать, так как есть :focus-visible
- попытка объять необъятное шрифтовые единицы измерения длины: cap, ch, em, ex, ic, lh, а также из «рутовые» аналоги rem, rlh, rex, rch, ric и другая магия
- выделение текста с помощью скролл-анимации: animation-timeline и background-size
- строим тоггл: с :has(), адаптивно, доступно, с «ручками» для кастомизации стилей
- анимация цветовых шрифтов font-palette (жаль, что самих шрифтов мало)
- анимация движения по линии в SVG с offset-path и offset-distance
- свежий взгляд на старую как мир стилизацию <table>

HTML, SVG
- про тег <abbr> и атрибут noscript: лучше не использовать и с noscript, и без него
- плохие стороны HTML: лучше НЕ использовать <select multiple>, атрибут noscript, <datalist>, <input type=number>, <input type=date>, <menu> во избежание проблем

Платформа
- базовые различия jwt и session-вариантов аутентификации: jwt более модное, но сложнее в реализации, сессия попроще и понадёжнее
- что намечается в рамках Interop 2024: хотеть custom properties, declarative shadow DOM, relative color syntax, @starting-style
🔥12👍32
Недавно мы с Александром, автором канала «Frontend Everyday» , решили подискутировать на тему «Отберёт ли ИИ работу у разработчиков».

По моему мнению, в обозримом будущем работа разработчиков существенно изменится.

Недавно мне попался рейтинг профессий Job Impact Index, в котором показано на сколько % сейчас та или иная работа затронута ИИ. Так вот, 70% условных задач frontend-разработчика уже сейчас автоматизируется и может быть делегирована (выполнена с помощью) ИИ.

Что же там в оставшихся 30% задач? Кастомизация и нешаблонные вещи, высокоуровневые задачи, которые сложно сформулировать, или которые находятся в контексте больших существующих систем, работа на стыках нескольких систем, проприетарщина и тд.

Но главное, что входит в эти 30% — это ответственность, которую человек берет на себя за результат.

Даже если бы уровень автоматизации был на условных 99%, все равно кто-то должен эту автоматизацию запускать, внедрять и поддерживать. Робот сам по себе не несет ответственности за то или иное решение. Это делает человек, который выбирает решение, предложенное роботом.

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

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

И мы оказываемся в ситуации, когда люди с определенным опытом, которые могут брать на себя ответственность за крупные задачи и системы (условно «сеньоры»), востребованы и их зарплата продолжает расти. В то же время начинающие разработчики, которые с ходу большую ответственность не могут потянуть (условно «джуны») теряют: во-первых, в деньгах, так как вдобавок растёт конкуренция среди других джунов, а во-вторых, в возможности вообще куда-то устроиться на работу, так как работу делают сеньоры и их дрессированные роботы.

Парадоксальность ситуации в том, откуда будут появляться новые сеньоры, если новых джунов в рабочих процессах задействуется всё меньше? Выходит, что путь «органического роста» из джуна в сеньора теперь становится слишком медленным и неудобным для изменившегося процесса работы. И новые сеньоры должны буквально прокачиваться на местах в мегаускоренном темпе «на стероидах».

Это может производиться либо с помощью классического прикрепления 1-1 джуна к сеньору (подмастерье <-> мастер), чтобы в максимально синхронном режиме вкатываться в рабочий процесс. Либо, если нужны промышленные масштабы, в некой симулирующей среде (тренажёре, симуляторе, инкубаторе, акселераторе…) джун на решении смоделированных задач ускоренно прокачивается и набирает нужное число часов «налёта» перед выходом в «реальный мир». Возможно даже и одно, и другое по очереди: симулятор -> парная работа.

Такие дела.

А теперь время пойти почитать, что скажет Александр в @front_everyday и решить, кто же из нас двоих прав. 😊
🔥6
#Пульс_веб_платформы 09.02.2024

Новости
- вышел Million 3 (кастомный компилятор для React): авторы обещают, что просто выполнив npx million@latest можно добиться ускорения работы Реакта с O(n) до O(1)
- вышла jQuery 4.0.0 BETA: без шуток внушительный чейнджлог, в который разве что не влез отказ от IE11
- вышел Vite 5.1: появился экспериментальный режим Vite Runtime API, позволяющий сделать прослойку между сервером и рантаймом и делать там что-то своё, такая мидлваря, но мощная, и отвязанная от сервера; поддержка запуска CSS-препроцессоров в отдельных потоках (перф улушается); более быстрый холодный старт; улучшенная поддержка .css?url и другие фишки
- вышел биндинг GSAP для React @gsap/react, включает удобный хук useGASP()
- вышел Remix v2.6.0, который однажды утром проснулся и обнаружил, что он превратился в Vite-плагин

Проекты
- drab — коллекция headless кастомных элементов (для расширения кругозора, что кастомные элементы можно использовать как обёртку как для ui-элемента, так и для процесса, например, prefetch)
- noscriptfm — визуальный конструктор SVG-фильтров, позволяющий собирать фильтры в цепочки (написано на JS!)
- baklava — приятная дизайн-система и ui на нативных веб-компонентах без примудростей
- replay — «проигрывание» действий в интерфейсе puppetier-ом с помощью Chrome DevTools Recorder (попробуйте, это вкладка есть в девтулзах Хрома)
- knip — либа для нахождения неиспользуемых файлов, зависимостей и экспортов в проекте
- simple-git-hooks — суперлайтовые и простые гит-хуки, если не нужно сложности и нужна быстрота и простота
- npmgraph — визуальное отображение зависимостей проекта в виде интерактивного графа

Статьи и демки

JS
- типобезопасные id в TS с помощью template literal types (`node_${string}`): в комментариях приводят более общее решение через branded types
- как Deno изменился за 2023 год, а также кое-что под названием JSR (JavaScript Registry), «смутно напоминающий npm», но с нативной интеграция TS и ESM-only пакетами, автоматически генерируемой документацией
- стата о самом востребованном JS-фреймворке: конечно, это React по количеству вакансий; в Бельгии больше всего востребован Vue, а в Швейцарии — Ангуляр (интересно, а отсутствие JS-фреймворка это хоть сколько-нибудь востребовано?)
- оказывается есть не только <input type="color"> (везде), но и цветовой пикер new EyeDropper() (в Хроме)
- очередной герой самоотверженно бросается в пучину настройки фронтовой монорепы и выясняет, что для него лучшим оказалось сочетание инструментов Turborepo + pnpm
- бестпрактисы и юзкейсы переменных окружения .env: можно задавать при запуске ноды, в .env-файлах можно задавать фича-тогглы, переменные для разных окружений и хранить секреты
- попытка ещё раз взять и запомнить различия между типами ReactElement, ReactChild и ReactNode
- когда может пригодиться as never в TS (спойлер: в этом кейсе не поможет даже as any!)
- шоукейс про микрофронты от команды Dodo: в 1 и 2 рассказано, как переходили на SingleSPA + SystemJS, а заодно и на Vite и Vitest
- а может и не нужны эти ваши микрофронты и достаточно ограничиться npm modules или даже git submodules?
- организация кэша в JS с помощью Cache Storage API и его преимущества перед local storage и indexed db

CSS
- юзкейсы all: revert-layer: более лайтовый ресет, чем all: revert, точечное восстановление ранее сброшенных значений, а также антихрупкие дефолты для переменных var(--size, revert-layer)
- градиентная рамка с помощью linear-gradient и mask
- боковая шторка на <dialog> (не обошлось без заворачивания в веб-компонент)
- CSS-анимация SVG-элементов и тонкости настройки transform-box и transform-origin

HTML, SVG
- пятёрка атрибутов, улучшающих UX: hreflang, translate, reversed, controls и autocomplete (в порядке возрастания полезности)

Платформа
- история о том, как веб нарушил конвенцию квадратных чекбоксов и круглых радиокнопок
- дзен и искусство ухода за маком в 2024: чеклист от и до
- кто такой и зачем нужен CORS с бонусным списком как не нужно его обходить (принимать всё отовсюду, выключать preflight checks плагинами в браузере и устанавливать mode в no-cors)
👍11🔥1😐1
Чему равно сравнение 0X0 === 0B0
Anonymous Quiz
44%
true
39%
false
17%
Error
Объяснение 👇

В JS можно записывать числа помимо десятичного формата в двоичном, 8-ричном и 16-ричном. Для этого нужно начать число с 0, а дальше:

- поставить B, а после него записать двоичное число, например, 0b10 === 2
- поставить O, а после него записать 8-ричное число, например, 0o10 === 8
- поставить X, а после него записать 16-ричное число, например, 0x10 === 16

0x0 — это 0 в 16-ричном формате, а 0B0 — это тоже ноль, но в двоичном формате. Но ноль любом формате — это всё тот же ноль, поэтому они равны между собой.

Завтра будет пост с одним интересным юзкейсом чисел в двоичном формате в JS 🛠️
👍8🔥2
#Лаборатория_веб_платформы

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


// все три слота свободны
000

// первый слот занят, остальные свободны
100

// первый и третий слоты заняты, второй свободен
101


Ок, идём дальше. То, что состояния теперь заданы в виде двоичных чисел, даёт возможность применять к ним двоичные операции! Например, это могут быть двоичные И и ИЛИ. Обозначаются они операторами & и |. Двоичные числа сравниваются побитово (первый бит одного числа с первым битом другого, второй бит одного числа со вторым битом другого…).

В случае логического И оба бита должны быть равными 1, чтобы в результате получить 1, в остальных случаях будет 0:


0 & 0 === 0
0 & 1 === 0
1 & 0 === 0
1 & 1 === 1


В случае логического ИЛИ любой из битов может быть равен 1, чтобы получить в результате 1:


0 | 0 === 0
0 | 1 === 1
1 | 0 === 1
1 | 1 === 1


И теперь, если вернуться к примеру со слотами, мы можем «складывать» два состояния с помощью побитового ИЛИ: 100 | 001 === 101 (первый занятый слот ИЛИ третий занятый слот — это занятые 1 и 3 слот). А из «суммы» двух состояний можно убрать все состояния, кроме определённого, с помощью побитового И: 101 & 100 === 100 (первый с третьим занятые слоты И первый занятый слот — это первый занятый слот).

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


const MOBILE = 0b0001;
const TABLET = 0b0010;
const LAPTOP = 0b0100;
const DESKTOP = 0b1000;


Можно использовать как просто отдельное состояние, например, MOBILE, так и композицию нескольких состояний, к примеру, MOBILE | LAPTOP (что буквально так и считывается мобайл ИЛИ лаптоп, спасибо TS👋).

Это можно использовать для задания динамических ключей объектов:


const objectMap = {
[MOBILE]: "mobile stuff",
[LAPTOP]: "laptop stuff",
[MOBILE | LAPTOP]: "mobile or laptop stuff",
};


Как вы уже, возможно, догадались, распаковать этот ключ можно с помощью логического И (&), обратной операции. Предположим, что нужно отфильтровать только те ключи, в которых есть MOBILE, то есть нужно ко всем ключам применить & MOBILE:


MOBILE & MOBILE === MOBILE
// у 0b0001 и 0b0001 есть общая 1, получаем 0b0001

LAPTOP & MOBILE === 0
// у 0b0100 и 0b0001 нет общей 1, получаем 0b0000

(MOBILE | LAPTOP) & MOBILE === MOBILE
// у 0b0101 и 0b0001 есть общая 1, получаем 0b0001


Дальше отфильтровываем те значения, ключи которых выдали нули и готово!

Вот как выглядит функция-фильтровщик:


function getFilteredValues(objectMap, filterKey) {
return Object.entries(objectMap)
.map(([key, value]) => {
const shouldInclude =
(key & MOBILE) === filterKey ||
(key & TABLET) === filterKey ||
(key & LAPTOP) === filterKey ||
(key & DESKTOP) === filterKey;
return shouldInclude ? value : null;
})
.filter(Boolean);
}


Код https://codepen.io/juwain/pen/KKEGRrB?editors=0011

Кстати, небольшой оффтоп: обратите внимание на ссылку. Codepen тоже использует битовую карту, чтобы обозначить, какие редакторы по умолчанию скрыть (0), а какие показать (1) 👾

Я использовал такой подход для динамического создания стилей для каждого типа девайса. Иногда стили для соседних девайсов повторялись, не хотелось их дублировать и получилось сгруппировать по типу MOBILE | LAPTOP.

Пример (это Styled Components):


${setResponsiveStyles({
[MOBILE]: css`
// some only mobile styles
`,
[MOBILE | TABLET]: css`
// some mobile or tablet styles
`,
[LAPTOP]: css`
// some only laptop styles
`,
[DESKTOP]: css`
// some only desktop styles
`
})}
🔥8👍5
#Пульс_веб_платформы 16.02.2024

Новости
- вышел Safari TP 188: добавлена поддержка альтернативного синтаксиса свойства content, поддержка supports внутри директивы @import, выпилена поддержка нестандартного resize: auto и много всего мелкого пофикшено
- из-за противостояния бюрократии и бигтехов в iOS в Европе перестанут работать PWA, как работают сейчас (по сути останется возможность только создать «закладку» со ссылкой 🤷‍♂️)
- мейнтейнер Express решил взбодрить проект и запостил планы на 5, 6 и 7 версии (которые подозрительно напоминают план начать с нового года жизнь заново): больше координации с LST-версиями Ноды, меньше манкипатчинга и использования внутрянок Ноды, официально поддерживаемые типы

Проекты
- hono — серверный фреймворк для все JS-рантаймов: недавно вышла версия 4, которая во времена Реакта, идущего на сервер, наоборот стала уметь в SSG, клиентские компоненты (c jsx и реактовскими хуками), file-based роутингом и другими плюшками. Безусловно, радует что не next-ом единым!
- glaze — если вдруг вам нравится tailwind-подход к написанию стилей, этой либой можно так же «декларативно» описывать GSAP-анимации
- tabgod — запуск JS-скрипта одновременно в нескольких табах сразу (для гугления сразу в нескольких гуглах, например)
- react-joyride — либа для создания туториалов и онбордингов по сервису
- type-fest — набор базовых утилитарных дженерик-типов TS (автор разрешил копипастить код без импорта либы 😊)
- tempo — yet another библиотека для работы с датами от команды Formkit

Статьи и демки

JS
- иногда сидишь, думаешь, как пробросить что-то из состояния в DOM или наоборот, и тут, хоба!, можно же пробросить значение в кастомном свойстве!
- подход к рефакторингу кода, который оброс множественными ветками условий или кейсов: найти общий паттерн, выделить его в интерфейс и причесать ветки кода так, чтобы каждая имплементировала выделенный интерфейс
- как хэндлить события за пределами компонента в Реакте, из которого я узнал в том числе о нативном методе event.composedPath(), выдающие массив всех таргетов, через которых пройдёт событие при всплытии
- дружеское напоминание, что Array.prototype.with работает везде и может «заменять» элементы массива немутабельно
- новые методы Set.prototype.union, Set.prototype.intersection, Set.prototype.difference и другие (похожие на SQL) методы доступны в Chrome 122+ и Safari 17+

CSS
- объёмный (я бы даже сказал) справочник по цветовым пространствам, функциям в CSS от базовых до современных от гугловцев: color(), display-p3, oklch, градиенты, проверка фич в supports()
- пока мы тут работу работаем, в CSS тихо варятся нативные mixin-ы и функции
- новые функции возведения в степень pow(), квадратный корень sqrt() и другая математика (даже есть примеры!)
- задание диапазона жирности насыщенности шрифта с font-weight для вариативных шрифтов
- как побороть поведение iOS, когда неправильно определяется цвет скроллбара, и он оказывается белым на белом фоне
- на три вещи можно смотреть вечно: на огонь, воду и центровку блоков в CSS — современное прочтение без transform: translate(-50%)
- если нужно вставить SVG фоном, можно встроить его прямо в CSS, и оказывается, можно даже не энкодить его в base64

HTML, SVG
- ещё одно дружеское напоминание, что элемент <dialog>: 1) поддерживается везде и 2) из коробки имеет центровку, оверлей, закрывается по esc, а также ловит фокус и возвращает его при закрытии
- дизейблить кнопки ок, но не совсем ок дизейблить элементы форм (особенно кнопки, тк это ридонли-элементы)

Платформа
- ежегодное обновление поста Андрея Ситника о том, как подключать favicon (кажется, с каждым годом он всё короче и когда-нибудь схлопнется до 1 строки)
- никогда не будет лишним вспомнить или узнать хитрости по работе с гитом: config, blame, diff, rerere (не путать с ололо)
🔥6
#Пульс_веб_платформы 23.02.2024

Новости
- новости с полей Реакта: впиливают автомемоизацию (React Forget Compiler), Actions на клиенте, работа с <meta> из коробки, директивы "use client" и "use server", а также API для подгрузки статических файлов; всё это уже упаковано в канареечную версию вместе с докой и поедет в мажорной 19 версии
- 1 из 5 пакетов в npm на содержит ESM-модули
- анонсирован TypeScript 5.4 RC: улучшение в выводе типов, утилитарный тип NoInfer, Object.groupBy и Map.groupBy и другое

Проекты
- lucia — аутентификация во всех основных JS-рантаймах с адаптерами к БД из коробки
- react-virtuoso — либа для быстрой работы с большими списками без проблем с перфомансом (включает также «виртуальные» таблицы, сетки, бесконечный скролл, группировку со стики-хедером)
- restore-scroll — либа для восстановления позиции скролла после навигации (не только лишь body, но и любого другого элемента со скроллбаром)
- react-strict-dom — экспериментальная встройка StyleX в ReactDOM как часть движения по сближению React Native и React DOM

Статьи и демки

JS
- сравнение методов промисов all(), allSettled(), any() и race(), и от меня напоминание, что появлялись они не все сразу: all() и race() -> allSettled() -> any() в порядке исправления обнаруженных недостатков
- как работает Hot Module Replacement (HMR) в сборщиках типа Vite и почему всё это хорошо легло на ESM-модули благодаря мета-информации об импортах/экспортах (import.meta.)
- тренды React в 2024 (а скорее саммари событий 2023): Astro — самый быстрый фреймворк, аутентификация — всё ещё горячая тема, React Server Components шатко-валко адоптятся, в мире SPA новый роутер — TanStack Router, Vercel пушит React вперёд, противостояние Turbopack vs Vite и безголовые UI-либы
- и саммари результатов разработки Node в 2023: дропнули 14, 16 и 19 версии; добавили в зависимости Ada, simdutf, simdjson; обновили сайт; добавили систему пермишенов; добавили фичи: Single Executable Apps (самодостаточные Nodejs-приложения без необходимости установленной Nodejs в системе), встроенная поддержка .env, WebSocket-клиент и test runner
- визуализация распределения значений функции random и других её вариаций
- гайд по использованию localStorage: синхронный, хранит не больше 5mb, но проще IndexedDB и быстрее куки — годится для малых данных, которые не нужно постоянно читать/писать; узнал про File System API, который работает только через воркер и про Extension Storage API для хранения данных браузерных расширений
- как минимальными силами и зависимостями (только TS) поднять TS-сервер на Node c лайв-релоадом и env-переменными
- использование discriminating unions (для более декларативных и разделённых типов) и pattern matching (для укрощения развесистых условий) в TS
- анатомия итераторов в JS: встроенные и собственные, синхронные, асинхронные, прокачка объектов, чтобы сделать их итерируемыми

CSS
- наброс №1 (на серьёзных щщах) на Tailwind как маркетинговый проект, в котором идея «независимых от контента названий классов» была извращена, онбордя пользователей, а затем загоняя в vendor lock-in и заставляя привлекать в экосистему новых адептов
- наброс №2 (смешной, слово «fuck» встречается 5 раз) на Tailwind с тем же посылом: если бы в мире был только HTML и Tailwind, а потом бы появился грамотно проданный CSS(!), то все бы начали писать кипятком по концептам, которые в него встроены
- Custom Highlight API уже есть в Chrome, Safari 17.2 и даже ночном Firefox, а это значит, что выделять элементы на странице станет проще
- работа с анимациями в UI: используем доп потоки, выносим разумно в композитные слои (они потребляют доп память)

Платформа
- попытка объять в одном тексте необъятное все виды состояний, которые влияют на конечный UI: состояние приложения, данных, страницы, UI-компонентов и элементов самого браузера, параметры и настройки девайсов и состояния самого пользователя 🤯
- если вы уже оптимизировали в ассетах, что могли, можно ещё попробовать подрезать кастомные шрифты, чтобы убрать оттуда неиспользуемые символы (есть ссылки на инструменты анализа и модификации подключенных шрифтов)
🔥42👍1
#Пульс_веб_платформы 01.03.2024

Новости
- вышел Firefox 123: поддерживает Declarative Shadow DOM (теперь поддерживается всеми!), пофикшен Date.parse(), улучшены SVG-градиенты, добавлена поддержка кода 103 Early Hints HTTP для предзагрузки ресурсов
- в Mozilla выпустили MDN curriculum — учебный план для разработчиков, чтобы подтянуть базу по фронту: HTML, CSS, JS, доступность, контроль версий, перфоманс, тестирование, фреймворки, тулинг
- в Firefox 125 будет доступен Popover API
- в Vue отрефакторили систему реактивности и заменили структуры данных, чем уменьшили использование памяти на 56% и улучшили перф на 100-200% (а что, так можно было?)
- вышел Git 2.44: более лучшие ребейзы командой git replay, опция --autosquash для сквоша коммитов при обычном, неинтерактивном ребейзе, настройка хинтов и другое

Проекты
- nue — генератор статических сайтов и аппликух, дерзкий, но честный аналог Astro и Next.js
- functional-ui-kit — есть много разных UI-китов, но мало из них классно реализовано и в коде, и в Figma: этот кит из таких
- shoelace — ещё один UI-кит, но на этот раз на веб-компонентах (аккуратный, с возможностью использовать совместно с фреймворками)
- picocss — минималистичный CSS-фреймворк для стилизации (практически) голого HTML
- keyux — либа для добавления управления с клавиатуры к сайту, интегрируется с aria- и role-атрибутами в HTML

Статьи и демки

JS
- подраскрывается концепт slot-ов: в веб-компонентах, Vue и Angular: даже если не использовать их напрямую, иногда полезно иметь в голове такую ментальную модель
- оказывается, в JSDoc есть даже продвинутые конструкции типа дженериков, каста типов и implements класса (правда становится нечитаемо быстрее, чем в TS)
- как мы докатились до жизни такой: для того, что показать статический лендос нужно 10+ mb JS-кода (а для чата 50+ mb) 🤯
- сравнительный разбор Next.js и Remix, что же выбрать? (не забываем об опции, что можно не выбирать)
- сравнительный разбор HTMX и React, что же выбрать? (опять же, можно и не выбирать 😏)
- как, упрощенно, работает React Compiler, а также в целом подход к компиляции Static Single Assignment
- а что, если не присылать на клиент JSON и строить DOM, а стримить готовый HTML? Такое сложно, но возможно не только для стрима при первой загрузке страницы, но и в рантайме при переходе в View Transitions API

CSS
- как подогнать стили при использовании View Transitions, чтобы две картинки «бесшовно переходили» одна в другую
- в CSS есть константное значение infinity, и с его помощью, наконец-то, можно завершить эту битву раз и навсегда — z-index: calc(infinity), только нужно иметь в виду, что это число зависит от контекста
- псевдоэлемент ::backdrop (подложка элемента <dialog>) теперь может наследовать все наследуемые свойства родителей, и кастомные тоже (странно, что раньше не могло)
- исчерпывающий гайд по селектору :has: такая читерская неявная связь элементов одновременно и привлекает, и отпугивает своей неявностью
- когда нужно использовать data URL-ы: как обычно, it depends, надо сравнить насколько передача файла по сети добавляет больше байтов (заголовки, обмен сообщениями…), чем строка, закодированная в CSS
- когда в кастомном свойстве CSS находится невалидное значение (20px задаётся для цвета, например), то срабатывает механизм Invalid At Computed Value Time (IACVT), который приводит к откату значения до unset

Платформа
- декларативный shadow DOM пришёл, для чего же он может пригодиться: это некий «ковёр», куда можно замести детали имплементации интерфейсных частей (сомнительно, но окэй)
- полезные настройки Git: автосквош и автостэш при ребейзе, автосоздание ветки на сервере при пуше, изменение алгоритма диффов, авторебейз при пулле, автосоздание ветки main вместо master и другое
🔥12👍31👨‍💻1
#Лаборатория_веб_платформы

Анимация без стереотипов

Хоть анимация и понимается прежде всего как «оживление», в CSS кроме обычной плавной анимации, есть ещё пара типов — дискретная и никакая (свойство не анимируется).

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

Свойства с плавной анимацией — это цвета, размеры, отступы и прочие свойства, к которым можно применить плавные переходы.

Свойства с дискретнной анимацией — (внезапно) почти все остальные свойства, за некоторым исключением.

Ок, как это можно использовать. В этом кейсе я воспринимаю анимацию как механизм переключения значения свойства из одного в другое (с опциональным таймером и повторением N-раз). То есть некий setInterval(() => fn(value)), только в мире CSS.

Я полистал список всех CSS-свойств и выбрал несколько, об анимации которых я раньше не задумывался. Например, свойство content. Можно сделать «мигающий курсор»:


div::after {
animation: blink 1s infinite;
}

@keyframes blink {
from {
content: '';
}
to {
content: '|';
}
}


А учитывая, что content в качестве значения поддерживает текст, картинки, кавычки, счётчики, то можно сделать хоть целое слайдшоу 😁

Окей, ещё с помощью дискретной анимации можно собрать свою gif-ку на коленке. Это буквально быстрая смена «кадров» с картинками, как в кино. Если в секунду сменять 10 «кадров», то скорость будет достаточная для создания иллюзии непрерывного движения:


.frame {
animation: movie 1s infinite;
}

@keyframes movie {
0% {
background-image: var(--image-1);
}

10% {
background-image: var(--image-2);
}


}


Демо собрано тут.

Дальше я решил развить тему кинематографа и следующим попробовать анимировать лейаут гридов. Для построения отдельных «кадров» я решил использовать свойство grid-template-areas. Это свойство описывает раскладку грида в декларативном виде. Вот так, к примеру, будет выглядеть начальный «кадр» будущего фильма:


grid-template-areas:
". . . . a a a a a . . . ."
". . . . . . . . b . . . ."
". . . . . . . . b . . . ."
". . . . . . . . b . . . ."
". . . . c c c c c . . . ."
". . . . . . . . d . . . ."
". . . . . . . . d . . . ."
". . . . . . . . d . . . ."
". . . . . . . . d . . . ."
". . . . e e e e e . . . .";


Точками в значении grid-template-areas обозначены те области грида, которые не будут закрашены белым, а буквами — те, которые закрашиваются. По ходу «фильма» значение grid-template-areas будет принимать разные значения. А вот подменять эти значения раскладки грида будет CSS-анимация. Для этого нужно прописать раскадровку «фильма» в кейфреймах:


@keyframes movie {
0% {
grid-template-areas: …;
}
10% {
grid-template-areas: …;
}


100% {
grid-template-areas: …;
}
}


И затем задать получившуюся анимацию для грид-контейнера .field:


.field {
animation-name: movie;
animation-duration: 10s;
animation-play-state: paused;
animation-timing-function: step-end;
animation-iteration-count: 1;
animation-fill-mode: both;
}


Получившийся триллер можно найти тут.

И ещё одна деталь про неанимируемые свойства. А что будет, если в кейфреймы положить display: none? Оно применится в конце, начале или середине анимации?


.fade-out {
animation: fade-out 1s forwards;
}

@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}


Спецификация говорит, что свойство display — not animatable. И для display: none с относительно недавних пор действует особое правило: если анимация «появляет» элемент, то display включается в самом начале, а если анимация элемент скрывает, то display: none применяется в самом конце, после всех остальных транзишнов (демо тут, работает везде)!
👍6🔥6😁1
#Пульс_веб_платформы 08.03.2024

Новости
- вышел TypeScript 5.4: нового с RC версии почти ничего не подвезли, но там было много всего хорошего, можно обновляться
- вышел Parcel v2.12.0: теперь умеет прекомпилировать JS-функции в билд-тайме вместо включения в общий бандл (вдохновлено макросами из Bun); на сайте появился REPL (интерактивный редактор с отображением результата); теперь под капотом Lightning CSS бандлит CSS-файлы; возможность вручную сконфигурировать shared-бандлы
- вышел Babel 7.24.0: теперь поддерживает JSON modules imports, а также последнюю актуальную версию декораторов
- в Safari 17.4 появится поддержка нового «пропатченного» чекбокса — переключателя (<input type=checkbox switch checked> с псевдоэлементами ::thumb и ::track), также появились вертикальные контролы форм, <hr> в <select>, обновление движка Inline Layout, работающий align-content для таблиц и блоков (не только гридов и флексбоксов), @scope и :scope, Promise.withResolvers, Object.groupBy и Map.groupBy и кое-что ещё
- вышла PixiJS v8: либа для 2d анимации с десятилетней историей хорошо бустанулась по перфу, подружилась с WebGPU, изменила структуру пакета, получила обновления в графических, векторных и текстовых API
- вышла бета Million Lint: интересный концепт линтера перфоманса React-приложения, который в реалтайме показывает в коде на манер eslint количество ререндеров и время
- React Compiler aka Forget (автомемоизатор) не будет включён в релиз React 19

Проекты
- readability — JS-версия браузерного режима для чтения из Firefox: это когда остаётся только текст, а стили и оформление с баннерами уходит
- embla-carousel — минималистичная JS-карусель, без зависимостей, для доп функциональности подключаются плагины
- pkgx — запускальщик всего здесь и сейчас без установки и смс, что не умеет npx, например, мождно запустить ноду pkgx node@16 или бан pkgx bun run
- turbo repo — тула для организации более быстрой работы команд запуска и сборки в монорепах (yarn/npm/pnpm устанавливает пакеты, turbo запускает с кешированием)
- capo.js — инструмент для анализа правильности в порядке тегов в <head>: покажет, в какой последовательности расставить теги будет правильнее


Статьи и демки

JS
- 4 издание прекрасной книги про JS — Eloquent JavaScript — для программистов любых возрастов и вероисповедания
- первые отзывы о JSR — альтернативному npm пакетному менеджеру от создателей deno: пока очень нишево, привязано к deno и немного чем отличается (TS-first, only ESM-модули), но, тем не менее, конкуренция — всегда хорошо
- если вы, как и автор статьи, удивляетесь, почему у однострочных пакетов типа is-number столько скачиваний на npm, то бывает это сам автор раздувает использование своей либы через другие пакеты (naturally, пакеты с пакетами)
- как на Performance API собрать (на коленке) основные пользовательские метрики перфа: Largest Contentful Paint, First Contentful Paint, Cumulative Layout Shift, Interaction To Next Paint, Long Animation Frames

CSS
- реакт реактом, а переносить текст со строчки на строчку всё равно нужно — гайд по word-break, oveflow-wrap, hyphens, <wbr>, &shy (с последней парочкой нужно быть аккуратными)
- скролл-анимация триггерит смену кастомного свойства --animate: true, а по нему применяется Style Query @container style(--animate: true), который анимирует появившийся во вьюпорте элемент — самый блидинг из возможных эджей
- хочешь не хочешь, а рано или поздно придёт она — задача на стилизацию печатных страниц, в этом случае пригодится детальный гайд по @page и @media print в разных вариациях

Платформа
- обширный гайд по скриншотному тестированию с Playwright: самое ценное, пожалуй, что есть рецепт по запуску таких тестов в CI/CD, так как локально, как правило, скриншоты будут немного отличаться в зависимости от ОС
- опыт команды Самолёта по оптимизации перфа: есть довольно полный чеклист кандидатов на оптимизацию
- из серии «не боги горшки обжигают»: понаблюдать за редизайном сайта nodejs можно тут: новый сайт, макет, обсуждение
🔥9👍72
Нанесения пользы пост

В 2024 году исполнилось 10 лет, как я работаю в эдтехе. Те, кто знают меня давно, в курсе, что я «стоял у истоков» HTML Academy. И если вы когда-нибудь участвовали в движухах Академии, то мы с вами так или иначе «пересекались»: в тренажёрах, интенсивах или наставничестве. Сейчас я продолжаю работать в обучении, но теперь уже в школьном сегменте, и лидю продуктовую команду в одном из образовательных подразделений VK: мы делаем инструменты для учителей, методистов и учеников, чтобы они они могли учить и учиться более современно.

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

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

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

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

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

Надеюсь на вашу поддержку ❤️‍🔥
11👍5🔥5
Веб-платформа pinned «Нанесения пользы пост В 2024 году исполнилось 10 лет, как я работаю в эдтехе. Те, кто знают меня давно, в курсе, что я «стоял у истоков» HTML Academy. И если вы когда-нибудь участвовали в движухах Академии, то мы с вами так или иначе «пересекались»: в тренажёрах…»
#Пульс_веб_платформы 15.03.2024

Новости
- в опенсорс выложен Rolldown, замена Rollup на Rust для Vite: радует, что обратно совместим с Rollup, но пока ещё в активной разработке, не для продакшена
- вышла Node v21.7.0: встроенная стилизация текста console.log(util.styleText('bold', 'text')), загрузка и парсинг переменных окружения process.loadEnvFile(path) и util.parseEnv(content), поддержка многострочных значений в .env файлах
- вышел Biome v1.6: поддержка расширений файлов vue, astro, svelte; новые настройки форматтера; лёгкая миграция с Prettier
- вышел Storybook 8: встроенные визуальные тесты, поддержка React Server Components, обновления интерфейса и ускорение работы
- INP теперь официальная метрика Core Web Vitals, FID будет задепрекейчена в сентябре 2024
- Astro выпустили Astro DB, адаптированную SQL-бд на основе libsql

Проекты
- utopia — система «резиновой» типографики, отступов, сетки: позволяет задать минимальное и максимальное разрешение интерфейса, а также количество промежуточных шагов между ними и получить готовые CSS-переменные для использования
- device-simulator — симуляция девайсов в браузере для тестирования интерфейсов: не browserstack, скорее переосмысление стандартных браузерных дев-тулзов (device toolbar), помощнее, есть возможность показа нескольких устройств одновременно
- gravity-ui — каждое поколение яндексоидов создаёт собственный UI-кит, и этот выглядит очень даже прилично: есть дизайн-система, Figma и токены, позаботилились о доступности, свои иконки; остаётся только понять, какой из двух Яндексов будет его дальше овнить
- react-geiger — счётчик Гейгера для React-приложения: если что-то рендерится долго и часто, то вы это услышите
- jsoncanvas — спецификация и формат файлов JSON Canvas для имплементации бесконечных досок аля Miro, Obsidian и тд

Статьи и демки

JS
- если долго сидеть у реки, то рано или поздно по ней проплывёт заброшенный JS-проект, так как его купили крупняки, уволили сотрудников и забили (речь о Gatsby, если что)
- работа с относительными datetime-ами с помощью Intl.RelativeTimeFormat (давно поддерживаемая в браузерах)
- создание доступных компонентов форм на React: кнопки, лейблы, филдсет, плейстхолдеры, фокус и навигация с клавиаутры, отображение ошибок
- лучшие практики по использованию React Testing Library: тестирование доступности компонентов, реализация смоук-тестов
- make macros great again: теперь подход с прекомпилированными в билд-тайме кусочками JS-кода доступен не только в parcel, но и в webpack, vite и остальных

CSS
- статьи про новые CSS-фичи читаются как научная фантастика: красиво, интересно, когда-то это будет, но пока полностью не работает; вот и в этом материале рассказывается, как собрать ванильные модалки и «тосты»: <dialog> для модальных всплывашек, popover — для немодальных всплывашек, нативная стилизация элементов и показ/сокрытие, стартовая анимация @starting-style и даже anchor positioning для показа в определённом месте интерфейса
- стилизация текста: глитч-эффект, множественные тени и SVG-фильтры (осторожно, можно случайно стать КМС по text-shadow)
- небольшие рецепты из жизни по использованию :has(): изменение лейаута, если в контейнере есть определённый элемент; подсветка контейнера, если внутри есть :target; затемнение соседей при ховере на элементе
- предложение от Ли Веру сделать из кастомных свойств своего рода «объекты»: --color-green: { base: red; 100: green; 200: blue}; зная, что благодаря Ли в CSS уже появилось много ништяков, глядишь и этот тоже затащат
- использование color-mix() для создания палитр: ещё один кусок платформа откусила от sass

HTML
- для записи кавычек в тексте alt используйте одинарные кавычки ' или &quot;

Платформа
- в Chrome 122 появилась улучшенная поддержка Speculation Rules API: это переосмысленный, более выразительный и автоматизированный последователь link="prerender" с исчерпывающим описанием, какие ресурсы и в какой очерёдности прелоадить и пререндерить
- 35 лет назад Тим Бернес Ли описал «спецификацию интернета» — Information Management: A Proposal

@web_platform | Поддержать канал 🤝
🔥8👍61
#Лаборатория_веб_платформы

Конечные автоматы

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

В целом, это ок подход. Он хорошо работает на прямолинейных сценариях с несложной логикой. В случае системы со сложным поведением, если её спроектировать исходя из действий, то тогда в программе начнут появляться «режимы работы», «флаги» isSomething… и хитроспетения условий с комбинациями значений этих флагов.

Если ветвлений и состояний более 8-10, то тогда сложно создать и держать в голове ментальную модель, код на флагах и ифах превращается в плохо структурированную кашу, в которой легко допустить ошибку или логическую дыру.

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

Самый простой автомат состоит из двух состояний: выключено → включено. Чтобы перейти из одного состояний в другое вызывается action. Например, человек «спит» → вызывается action «пробудиться» → человек «бодрствует».

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

На фронте для реализации конечных автоматов есть классная либа xState. Автор либы из Microsoft, и она появилась, чтобы было проще поддерживать редактор workflows в Azure. На самом деле такое случается сплошь и рядом, когда появляется некая развесистая система, в которой могут разобраться только её авторы, так как в неё сложно въехать, объять умом целиком. И если есть общая диаграмма работы, то больше шансов, что человек с улицы сможет её раскурить.

Например, посмотрите на вот эту схему, попробуйте нажать «Simulate» в правом верхнем углу и прогоните программу от начала до конца. Так уже сходу и стало более-менее понятно, что в ней происходит?

А теперь если добавить, что из этой схемы сразу же генерится и код автомата, который можно скопировать в проект, допилить напильником и он будет работать, то получается прям бомба-пушка. Кстати, для VS Code есть визуализация прям внутри редактора, оч удобно прочекать, где куда и что идёт, это «живая документация».

Что ещё интересного есть в xState. Между состояниями могут быть guards, которые в зависимости от результата поведут в одну сторону или в другую. Поддерживается TS и асинхронная логика. Есть интеграция с React, Vue, Svelte. Также авторы стали развивать либу в сторону actor-ов: это такой архитектурный паттерн, когда система представляется неким действующим лицом, актором, которое выполняет действия, может взаимодействовать с другими акторами и тд.

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

@web_platform | Поддержать канал 🤝
👍11🔥31
#Пульс_веб_платформы 22.03.2024

Новости
- вышел Astro 4.5: новая встроенная панель аудита сайта, по View Transitions теперь можно перерендерить интерактивные части сайта, обновлён хайлайтер синтаксиса для блоков кода Shiki, поддержка отдельных CDN для разных типов файлов (и заодно ребята отпраздновали 3 года проекта)
- вышел Firefox 124: добавлена поддержка AbortSignal.any, ::first-letter и ::first-line теперь работают для SVG <text>, content-visibility: auto включено по умолчанию (скорость отрисовки сайтов станет быстрее)
- что будет, если вместе соберутся создатель и бывший CEO npm, инжиниринг-менеджер из Github и npm и разработчик из Google? Они попробуют создать более лучший пакетный менеджер (JSR был только началом)!
- выпущен vitepress — генератор статических сайтов из md на vue и vite: изначально генерится статика SSG, а после загрузки инициализируется SPA для дальнейшей навигации по сайту


Проекты
- madge — анализ и нахождение циклических зависимостей в проекте, а также постройка визуального графа зависимостей
- shiki — стильный хайлайтер кода в браузере + если вы читали документацию по TS на сайте TS, то наверняка запомнили примеры кода с тултипами-аннотациями, в которых показываются «скомпиленные» подсказки: это реализовано с помощью twoslash, который работает в тандеме с shiki, а также бонусом библиотека анимирования кода из одного состояния в другой shiki-magic-move
- downshift — базовые примитивы, заложенные в хуки, для создания доступных выпадашек на React
- spectacle — либа для создания презентаций с помощью React и JSX
- modernfontstacks — наборы шрифтов (включая системные): показывается, какие шрифты используются сейчас в браузере, какие доступны и недоступны


Статьи и демки

JS
- автомемоизация React Compiler строится на том, чтобы при выводе типов понять какие значения — примитивы и не момойзить их; собственно, и без React Compiler примитивные значения мемойзить иногда вредно
- гайд по созданию анимаций с react spring: есть примеры с простыми и сложными анимациями, впрочем простые анимации можно собрать и на коленке на CSS, разве что в либе есть встроенные «пружинные» изинги
- сравнительная таблица наличия API в разных JS-рантаймах (кроме браузера): заодно освещён рантайм WinterJS, использующий для JS движок SpiderMonkey из FF
- мастеркласс по экономии на спичках в JS-коде, если всё остальное уже оптимизировано
- как настроить среду и TS для разработки Node-приложения
- шпаргалка по типизации в React-е: если вы когда-нибудь натыкались на заковыристую типизацию, она наверняка раскрыта в этой доке

CSS
- напоминание, что отступы margin и padding недопустимы в стилях агностик-UI-компонентов, вместо них нужно использовать gap
- свойство contain, которое привносит новизну в вёрстку двухколоночного лейаута: с contain: size можно «изолировать» лейаут одного элемента от всех остальных (как будто position absolute только в потоке), а также с помощью contain: layout можно спозиционировать fixed элемент относительно родителя (но он перестанет быть fixed!)
- вместо border: 0 лучше писать border-color: transparent, чтобы не отрубать рамки для контрастного режима браузера (такое стоит делать хотя бы для @media (forced-colors: active))
- неочевидные стили для кнопок: touch-action: manipulation для отключения зума по двойному тапу, user-select: none для выключение выделения текста, ::file-selector-button для стилизации кнопки input file, аутлайн для фокуса не по клику с :focus-visible
- значение align-items: safe center для выравнивания элементов без риска обрезать их в случае появления скролла в контейнере
- ликбез по боксовой модели CSS, а также сброс неудобной дефолтной настройки box-sizing: content-box
- удобный дефолт для респонсив-размера шрифта font-size: calc(1rem + 0.25vw) вместо дурацкого переключения по разрешениям


Платформа
- если ваша монорепа разрастётся до миллиона файлов, то скорее всего в ней начнёт тормозить git; если такое произошло, выхода два: распилить монорепу или перейти на Mercurial (как сделали ребята из компании на букву F)

@web_platform | Поддержать канал 🤝
🔥7👍62
#Лаборатория_веб_платформы

Зависимости

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

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

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

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

Сам цикл может проходить быстро, если проект — это mvp со сроком жизни в месяц, или долго, когда проект долгоиграющий (Linux 👋).

Так вот, к зависимостям.

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

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

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

🍿 Часто бывает, что зависимость выбирается по популярности. Типа «миллионы юзеров не могут ошибаться».Да, у популярного проекта большее сообщество, больше контрибьюторов, но бывает, что что-то становится модным, а затем мода на это проходит. Тут можно смотреть на количество звёзд, форков, подписчиков, контрибьюторов, скачиваний (а также тренд скачиваний).

👥 Мейнтейнер(ы) и мейнтейн. Если мейнтейнер один, то вероятность стать заброшенным у проекта больше, так как бас фактор. Мейнтейн можно оценить по соотношению открытых/закрытых ишью, времени закрытия ишью, времени последнего обновления и частоте релизов.

🛠️ Качество инфраструктуры. Документация, настроенный линтер, тесты, внятное версионирование. Тут всё ясно.

⛓️ Зависимость от других зависимостей. Чем больше зависимостей, тем хуже. Энтропия увеличивается, всё остальное падает. Одиночные пакеты лучше, но есть исключение, когда речь идёт о целой экосистеме, например, ui-ките, который вы целиком используете.

🏋️ Размер. Часто даже у популярного проекта могут быть более компактные аналоги. Размер одиночных пакетов часто кореллирует с количеством зависимостей. Меньше зависимостей — меньше размер.

🧭 DX. Если проект будет минимального размера и без внешних зависимостей, но при этом него будет неудобный API, то не стоит брать его. Нервы дороже.

💸 Финансирование. Если у проекта есть платная версия или же за ним стоит зарабатывающая компания, то вероятность более длинной жизни проекта больше. Без поддержки энтузиазм быстрее заканчивается.

Как теперь это всё отслеживать, спросите вы. Для этого есть инструменты.

Оценить размер бандла, увидеть вложенные зависимости и сравнить с аналогами можно на bundlephobia (пример).

Увидеть «рейтинг» пакета можно на npms (пример). Там оценивается «качество», «популярность» и «мейнтейн». Так же можно сравнить с аналогами.

Более детально проанализировать зависимости можно на npmgraph. Например, можно оценить количество мейнтейнеров в дочерних зависимостях, актуальность зависимостей, оценку npms.

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

@web_platform | Поддержать канал 🤝
👍62