📝 Рассказ фронтендера
СтатистикаПишу про frontend (JS/TS/React), задачки с собесов с разбором и теория, советую книжки и многое другое 🤭 Contact: @atrapeznikov
- Последний пост
- 29 мая
- Последнее чтение
- 15:01
- Постов за неделю
- 0
- Всего постов
- 20
- Тип
- открытый
- Язык
- русский
- Категория
- Технологии (по похожим)
- В каталоге с
- 13 авг.
- 1/24сутки в ленте
- —
- 1/48двое суток
- —
- 1/72трое суток
- —
Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.
Посты
Ну с выходом opus 4.8, точно нет 🥵
Уууу валит
♊️Gemini CLI и Subagents На примере простого проекта с нуля разберем, как настроить и связать между собой субагентов для решения сложных задач. Читать тут
🌐 Превращаем любой сайт в приложение с помощью Pake. Из интересного: тут не используются Electron или браузеры, а какие-то нативные библиотеки, и написано это всё на Rust. В итоге объем этого приложения может быть меньше 5 МБ, у electron минимум 100 МБ... # Install Pake CLI pnpm install -g pake-cli # Basic usage - automatically fetches website icon pake https://github.com --name GitHub # Advanced usage with custom options pake https://weekly.tw93.fun --name Weekly --icon https://cdn.tw93.fun/pake/weekly.icns --width 1200 --height 800 --hide-title-bar
видео или голосовое, без подписи
Опять тут вышла самая умная. лучшая модель - Qwen 3.7-Max. И результаты тестов интересные 😁
Когда ты null null, а хотел быть [object Object] 🥲
💦Жидкое стекло в вебе: canvas, WebGPU и без CSS blur Интересная либа liquid-dom - считывает HTML-структуру страницы, переносит её в Canvas и использует WebGPU/WebGL для рендеринга физически корректных преломлений, бликов и капель в реальном времени. 🌿Github https://github.com/AndrewPrifer/liquid-dom 🌿Демка https://liquid-dom-showcase.vercel.app/
Не забываем 🗒️
😱 Вчера злоумышленник опубликовал 84 вредоносные версии в 42 пакетах @tanstack/*, которые были доступны около 20 минут, пока они не были обнаружены. Хорошая новость: атаку выявили быстро, пакеты были помечены как устаревшие. Плохая новость: если вы запускали npm install вчера и у вас есть в проекте @tanstack/* - у вас возможно есть эти вредоносные пакеты... 🥲 А как так получилось ??? Атака строилась на цепочке из трёх уязвимостей. Вредоносный PR использовал pull_request_target в GitHub Actions, чтобы отравить общий pnpm-кэш кастомным payload. Когда в следующий раз запускался релиз, он восстановил этот заражённый кэш - и код злоумышленника извлёк OIDC-токен прямо из памяти раннера, чтобы опубликовать пакет в npm, не прикоснувшись ни к одному сохранённому credential. Для npm заражённая версия выглядела на 100% легитимной. Что делал вредоносный payload: 🙈 Сбор учётных данных - AWS, GCP, Kubernetes, Vault, GitHub-токены, SSH-ключи, ~/.npmrc. Всё, до чего можно дотянуться с заражённого хоста 🙊Самораспространяющийся червь - запрашивал реестр npm в поисках других пакетов, которые поддерживает жертва, и заражал их тоже. 🙉 «Мёртвая рука» — скрипт ~/.local/bin/gh-token-monitor.sh устанавливался как systemd-сервис (Linux) или LaunchAgent (macOS) и каждые 60 секунд проверял api.github.com/user с украденным токеном. Если пользователь отзывал токен - срабатывал rm -rf ~/. Вот такие новости. https://github.com/TanStack/router/issues/7383
🤖Gemini CLI, как пользоваться, какие есть функции и пр. https://frontendtales.ru/ru/blog/gemini-cli-part-one
Вроде там и код на русском пишут....
🖥 Интересная альтернатива Firebase и Supabase - PocketBase Есть даже SDK для JS. Но есть нюанс 🤔 Please keep in mind that PocketBase is still under active development and full backward compatibility is not guaranteed before reaching v1.0.0. PocketBase is NOT recommended for production critical applications yet, unless you are fine with reading the changelog and applying some manual migration steps from time to time. @frontend_tales
DOOM в терминале через curl 😐 https://github.com/xsawyerx/curl-doom
👩💻 ➕ 👩💻 🟰❤️ https://frontendtales.ru/ru/blog/react-and-typescript
Интересненько 🌚
📹Атрибут poster для тега <video> Атрибут poster в HTML-теге <video> задаёт изображение-заставку, которое показывается до начала воспроизведения видео. Это как обложка у книги - первое, что видит пользователь. <video src="movie.mp4" poster="preview.jpg" controls> Ваш браузер не поддерживает видео. </video> ❗Что важно учитывать ☑️Размер и соотношение сторон. Лучше всего, когда размер постера совпадает с размерами видео - иначе браузер растянет или сожмёт картинку, и может появиться некрасивая рамка. Например, для видео 1920×1080 используйте постер такого же разрешения или пропорций 16:9. ☑️Вес файла. Постер загружается раньше видео, поэтому он должен быть лёгким. Имеет смысл сжать JPG или использовать WebP - пользователь увидит заставку быстрее. ☑️Отсутствие постера. Если poster не указан, браузер покажет либо пустой чёрный прямоугольник, либо первый кадр видео (поведение зависит от браузера и атрибута preload). Практический пример: <video width="800" height="450" poster="/images/preview.webp" controls preload="metadata"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video> Здесь preload="metadata" в паре с poster - хорошая комбинация: браузер не качает само видео заранее, но сразу показывает красивую заставку.
📝 Форматируем списки Intl.ListFormat - это встроенный JavaScript API для форматирования списков на естественном языке. Вместо ручной склейки строк через запятые и союзы, он делает это автоматически, учитывая правила конкретного языка. Основной синтаксис: new Intl.ListFormat(locale, options) options принимает два ключевых параметра: 🟠type — тип списка: "conjunction" (и), "disjunction" (или), "unit" (просто перечисление) 🟠style — стиль: "long", "short", "narrow" Примеры: const items = ['Яблоко', 'Банан', 'Вишня']; // Союз «и» (conjunction) — по умолчанию const conjRu = new Intl.ListFormat('ru', { type: 'conjunction' }); conjRu.format(items); // → "Яблоко, Банан и Вишня" // Союз «или» (disjunction) const disjRu = new Intl.ListFormat('ru', { type: 'disjunction' }); disjRu.format(items); // → "Яблоко, Банан или Вишня" // Простое перечисление (unit) const unitRu = new Intl.ListFormat('ru', { type: 'unit', style: 'narrow' }); unitRu.format(items); // → "Яблоко Банан Вишня" // Английский для сравнения const conjEn = new Intl.ListFormat('en', { type: 'conjunction' }); conjEn.format(['Apple', 'Banana', 'Cherry']); // → "Apple, Banana, and Cherry" Метод formatToParts - возвращает массив объектов, если нужен контроль над каждой частью: const fmt = new Intl.ListFormat('ru', { type: 'conjunction' }); fmt.formatToParts(['Кот', 'Пёс', 'Хомяк']); // → [ // { type: 'element', value: 'Кот' }, // { type: 'literal', value: ', ' }, // { type: 'element', value: 'Пёс' }, // { type: 'literal', value: ' и ' }, // { type: 'element', value: 'Хомяк' } // ] Это удобно, например, когда нужно обернуть каждый элемент в <span> с отдельным стилем. 🔵Практический кейс - вывод имён авторов: function formatAuthors(authors, locale = 'ru') { if (authors.length === 0) return 'Автор неизвестен'; return new Intl.ListFormat(locale, { style: 'long', type: 'conjunction', }).format(authors); } formatAuthors(['Толстой', 'Достоевский']); // → "Толстой и Достоевский" formatAuthors(['Толстой', 'Достоевский', 'Чехов']); // → "Толстой, Достоевский и Чехов" @frontend_tales
CSS-библиотека, которая превращает интерфейс в 8-битную игру 😈 https://nostalgic-css.github.io/NES.css/ @frontend_tales
Channel name was changed to «📝 Рассказ бэкендера»