TypeSpec - TypeScript для API

02.04.2025, Новость с анонсом

Microsoft не собираются останавливаться на успехе TypeScript’а и сделали ещё один язык в экосистему типизации – TypeSpec, но пока только Release Candidate.

Идея очень проста – ускорить разработку API, с упором на стабильность контрактов. Код, или лучше сказать – инструкции, написанные на TypeSpec генерируются в OpenAPI или JSON формат, который просто описывает то, что мы будем ожидать от контрактов, как с ними работать и т.д. Всё это очень похоже на просто Swagger, который могут описывать фронтендеры. Но TypeSpec предоставляет намного больше возможностей: например можно описать интерфейс модели и сгенерировать код для серверной реализации, и скорее всего надо будет описать только реализацию, а можно сгенерировать код для клиента, а ещё можно детально описывать поведение контрактов.

Язык в активной разработке и нам обещают больше форматов и языков для генерации. А уже сейчас можно написать свой кодген для TypeScript’а при помощи TypeSpec и Alloy (JSX для TypeScript’а) - dts-gen умер, да здравствует dts-gen!

Ссылка на оригинал

Composites

14.05.2025, Отзыв предложения Record & Tuples, Объяснение Composites

На очередном собрании TC39 было отклонено предложении Record & Tuples, которое было уже на стадии 2, основная цель которого было в том, чтобы дать нам возможность работать с иммутабельными структурами в JS, что в свою очередь позволило бы сравнивать объекты не по ссылкам, а по значениям.

Синтаксис был следующим:

const record = #{ name: 'John', age: 30 };
const tuple = #[0, 1, 2];

и мы могли бы их сравнивать обычным равенством:

console.log(#{ key: 1 } === #{ key: 1 }); // true
console.log(#{ nested: #{ key: 2 } } === #{ nested: #{ key: 2 } }); // true

Вместо Record & Tuples было внесено новое предложение - Composites, которое сейчас на стадии 1. И его цель такая же, как и в Record & Tuples за исключением того, что это не новый синтаксис, а специальный класс со своими методами:

const record = Composite({ name: 'John', age: 30 });
// НО Tuples ещё нет!
const tuple = Composite(0, 1, 2); // или возможен Composite.of()
 
const isEqual = Composite.equal(
	Composite({ nested: Composite({ key: 3 }) }),
	Composite({ nested: Composite({ key: 3 }) })
); // true
 
const isNotEqual = Composite.equal(
	Composite({ nested: Composite({ key: 3 }) }),
	Composite({ nested: Composite({ key: 3, anotherKey: 4 }) })
); // false

Composites позволяет использовать внутри значений символы и прототипы, а также вообще любые значения, которые в свою очередь будут shallowly immutable.

Ссылка на оригинал

React Router 7.5 – загружаем лениво ещё лучше

17.04.2025, Статья с объяснением

В React Router 6.4 появилась возможность определять ленивые маршруты примерно так, как если бы мы использовать React.lazy(). API ленивых маршрутов требовал от нас экспортировать два компонента loader и Component.

С новым Middleware API появится возможность исполнить что-то до момента, когда лоадер и Компонент начнут работу. С предшествующей реализацией ленивой загрузки это привело к проблеме – все лоадеры бы ждали исполнения middlewar’ов, описанных как для своих, так и для других роутов.

В React Router 7.5 представили новый подход к работе с ленивыми роутами - теперь необходимо декларативно писать лоадер и Компонент в роутере, что, по сути, не одна, а две ленивые загрузки. По задумке это позволит лениво загружать отдельные свойства роута, а не загружать их все сразу, а ещё можно это будет разделить на несколько файлов.

const route = {
  lazy: {
    loader: async () => {
      return (await import('./projects/loader')).loader;
    },
    Component: async () => {
      return (await import('./projects/component')).Component;
    },
  },
};

React Router и дальше продолжает выкатывать крутые фичи для Framework-режима, что заставляет в очередной раз задуматься о целесообразности только клиентского (SPA) Data-подхода.

Ссылка на оригинал

ViewModel в React - ещё раз про разделение приложений на клиент и сервер

16.04.2025, Статья от Дэна Абрамова

Дэн Абрамов в очередной раз опубликовал очень большую и подробную статью, в которой он предлагает пересмотреть то, как мы работаем с API и приложением на Реакте. Рассуждение сводится к тому, что, по сути, мы собираем пропы на сервере для Реакта – в таком случае почему бы не попробовать работать на сервере с ViewModel.

В статье постепенно происходит преобразование API в формат, похожий на Server Components. Во время повествованию задаются резонные вопросы о том, а как перейти на такой вариант работы, ведь команда, по разработке REST API может отказаться, ответом чему следует - BFF, что звучит очень логично (и похоже на Next). BFF могут относительно легко поддерживать фронтендеры или несколько команд, отвечающие за BFF и само клиентское представление. Конечно, BFF - не панацея, и в случае его использования команда фронтенда должна очень хорошо подтянуть знания по серверной разработке, о чем было рассказано на “Я 💛 Фронтенд 2025”. На конференции Максим Вишневский много рассуждал о надобности BFF и как с ним корректно работать, и поделился полезными ресурсами о BFF.

Наконец, имея BFF Дэн Абрамов переходит к реализации самой ViewModel в рамках Реакта и сервера и приходит к тому, как можно это улучшить и разделить на клиентские и серверные компоненты.

Помимо относительно свежего взгляда по ViewModel для Реакта мы получим много ответов на вопросы: почему это хорошо, какие есть трудности, почему Реакт 19 вышел с упором на серверную обработку.

Статья заставляет задуматься о развитии фронтенда в рамках Реакта, и, кажется Next делает всё правильно.

Ссылка на оригинал

Cookie Store API - современный подход к работе с куками

14.04.2025, Ссылка на статью, Документация на MDN

В браузере у нас есть устоявшийся способ работы с куками - document.cookie, но API по работе с ними не самое удобное:

// Записываем куку со значением темы
document.cookie = 'theme=dark; max-age=31536000; path=/';
 
// Читаем куку со значением темы
const cookies = Object.fromEntries(
	document.cookie
		.split(';')
		.map((cookie) => {
			const preparedCookie = cookie.trim();
			const delimiterPos = preparedCookie.indexOf('=');
			return [
				preparedCookie.slice(0, delimiterPos),
				preparedCookie.slice(delimiterPos + 1)
			];
		})
);
const theme = cookies['theme'] ?? 'light';

С новым CookieStore API работать с куками становится очень легко:

await cookieStore.set({
	name: 'theme',
	value: 'dark',
	expires: Date.now() + 31536000,
});
 
const { value: theme } = await cookieStore.get('theme');

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

Единственный минус - только появилось в Firefox Nightly 139 и наполовину в свежем Safari 18.4.

Ссылка на оригинал

Top Layer - виртуальный слой для работы диалогов и поповеров

22.08.2022, Новость в блоге Хрома, Статья на MDN

Недавно выходила статья о том, как можно сделать z-index, который (почти) никак не перебить – Never lose a z-index battle again. Идея заключается в том, что в calc() можно передать infinity (и не только его), умноженный на 1px, и выражение calc(infinity * 1px) просто превратится в максимальное Int32 значение.

Рецепт

Если когда-нибудь надо было сделать форму элемента в виде таблетки (радиус скругления равен половине минимума ширина или высоты), то это очень легко сделать с помощью calc(infinity * 1px).

В противовес такому решению для z-index’а существует Top Layer – специальный виртуальный слой, который всегда выше всей страницы и не обращает внимание на z-index. Но у этого слоя есть ограничения – в него попадают только фулскрин-элементы, dialog’и и popover’ы. Никак программно доступ к нему получить нельзя.

Пример работы Top Layer

Почему Top Layer важен? Если мы можем позволить себе создание тултипов и попапов на Popover API – то будут очень крутые нативные тултипы, игнорирующие большинство проблем с позиционированием и наслоением z-index’ов. Ну а для модалок подошёл бы dialog, который также себя хорошо чувствовал. Но тогда и все компоненты с попапами (напр. Select’ы), тоже стоило бы перевести на Popover API.

Надеемся, что в будущем сможем работать с Top Layer не только через диалоги и поповеры.

Ссылка на оригинал