Веб-страница
22.2K subscribers
2.15K photos
559 videos
2 files
4.43K links
Всё по фронтенду, бэкенду и девопсу в одном месте

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/64ai
Download Telegram
В Node.js завезли работу с ZIP без единой зависимости

Распаковать архив в Node до сих пор означало тащить adm-zip, yauzl или jszip — за одну операцию вы получали в дерево зависимостей чужой код, который потом надо обновлять и проверять на уязвимости.

В Node.js 26.8.0 от 26 августа в модуль zlib добавили ZipEntry, ZipFile и ZipBuffer. Читать архивы и разбирать их по записям теперь можно средствами платформы.

Что ещё в релизе:

— net.BlockList заметно ускорили, а TracingChannel в diagnostics_channel объявлен стабильным;
— в Cipher и Decipher включили режимы SIV и GCM-SIV: шифрование, устойчивое к повторному использованию nonce, что чаще всего и ломает AES-GCM в чужом коде;
— у StatementSync во встроенном sqlite появились close() и поддержка Symbol.dispose, то есть подготовленный запрос можно держать в using;
— MIMEType.parse разбирает тип и возвращает null вместо исключения на мусоре;
— в REPL появилась базовая подсветка синтаксиса;
— корневые сертификаты обновлены до NSS 3.126.

26.x — текущая линейка Current; в LTS zlib с ZIP приедет позже, так что в прод пока не тащите.

#nodejs
❤4👍4
Push to deploy без долларовой карты: что выросло на месте Heroku

Схему, которую Heroku придумал в 2008-м, до сих пор трудно переплюнуть: git push — и через минуту сайт живой. Vercel, Render, Railway и Netlify выросли из той же идеи, но упираются в одно и то же: оплата долларовой картой и серверы не здесь.

На Tproger вышел разбор от команды, которая четыре года собирала российский аналог: MVP за полгода, потом деплой через MCP прямо из Codex и Claude, встроенная IDE с агентом, управляемый PostgreSQL с pgVector и прокси к API OpenAI, Anthropic и Telegram, чтобы приложение в московском регионе не упиралось в блокировки. Отдельным блоком — честное сравнение с каждым из пяти конкурентов: где похоже, где хуже, где иначе.

В нашем канале Tproger разобрали подробнее.
❤1
Svelte ускорил старую реактивность, которой всё ещё много в проектах

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

В Svelte 5.57.0 поиск по Map в этом месте перевели с квадратичной сложности на линейную. Изменение относится к legacy-реактивности; для кода на рунах эта оптимизация не заявлена. Процента ускорения приложения целиком авторы не приводят: в описании релиза указана только смена сложности алгоритма.

В том же выпуске кеш сеттеров перевели с массива на Set, SSR-маркеры сворачиваются в первый push, а для единственного дочернего элемента генерируется вызов only_child. Оптимизация прежде всего касается проектов, которые сохранили старый синтаксис Svelte. На GitHub релиз собрал 13 реакций к 30 августа 2026 года.
❤1
pnpm закрыл глобальную подмену реестра через файл проекта

pnpm — пакетный менеджер для JavaScript и TypeScript с общим хранилищем пакетов на диске и строгим деревом зависимостей. В версии 12.1.0 он перестал принимать настройку scope из pnpm-workspace.yaml: закоммиченный в репозиторий файл через неё дотягивался до глобальной конфигурации разработчика.

Цепочка срабатывала на обычном pnpm login. Репозиторий держал в pnpm-workspace.yaml строку вида scope: acme, логин подхватывал её наравне с флагом --scope и дописывал маршрут @acme:registry в машинно-глобальный auth.ini — файл вне репозитория, который pnpm считает доверенным источником и который перебивает ~/.npmrc в каждом проекте на машине. В выводе команды при этом было видно только Logged in on https://registry.npmjs.org/, про scope ни слова. Дальше пакеты @acme/* резолвились с записанного реестра и в проектах, к тому репозиторию отношения не имеющих.

Теперь такой scope игнорируется, а pnpm подсказывает, где его задавать: флагом --scope, переменной PNPM_CONFIG_SCOPE или в глобальном конфиге. Поведение унаследовано от npm CLI и повторяется в pacquet, поэтому в трекере это завели обычной задачей на укрепление, без security-advisory.

Оговорка про версии: 12.1.0 и 11.25.0 вышли 29 августа под тегами next-12 и next-11, а latest на 30 августа всё ещё показывает на 11.24.0. Проверить pnpm-workspace.yaml в своих и чужих репозиториях на строку scope и заглянуть в глобальный auth.ini на лишние маршруты можно уже сейчас.
❤2
Connection Allowlist в Chrome может отключить вход через FedCM

Chrome добавил сайтам способ заранее ограничить все сетевые подключения страницы. Механизм включается добровольно через заголовок Connection-Allowlist, но после включения любое забытое направление блокируется. Под удар попадает и FedCM — браузерный протокол для кнопок федеративного входа.

В Chrome 152 владельцу сайта нужно вручную разрешить все адреса поставщика удостоверений. В список входят конечные точки .well-known, Config, Accounts, ID assertion, Disconnect и Client metadata. Запись может выглядеть так: ("https://idp.example/*" response-origin).

Без этих разрешений интеграция FedCM может повести себя не так, как ожидается, вплоть до того, что пользователь не сможет войти. Google описала этот побочный эффект отдельно. Для сайта с таким входом нужно сопоставить заголовок со всеми конечными точками провайдера до включения механизма. Пока Connection-Allowlist не задан, сетевое поведение страницы остаётся прежним.
❤1
Firefox начал догонять Chrome в предварительной загрузке страниц

Firefox Nightly получил ограниченную поддержку Speculation Rules API. Этот API позволяет прямо в HTML указать ссылки для предварительной загрузки, чтобы браузер подготовил переход заранее. В Chrome механизм работает давно, поэтому его отсутствие в Firefox оставалось одним из заметных расхождений в скорости навигации.

Сейчас реализация Mozilla покрывает только same-origin prefetch, режим immediate и правила-источники list. Браузер умеет заранее загружать ресурсы в пределах того же источника по явно заданному списку. Остальная часть API пока за рамками заявленной поддержки.

Правила задаются блоком script type="speculationrules" прямо в HTML: браузеры без поддержки его просто игнорируют, так что добавить его безопасно уже сейчас — в Chrome предзагрузка заработает сразу, а Firefox подтянется. Пока это Nightly 157: Mozilla предупреждает, что функции оттуда могут не дойти до стабильного выпуска.
❤2👍1
«В приложении удобнее» — а потом вас выкидывает в браузер

Терранс Иден описал бытовую сцену, знакомую любому, кто делает продукт с приложением и сайтом. Он хотел подписаться на календарь событий. У него была ссылка, Pixel с Android 17 и обновлённое приложение «Календарь». Добавить календарь по ссылке из приложения оказалось нельзя. Он открыл calendar.google.com в браузере в режиме desktop, подписался — и календарь тут же появился в приложении.

Задача не из сложных: кнопка, поле ввода, валидация, сохранение. Функциональность на бэкенде уже есть, приложение её просто не показывает.

Дальше автор обобщает по своему опыту разработки под Symbian, BlackBerry и Palm Pilot. Приложение тяжело обновлять: каждая новая возможность или даже новый экран требуют проверки на тысяче устройств и потом медленно расходятся по пользователям. Единственный способ это обойти — научить приложение подтягивать функциональность с сервера. На этом месте вы уже написали браузер.

Практический вывод для тех, кто отвечает за веб-версию: приложение обычно покрывает узкий сценарий, всё остальное всё равно возвращается в браузер. Значит, мобильный сайт стоит держать полнофункциональным — включая те операции, которые «по логике» должны жить в приложении. Проверить у себя просто: возьмите список действий пользователя и отметьте те, что с телефона выполняются только через desktop-режим браузера.

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

#фронтенд
👍2❤1
Браузер научится подтверждать почту без письма с кодом — разбор Email Verification API

Каждая регистрация с подтверждением почты теряет людей на одном шаге: отправили код или magic link, пользователь ушёл во вкладку почты — и не факт, что вернулся. Email Verification API — новое предложение, которое убирает этот шаг: браузер подтверждает сайту, что адрес принадлежит пользователю, не выпуская его со страницы.

Как это устроено: у адреса есть провайдер почты (gmail.com) и издатель — issuer, сервис, управляющий учётной записью (accounts.google.com). Браузер находит issuer, тот проверяет активную сессию пользователя и выпускает подписанный токен подтверждения, а сервер сайта проверяет токен у себя. Вместе с кодами исчезают и опечатки в адресах с мёртвыми ящиками, которые портят репутацию отправителя.

Статус ранний: это proposal, браузерная часть доступна через origin trial в Chrome, из почтовых провайдеров участвует Gmail. Подключать можно уже сейчас как progressive enhancement — с фолбэком на обычный код.

Разбор с примерами кода

#фронтенд
🔥4👍3👎1🤔1
Векторизуйте логотип в SVG прямо во вкладке браузера, не отправляя файл на сервер

Онлайн-сервисы просят за трассировку растра деньги или подписку, а бесплатные выдают контуры, будто их обводили во время землетрясения. Vectron решает этот случай локально: внутри открытый движок VTracer на Rust, собранный в WebAssembly и запущенный в Web Worker, поэтому картинка никуда не уходит.

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

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

#фронтенд
❤2👍1
Переведите SVG-контур в CSS-функцию shape() за один вставленный путь

Функция shape() описывает произвольный контур прямо в CSS: её можно анимировать, задавать в ней проценты и единицы вроде em, использовать в clip-path и offset-path. Проблема ровно одна: писать её руками мучительно, а все реальные контуры уже нарисованы и лежат в виде d-атрибута внутри SVG.

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

— Path to Shape переводит d из SVG-пути в синтаксис shape();
— Shape to Polygon делает обратный ход в polygon(). Пригодится как запасной вариант для браузеров без поддержки shape(), а иногда и как прямая замена: polygon() часто выходит компактнее;
— Minify Shape сжимает готовый код shape() примерно так же, как SVGO поступает с SVG.

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

#css
❤4
Firefox 155 добавил CSS-функцию progress() и Promise.allKeyed(), а на iOS браузер получил встроенный блокировщик рекламы

Для вёрстки главное: progress(value, start, end) возвращает долю от 0 до 1 между двумя границами, так что адаптивные размеры пишутся без ручного calc(); alpha() меняет прозрачность любого цвета; attr() теперь работает в любом свойстве, а не только в content; font-width заменил font-stretch, старое имя осталось псевдонимом.

В JavaScript появились Promise.allKeyed() и Promise.allSettledKeyed(): на вход объект с промисами, на выход объект с теми же ключами, без сопоставления по индексам. В сети добавили согласование QUIC v2 для HTTP/3, DevTools научились читать NDJSON построчно.

На iPhone у Firefox нет привычных расширений, поэтому Mozilla встроила блокировщик на Apple Content Blocker и EasyList прямо в настройки; выключен по умолчанию.

Примеры кода и список закрытых уязвимостей разобрали на сайте.

@tproger_web
❤3
Уберите тормозящую задержку из многоуровневого меню — её заменяет геометрия

Пользователь ведёт курсор по диагонали от пункта к подменю, задевает по дороге соседнюю строку, и содержимое переключается прямо под мышью. Обычное лечение — задержка перед сменой подменю, из-за которой интерфейс ощущается медленным. В большом меню Shop by Department на Amazon задержки нет, и промаха тоже.

Синий треугольник на схеме — предполагаемый путь курсора. Его вершины: текущая позиция указателя и правые верхний и нижний углы открытого меню. Если следующая позиция попадает внутрь, человек, скорее всего, идёт к подменю, и оно остаётся открытым чуть дольше, даже когда курсор на секунду оказался над соседним пунктом. Вышел за треугольник — подменю переключается мгновенно.

Механизм разобрал Бен Кеймeнс в 2013 году и выпустил по мотивам плагин jQuery-menu-aim, который позже применили в меню Khan Academy. Приём описывает геометрию намерения пользователя, поэтому живёт дольше любой библиотеки.

#javascript #фронтенд
👍3❤1
Cloudflare начала отключать D1 на бесплатном плане после 5 млн прочитанных строк в сутки

С 1 сентября превышение дневного лимита на Workers Free больше не проходит незаметно: запросы к базе возвращают ошибки до полуночи UTC (03:00 МСК), данные не удаляются. Лимиты прежние: 5 млн прочитанных и 100 тысяч записанных строк в сутки, 5 ГБ хранилища. Изменился только режим: раньше мягко, теперь жёстко.

Ловушка в учёте: считаются строки, которые прошёл движок, а не строки в ответе. SELECT без индекса по таблице в 100 тысяч записей съедает 100 тысяч чтений за один вызов. Сколько реально прочитал запрос, D1 показывает в meta.rows_read.

Что сделать: пройтись EXPLAIN QUERY PLAN по частым запросам и добавить индексы там, где SCAN; кэшировать горячие ответы в KV; писать батчами, лимит записей в 50 раз меньше лимита чтений.

Тарифы платного плана и чек-лист собрали на сайте.

@tproger_web
❤2
Задайте источник света один раз, и все тени на странице посчитаются сами

Ambient CSS предлагает вместо ручных shadow-sm, shadow-md и shadow-lg описать свет: направление, интенсивность ключевого и заполняющего света, оттенок, высоту. Каждый элемент получает пятислойный box-shadow: тень, блики, фаски и внутренние затемнения, и все они согласованы между собой, потому что источник один.

У элемента задаётся только высота над поверхностью, elevation от 0 до 3, и толщина, thickness от 0 до 2. Пакет @ambientcss/css работает без зависимостей в любом HTML, есть отдельная обёртка для React. Автор выложил третью версию 1 сентября, на HN у неё 94 очка. В комментариях жалуются на мобильную версию демо, так что смотреть лучше с десктопа: ambientcss.vercel.app.

#css #фронтенд
🔥4❤1👍1
Август-сентябрь — сезон поиска работы, и в IT он сейчас особенно непростой. Не всегда понятно, в какую сторону расти, страшно менять профессию, а после нескольких неудачных собеседований начинает казаться, что дело в вас.

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

Куда двигаться:
Каких спецов сейчас не хватает
Куда расти, если не хочется в менеджмент
Как попасть в QA в 2026

Собеседования и выгорание:
Почему тянет уволиться после отпуска
Как пройти собес, если стесняешься
Как пройти собес без опыта

Работа в новой компании и карьерный трек:
Что нужно знать про онбординг
Почему сеньоров не слышат
Как построить карьерный трек
Как определять грейды
Как измеряют вашу удовлетворённость работой
😁3
Manifest V2 закрыт окончательно: Google удалил из Chrome Web Store все старые расширения, включая uBlock Origin

Для авторов расширений новость не про блокировщик, а про режим совместимости: закончился период, когда V2-сборки у клиентов можно было обновлять. Chrome 138 был последней версией с корпоративным ключом ExtensionManifestV2Availability, в 139 его убрали, 31 августа расширения исчезли из магазина.

Чек-лист переезда, если он ещё не завершён: сетевую фильтрацию на declarativeNetRequest со статическими правилами в JSON; фоновую страницу на service worker с состоянием в chrome.storage, а не в переменных; никакого удалённо загружаемого кода; проверка того же пакета в Edge и Firefox, у них свои отличия в поддержке V3.

Что произошло с uBlock Origin и куда переехать пользователям разобрали на сайте.

@tproger_web
🤯2💩1
Safari наконец починил top-level await: WebKit переписал загрузчик модулей с нуля

Если модуль с await на верхнем уровне падал у вас в Safari с «Cannot access ... before initialization», это не ваш баг. WebKit сегодня рассказал, почему так было: загрузчик модулей Safari написали по черновику WHATWG Loader, заброшенному в январе 2016 года, ещё до появления async/await в языке. Top-level await из ES2022 прикрутили поверх него, и годы точечных правок проблему не закрывали.

В январе 2026-го команда удалила старый загрузчик целиком и переписала его на C++ по алгоритмам спецификации ECMAScript. В примере из блога один модуль с задержкой импортируется три раза: старый Safari завершал импорты в порядке 2, 3, 1, и два из трёх падали на неинициализированных экспортах, новый выдаёт 1, 2, 3. Проверяли тест-кейсами от команды Bun (тот же JavaScriptCore, те же баги), фаззером графов модулей со сравнением вывода с другими движками и полным набором модульных тестов test262.

Исправление уже в Safari Technology Preview 251 и бете Safari 27, в стабильный придёт с релизом 27. Обходные пути для Safari пока не убирайте, старые версии никуда не денутся. Что именно ломалось и как это чинили, разобрали подробнее.
❤3
Интерпретатор Wasm стал в 2,2 раза быстрее, и это важно там, где V8 не поможет

В браузере WebAssembly исполняет JIT, и про интерпретаторы фронтендеры обычно не думают. Но как только Wasm выходит за пределы вкладки, в плагины, edge-функции, iOS-приложения и песочницы, JIT либо запрещён, либо не помещается в память. Там живёт Wasmi, интерпретатор на Rust, и версия 2.0 по замерам проекта в 2,2 раза быстрее 1.0 по геометрическому среднему.

Внутри четыре режима dispatch вместо одного switch-loop, новое IR с аккумуляторными регистрами и структура CodeMap, где вызов функции не делает ни одного lookup. Включение SIMD больше не замедляет обычный код: в 1.0 это стоило около 8%.

Бенчмарки можно повторить из репозитория wasmi-benchmarks; сравнение с Wasm3, WAMR и Wasmtime Pulley, а также историю про Rust 1.92, который уронил CoreMark на треть, разобрали на сайте.

#wasm #перформанс
❤4
Chrome 154 beta: WebSocket в локальную сеть, постквантовые ключи в Web Crypto и табы на чистом CSS

Три вещи из беты, которые меняют код. Первая: new WebSocket(url, { protocols: "soap", targetAddressSpace: "local" }) открывает сокет к устройству в локальной сети со страницы на HTTPS, если пользователь дал разрешение Local Network Access, а имя хоста резолвится в локальный IP. Раньше это было запрещено без обходных путей.

Вторая: в crypto.subtle появились ML-KEM 768/1024, ML-DSA 44/65/87, ChaCha20-Poly1305 и гибрид X-Wing. Сквозное шифрование в веб-приложении можно строить на постквантовых алгоритмах без сторонних библиотек. Третья: scroll-marker-group: tabs делает из CSS-карусели настоящий tablist для скринридеров, активный маркер единственный останавливается по Tab, а контент неактивных панелей скрыт из дерева доступности.

Что сломается: Background Fetch начал применять CORS, AbortController передаёт reason в Response и ReadableStream. Полный список на сайте.

#браузеры #css
❤1
Ваш код не медленный, он просто держит главный поток

Скролл подёргивается, кнопка отвечает с задержкой, буквы в поиске появляются на полтакта позже. Первый рефлекс: искать медленный алгоритм. Автор разбора показывает, что чаще проблема не в скорости кода, а в том, что он занимает единственный поток, где живут и JavaScript, и стили, и layout, и paint.

Бюджет на кадр при 60 Гц около 16,6 мс, из которых практически доступны примерно 10; на 120 Гц вдвое меньше. Функция на 200 мс замораживает экран на 200 мс, и никакой бандл-оптимизацией это не лечится. Отсюда четыре приёма на самом потоке: делить длинные задачи, группировать частые, расставлять приоритеты, откладывать необязательное. И три способа увести работу с потока: на композитор, в worker, или не делать её вовсе.

Внутри интерактивные демо: чат, куда прилетают сотни сообщений в секунду, и разница между «рисовать сразу» и «отдавать поток каждые 20 сообщений». Yield не делает работу быстрее, но возвращает интерфейсу отзывчивость. Я бы прошёл этот текст перед следующим разбором INP. Разбор в блоге kciter.

#перформанс #javascript
👍5❤2