WebDev+ | Веб-разработка
8.31K subscribers
506 photos
242 videos
10 files
702 links
Присоединяйтесь к нашему каналу и погрузитесь в мир веб-разработки

Связь: @devmangx
Download Telegram
Intl.ListFormat это удобный способ собрать список в строку с учетом локали, без самописных костылей.

onst getMessage = (users) => {
const formatter = new Intl.ListFormat("en-US", {
style: "long",
// long (по умолчанию), short, narrow
type: "conjunction"
// conjunction (and), disjunction (or), unit
});
return `Hello ${formatter.format(users)}!`;
};

// Автоматически подстраивает грамматику
console.log(getMessage(["Alice"]));
// → "Hello Alice!"

console.log(getMessage(["Alice", "Bob"]));
// → "Hello Alice and Bob!"

console.log(getMessage(["Alice", "Bob", "Charlie"]));
// → "Hello Alice, Bob, and Charlie!"


По сути, он сам правильно ставит запятые, союзы и форматирует список в зависимости от языка. Удобнее, чем писать if users.length === 2 ... else ... и поддерживать всё вручную.

@WebDev_Plus
👍6
This media is not supported in your browser
VIEW IN TELEGRAM
Мигель сделал расширение для Visual Studio Code

Оно называется Better SVG и делает работу с SVG удобнее.

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

@WebDev_Plus
🔥1
В следующей версии ArkType любой Standard Schema будет валидным определением.

Миграция с Zod станет куда проще

@WebDev_Plus
🔥3
Свежая партия апдейтов по TypeScript 7. Новый нативный порт уже подъехал, и выглядит очень бодро.

Что умеет:

• проверяет типы в любом проекте
• поддерживает флаги --build и --incremental
• уже завезли полноценные фичи для редакторов
• и при этом работает примерно в 10 раз быстрее

Короче, можно пробовать прямо сейчас — версия уже в состоянии «юзабельно и приятно».

@WebDev_Plus
👍41
This media is not supported in your browser
VIEW IN TELEGRAM
Нравится этот шрифт?

Это Glass TTY VT220. Ссылка на шрифт - https://github.com/svofski/glasstty

А финальный ретро-вайб дает Cool Retro Term с эффектом послесвечения.

@WebDev_Plus
11
This media is not supported in your browser
VIEW IN TELEGRAM
Эксперимент на WebGL, который показывает, как VAT может масштабироваться прямо в браузере.

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

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

@WebDev_Plus
Ресурс для создания диаграмм на основе вашего TypeScript.

http://tsdiagram.com

@WebDev_Plus
23❤‍🔥1
В React Server Components обнаружена критическая уязвимость, описанная как CVE-2025-55182, которая затрагивает React 19 и использующие его фреймворки.

Исправление опубликовано в версиях React 19.0.1, 19.1.2 и 19.2.1. Рекомендуем немедленно обновить версию.

@WebDev_Plus
1
This media is not supported in your browser
VIEW IN TELEGRAM
Сделай свой веб-интерфейс по-настоящему динозавровым 🦖

Меняй сложный JS на пару строк CSS, чтобы собрать карусели и оживить анимации.

Уже доступно в Chrome, скоро подтянутся и другие браузеры → https://goo.gle/44L646B

@WebDev_Plus
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Используй стандартное поле Node.js imports вместо алиасов TypeScript.

@WebDev_Plus
5🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Настоящий TypeScript ещё ни разу по-настоящему не пробовали.

@WebDev_Plus
👍1
Это может стать настоящей революцией в веб-разработке!
Сейчас разрабатывают протокол проверки email-адресов (Email Verification Protocol).

Можно будет валидировать почту без отправки писем и без соцлогина.
Прямо из браузера и на 100% приватно.

Пока это только предложение, но выглядит очень интересно.

@WebDev_Plus
👍32
Просто небольшое напоминание: для описания ограниченного набора возможных состояний лучше использовать union type.
А не жонглировать кучей boolean-полей и потенциально невалидными состояниями.

@WebDev_Plus
🔥5
Chainable async API

Меня всегда интересовало, как DrizzleORM
удаётся чейнить async-функции вроде await delete() и await delete().where().

Они реализовали свой кастомный Promise, от которого наследуются все операции с БД, например PgDelete для delete в Postgres.

Чейнящиеся методы типа delete() и where() просто изменяют внутреннее состояние и всегда возвращают this (тот же самый инстанс промиса).

Поэтому, когда ты делаешь await delete(), под капотом вызывается then() этого промиса, который запускает this.execute().

Реальный запрос к базе выполняется именно в методе execute, который переопределяется в каждом подклассе.

Я считаю, что это очень крутой дизайн API, а сама идея имплементить Promise — просто отличная.

Ссылка на QueryPromise
Ссылка на PgDelete

@WebDev_Plus
Обеспечьте исчерпывающую проверку на этапе компиляции с помощью утилитарного типа Record в TypeScript

@WebDev_Plus
3
This media is not supported in your browser
VIEW IN TELEGRAM
Изучаю SwiftUI после долгой работы с React. Первое, что реально бросается в глаза — .task.

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

Удобно, например, чтобы поднять подписку через convex и сохранить данные в состоянии. Чисто и приятно 👍

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

Ещё интересно, во что это может вылиться, если везде рендерить по принципу render-as-you-fetch. Похоже, на масштабе всё же придётся активно передавать данные через пропсы?

@WebDev_Plus
Please open Telegram to view this post
VIEW IN TELEGRAM
1
This media is not supported in your browser
VIEW IN TELEGRAM
У <dialog> вместе с формами есть простой способ сделать кнопку Cancel без единой строчки JS. Помимо POST и GET, формы внутри <dialog> могут использовать метод DIALOG. В этом режиме кнопка submit просто закрывает диалог, не отправляя данные на бэкенд.

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

Когда форма внутри <dialog> отправляется методом dialog, само диалоговое окно закрывается, состояние контролов формы сохраняется, но ничего не уходит на сервер. При этом returnValue принимает значение той кнопки, по которой пользователь кликнул.

Чистый и удобный способ обработать отмену или выбор без полноценного сабмита.

Только не забудь добавить formnovalidate, чтобы кнопку Cancel всегда можно было нажать, даже если форма валится по валидации.

Подробнее на MDN: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog

@WebDev_Plus
1👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Нужны эффектные анимации для React Native?

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

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

Исходники: github.com/enzomanuelmangano/demos

@WebDev_Plus
👍1
По мне, это самый удобный вариант монорепы без отдельного шага сборки:

• pnpm workspaces и установка через workspace:*
• внутренние пакеты, которые экспортируют *.ts файлы
• опционально: pnpm publishConfig, чтобы при публикации подменять экспорты на *.js

{
"name": "@internal/foo",
"version": "1.0.0",
// Экспорт исходников TypeScript
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
// Экспорт собранного кода при публикации
"publishConfig": {
"access": "public",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js"
}
},
"dependencies": {
// Установка других внутренних пакетов из workspace
"@internal/bar": "workspace:*"
}
}


@WebDev_Plus
4
React провернул трюк на миллиард долларов. Он превратил невозможную задачу O(n³) в O(n).

Сама задача такая. Ты обновляешь UI. У React есть две виртуальные DOM-деревья: одно отражает то, что сейчас на экране, второе то, что должно быть на экране. Нужно понять, что изменилось.

Классическое решение? Сравнить каждый узел дерева A с каждым узлом дерева B, чтобы найти оптимальное преобразование. Это алгоритм вычисления расстояния между деревьями. Его сложность O(n³).

Для 1000 элементов UI это миллиард сравнений. Приложение зависает на 10 секунд каждый раз, когда ты нажимаешь кнопку. Лента Facebook? Таймлайн Instagram? Нереально.

React посмотрел на эту классическую CS-задачу и решил: а что если нам не нужен идеальный результат? Что если достаточно «достаточно хорошего»?

Они сделали два жестких компромисса.

Компромисс 1. Разные типы компонентов? Даже не сравниваем их детей. Старое поддерево выкидываем целиком. Новое создаем целиком. Ноль анализа. Мгновенное O(1) решение. Иногда расточительно? Да. Быстро? Да.

Компромисс 2. Один и тот же тип? Сравниваем только узлы на одном уровне дерева. Не ищем более удачные соответствия где-то глубже. Какие-то оптимизации теряются? Конечно. Но сложность падает с O(n³) до O(n).

В итоге миллиард операций превращается в тысячу. 10 секунд превращаются в 2 миллисекунды. Невозможное становится тривиальным.

Поэтому ленты Instagram листаются плавно. Поэтому Facebook не зависает, когда ты ставишь лайк. Поэтому твое React-приложение с 10 000 компонентов ощущается мгновенным. Поэтому веб ощущается почти нативным.

React не решил невозможную задачу. Он просто сменил задачу.

Главный вывод: стремление к идеалу убивает скорость. А скорость — единственное, что действительно важно пользователю.

@WebDev_Plus
🔥6👍32🤡2🗿1