Telegram Web Link
A Brief History of JavaScript

Javascript'у в этом году 30 лет! В честь этого Deno в своем блоге сделали блог-пост с короткой историей JS в виде таймлайна. Осторожно, от некоторых скриншотов в посте возникает приступ ностальгии (как, например, первая версия хрома в windows XP).

Достаточно интересное чтиво, хотя и не очень полезное.

https://deno.com/blog/history-of-javascript

#development #javascript #history
Progressive JSON

Статья от Дэна Абрамова про реализацию Progressive JSON, которая понадобилась в react server components. Это отсылка к Progressive JPEG - это jpeg, который закодирован так, что получив первые байты с данными, браузер уже может отрендерить что-то размытое. По мере дозагрузки данных картинка становится четче.

К сожалению, JSON такой формат, который не Progressive из коробки. Если вы получили первую порцию данных, то попытка сделать JSON.parse вызовет ошибку.

Например мы имеем такой json

{
header: 'Welcome to my blog',
post: {
content: 'This is my article',
comments: [
'First comment',
'Second comment',
// ...
]
},
footer: 'Hope you like it'
}


Если с сервера успеет придти только
{
header: 'Welcome to my blog',
post: {
content: 'This is my article',
comments: [
'First comment',
'Second comment'


То мы можем предположить, что скобки необходимо закрыть

{
header: 'Welcome to my blog',
post: {
content: 'This is my article',
comments: [
'First comment',
'Second comment'
// (The rest of the comments are missing)
]
}
// (The footer property is missing)
}


Но наш код может ожидать footer, и непонятно, будут ли еще какие-то данные или нет. Вместо такого подхода Дэн Абрамов предлагает реализовать стриминг JSON по уровням вложенности:
- Сначала отсылаем верхнеуровневую структуру полей
- Затем досылаем значения полей
- Если полученное поле само является объектом - данные по нему будут досланы позже

В данном примере это выглядит так
Первая отправка
{
header: "$1",
post: "$2",
footer: "$3"
}


Вторая отправка
/* $1 */
"Welcome to my blog"
/* $3 */
"Hope you like it"


Теперь клиент может собрать
{
header: "Welcome to my blog",
post: "$2",
footer: "Hope you like it"
}


Третья порция данных
/* $2 */
{
content: "$4",
comments: "$5"
}
/* $4 */
"This is my article"


Теперь клиент может собрать
{
header: "Welcome to my blog",
post: {
content: "This is my article",
comments: "$5"
},
footer: "Hope you like it"
}



Таким образом, можно досылать данные и делать прогрессивный JSON. И такой стриминг а) реализован в react server components; б) удобен для прогрессивного появления UI

В статье описано больше технических подробностей. Я лишь прошелся по верхам.

https://overreacted.io/progressive-json/

#development #javascript #JSON #abramov
Web Vitals: что это и как мы их собираем?

На выходных прошла конференция Codefest, на которой было много интересных докладов. Записей пока нет, но я опишу в канал свои заметки про пару докладов и скину пару полезных ссылок.

Доклад "Web Vitals: что это и как мы их собираем?", очевидно из названия, рассказывает про метрики производительности. Буквально на каждой конференции, где есть фронтенд, кто-то рассказывает про эти метрики. Тем не менее, хочется выделить этот доклад как очень хороший по подаче и качеству обзора метрик и инструментов

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

По поводу информации в докладе. Доклад делится на 2 части:
- Собственно про сами метрики Web Vitals - что это за метрики, какие есть рекомендации от гугла, из каких браузеров они собираются. Это ожидаемая общая часть всех докладов про перформанс
- Менее ожидаемая часть - про инструменты. Роман рассказал про то, как они в Дроме собирают эти метрики, как за ними следят и какие вообще есть инструменты для слежения за этими метриками

Расскажу подробнее про инструменты.

Самый очевидный инструмент - Lighthouse, который встроен в Chrome. Из плюсов: можно запускать локально, можно запускать в CI.
Примерно похожий отчет можно получить в Pagespeed Insights. Вставляете урл до вашего сайта и смотрите, что у него по метрикам.

Другой крутой инструмент - WebPageTest. Я им сам неоднократно пользовался. Можно использовать как облачный вариант, так и развернуть его у себя. WebPageTest - супер мощный инструмент.
Он позволяет:
- Посмотреть каждый запрос, отправляемый браузером и на что было потрачено время (установка соединения, ssl-handshake и тд)
- Вставить кастомные куки или параметры запроса
- Писать скрипты. Мы так замеряли скорость работы пользовательских сценариев
- Сравнивать несколько прогонов, причем как в виде метрик, так и в виде видео
Также есть супер похожий опенсорсный инструмент - https://www.sitespeed.io. Его я тоже использовал. Умеет практически все тоже самое что и webpagetest. Строго рекомендую

Все эти инструменты объединяет одно - вы собираете метрики производительности в "лабораторных" условиях. Легко получить 100-скор в lighthouse, если вы запускаете lighthouse на ультрамощном компьютере с ультрабыстрым интернетом и ультранизкой задержкой сети. Пока у вас по отчетам все хорошо, у пользователей все может быть плохо. Вторая группа инструментов собирает данные с юзеров, что позволяет быть уверенными, что если у вас по отчетам все хорошо, значит и у юзеров все хорошо.

Первый из таких инструментов - Chrome UX report. Есть веб интерфейс, где можно вставить ссылку на сайт и посмотреть метрики реальных юзеров за большой срок. Показывается 75-й персентиль метрик.

Другой подходящий инструмент, внезапно, Sentry. Оказывается в Sentry есть модуль для сбора Web Vitals с пользователей и Sentry умеет строить графики по этим данным.

Третий путь - собирать метрики самому. Роман показывает, как их собирать, отсылать, агрегировать - все это можно делать по-разному. Например, можно самому собирать метрики с нужной точностью, а можно взять пакет web-vitals и получить метрики через функции пакета.

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

В общем, хороший доклад. Как будет доступна запись - обязательно скину.



#development #javascript #performance #note #codefest
Дайджест за 2025-06-02 - 2025-06-05

A Brief History of JavaScript
Javascript'у в этом году 30 лет! В честь этого Deno в своем блоге сделали блог-пост с короткой историей JS в виде таймлайна. Осторожно, от некоторых скриншотов в посте возникает приступ ностальгии (как, например, первая версия хрома в windows XP).

Достаточно интересное чтиво, хотя и не очень полезное.

Progressive JSON
Статья от Дэна Абрамова про реализацию Progressive JSON, которая понадобилась в react server components. Это отсылка к Progressive JPEG - это jpeg, который закодирован так, что получив первые байты с данными, браузер уже может отрендерить что-то размытое. По мере дозагрузки данных картинка становится четче.

К сожалению, JSON такой формат, который не Progressive из коробки. Если вы получили первую порцию данных, то попытка сделать JSON.parse вызовет ошибку.

Web Vitals: что это и как мы их собираем?
На выходных прошла конференция Codefest, на которой было много интересных докладов. Записей пока нет, но я опишу в канал свои заметки про пару докладов и скину пару полезных ссылок.

Доклад "Web Vitals: что это и как мы их собираем?", очевидно из названия, рассказывает про метрики производительности. Буквально на каждой конференции, где есть фронтенд, кто-то рассказывает про эти метрики. Тем не менее, хочется выделить этот доклад как очень хороший по подаче и качеству обзора метрик и инструментов

——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
A new way to style gaps in CSS

Пост в блоге Хрома про новые возможности стилизации отступов в CSS. Раньше для решения адачи приходилось использовать разные обходные пути, которые ухудшали доступность, читаемость, перформанс и вообще были сложными. Теперь же браузеры в рамках экспериментальных фич завезли стилизацию отступов через column-rule и new-rule

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

https://developer.chrome.com/blog/gap-decorations/

#development #css
Jest 30: Faster, Leaner, Better

Анонсировал Jest 30. Обычно я про jest не пишу т.к. каждый раз сгораю от работы с ним, однако в 30 релиз завезли улучшения перформанса и несколько полезных плюшек

Остановлюсь на улучшении перформанса. Тот кто профилировал работу jest и пробовал выяснить, почему же сам describe отрабатывает за 100мс, а весь тест-ран за 10 секунд, примерно представляют насколько все плохо у jest с резолвом зависимостей. И вот в 30 jest завезли улучшения резолва модулей, который потребляет меньше памяти и ускоряет запуск тестов. На бенче от Jest сравниваются серверные и клиентские тесты. Серверные стали потреблять в 4 раза меньше памяти и ускорились на половину. Клиентские уменьшили потребление на 20% и ускорились где-то на 10. Итоговые цифры будут отличаться от проекта к проекту. Тесты в Happo ускорились с 14 минут до 9 при обновлении Jest

Я, при первом прочтении новости, сразу же попробовать обновить Jest в рабочем проекте - не вышло - что-то еще не попало в стабильный релиз. Надеюсь, за выходные все пролилось и можно будет потестить.

Что еще завезли, кроме перформанса
- Изоляция тест-файлов через VM Context
- Улучшенная поддержка ES Module
- Если запущена Nodejs с опцией вырезания типов, то Jest не будет тянуть ts компилятор для сборки файлов (когда прочел, понял, что это еще 1 пункт, который меня удивил в последней попытке профайлинга перформанса jest - чтобы загрузить конфиг jest.config.ts, jest подгружает tsc и инициализирует его)
- Поддержка using для spy. using spy = jest.spyOn(console, 'warn'); Такое использование автоматически подчистит spy в конце текущего блока
- Новая проверка - expect.arrayOf
- test.each поддерживает плейсхолдер %$ (читаемость, конечно, не учитывали. Спасибо что не эмоджи), который всталвяет порядковый номер текущего кейса.
- jest.advanceTimersToNextFrame() позволяет двинуть таймер для запуска следующих requestAnimationFrame
- Ретрай теперь конфигирируемый - можно указать время между ретраями
- setupFiles и setupFilesAfterEnv теперь умеют в асинхронные функции. Наконец-то!

https://jestjs.io/blog/2025/06/04/jest-30

#development #javascript #jest #release #performance
Part 7: Office Migration from Source Depot to Git, or how I learned to love DevEx.

История от Microsoft Office, как они мигрировали в Git. В статье очень мало технических подробностей. Тем не менее, её достаточно интересно почитать.

Почему вообще MS Office не в Git:
1. Когда MS Office переходил на систему контроля версий, git еще не существовало. Поэтому Microsoft реализовали свой CVS - Source Depot. В то время это был прорыв, но сейчас он неудобен в использовании.
2. MS Office огромный. 4000 инженеров, которые поддерживают кодовую базу на 200гб. Git не умеет или не умел работать с такими большими базами - любые изменения вносились очень долго

Почему переехать в Git сложно:
- Во первых, из-за размеров репозитория. Как я писал выше, git будет работать очень долго в таком огромном репозитории. Поэтому Microsoft в свое время сделала Virtual File System for Git - виртуальная файловая система, которая позволила клонировать не весь репозиторий, а только нужные файлы
- Переехать надо между мажорными релизами офиса - это достаточно жесткий дедлайн (я не до конца понял, откуда появилось это условие)
- Для плавной миграции необходимо уметь синхронизировать состояние кода в Source Depot и Git. Т.к. идеология систем отличается, то это нетривиальная задача. Ее решили только с 3го раза
- Надо переобучить всех разработчиков (самый легкий пункт)

Как состоялся переезд:
- Фаза 1: создали параллельный Git репозиторий, который синхронизировался с Source Depot. Работать можно было в любом из репозиториев
- Фаза 2: гарантия эквивалентности продукта. Нужно подтвердить, что сборка того, что хранится в Git, полностью эквивалентна сборке в Source Depot. Т.к. продукт старый, то у него было очень много своих нюансов при сборке, которые надо было исправить или повторить в git
- Были организованы общие каналы коммуникации и план "что делать если все пойдет не так"
- Провели обучение сотрудников, решая разные риски (страх все сломать, страх изменений и тд и тп)
- Дали возможность переехать в Git.

В итоге, почти все разработчики переехали в Git и продуктивность разработчиков (на основе внутренних опросов) стала лучше

https://danielsada.tech/blog/carreer-part-7-how-office-moved-to-git-and-i-loved-devex/

#development #git #migration #msoffice
Reactivity is easy

Простая статья про то, как можно улучшить перформанс React-компонента, если правильно использовать реактивность. Автор написла статью на основе ускорения перформанса MUI X Data Grid.

В чем проблема: есть Grid и есть Cell. Cell рендерятся внутри Grid в цикле. Когда cell кликают, она становится сфокусированной и это записывается в стейт. При обновлении стейта ререндерится весь Grid - это плохо

Код для понимания
const Context = createContext();

function Grid() {
const [focus, setFocus] = useState(0);
const context = useMemo(() => ({ focus, setFocus }), [focus]);

return (
<Context.Provider value={context}>
{Array.from({ length: 50 }).map((_, i) => (
<Cell index={i} />
))}
</Context.Provider>
);
}

function Cell({ index }) {
const context = useContext(Context);
const focus = context.focus === index;
return (
<button
onClick={() => context.setFocus(index)}
className={clsx({ focus })}
>
{index}
</button>
);
};


В статье есть интерактивная демка - зайдите потыкайте, чтоб воочию увидеть проблему

Решение простое - для хранения сфокусированности текущего компонента использовать useState внутри Cell, а весь глобальный стейт перевести на ref, в данном примере это делается через кастомный стор

Стор:
type Listener<S> = (s: S) => void;

class Store<State> {
public state: State;
private listeners: Set<Listener<State>>;

constructor(state: State) {
this.state = state;
this.listeners = new Set();
}

public subscribe = (fn: Listener<State>) => {
this.listeners.add(fn);
return () => { this.listeners.delete(fn); };
};

public update = (newState: State) => {
this.state = newState;
this.listeners.forEach((l) => l(newState));
};
}

function useSelector(store, selector, ...args) {
const [value, setValue] =
useState(() => selector(store.state, ...args));

useEffect(() =>
store.subscribe((state) =>
setValue(selector(state, ...args)))
, []);

return value;
}


Обновленные компоненты
const Context = createContext();

export function Grid() {
const [store] = useState(() => new Store({ focus: 0 }));

return (
<Context.Provider value={store}>
{Array.from({ length: 50 }).map((_, i) => (
<Cell index={i} />
))}
</Context.Provider>
);
}

const selectors = {
isFocus: (state, index) => state.focus === index,
};

function Cell({ index }) {
const store = useContext(Context);
const focus = useSelector(store, selectors.isFocus, index);

return (
<button
ref={ref}
onClick={() => store.update({ ...store.state, focus: index })}
className={clsx({ focus })}
>
{index}
</button>
);
};


На этот пример также есть интерактивная демка, где видно, что при клике на ячейку теперь только 2 ререндера - одна ячейка перестает быть фокусной, а другая - становится.

Далее автор еще улучшает свое решение, доводя его до хорошего, которое учитывает разные граничные случаи

https://romgrk.com/posts/reactivity-is-easy/

#development #javascript #react #performance
Native Nodejs HMR

Короткая статья про то, как реализовать Hot Module Replacement в свежей Nodejs с помощью новых хуков для модулей.

В NodeJS есть флаг watch, но он перезапускает все приложение при изменении файла. Идея реализации HMR следующая:
- Создается кастомный хук который
- Следит за изменением файлов
- Если файл не изменился - он будет подгружен из кеша
- Если файл изменился - он будет подгружен с диска, а также все модули, которые зависят от текущего - будут инвалидированы и исчезнут из кеша

Более подробно это все описано в статье + приложены ссылки на пакет

https://immaculata.dev/blog/native-nodejs-hmr.html

#development #javascript #nodejs #hmr #hooks
Дайджест за 2025-06-16 - 2025-06-20

A new way to style gaps in CSS 
Пост в блоге Хрома про новые возможности стилизации отступов в CSS. Раньше для решения адачи приходилось использовать разные обходные пути, которые ухудшали доступность, читаемость, перформанс и вообще были сложными. Теперь же браузеры в рамках экспериментальных фич завезли стилизацию отступов через column-rule и new-rule

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

Jest 30: Faster, Leaner, Better 
Анонсировал Jest 30. Обычно я про jest не пишу т.к. каждый раз сгораю от работы с ним, однако в 30 релиз завезли улучшения перформанса  и несколько полезных плюшек

Остановлюсь на улучшении перформанса. Тот кто профилировал работу jest и пробовал выяснить, почему же сам describe отрабатывает за 100мс, а весь тест-ран за 10 секунд, примерно представляют насколько все плохо у jest с резолвом зависимостей. И вот в 30 jest завезли улучшения резолва модулей, который потребляет меньше памяти и ускоряет запуск тестов. На бенче от Jest сравниваются серверные и клиентские тесты. Серверные стали потреблять в 4 раза меньше памяти и ускорились на половину. Клиентские уменьшили потребление на 20% и ускорились где-то на 10. Итоговые цифры будут отличаться от проекта к проекту. Тесты в Happo ускорились с 14 минут до 9 при обновлении Jest

Part 7: Office Migration from Source Depot to Git, or how I learned to love DevEx. 
История от Microsoft Office, как они мигрировали в Git. В статье очень мало технических подробностей. Тем не менее, её достаточно интересно почитать.

Почему вообще MS Office не в Git:

Reactivity is easy 
Простая статья про то, как можно улучшить перформанс React-компонента, если правильно использовать реактивность. Автор написла статью на основе ускорения перформанса MUI X Data Grid.

В чем проблема: есть Grid и есть Cell. Cell рендерятся внутри Grid в цикле. Когда cell кликают, она становится сфокусированной и это записывается в стейт. При обновлении стейта ререндерится весь Grid - это плохо

Native Nodejs HMR 
Короткая статья про то, как реализовать Hot Module Replacement в свежей Nodejs с помощью новых хуков для модулей.

В NodeJS есть флаг watch, но он перезапускает все приложение при изменении файла. Идея реализации HMR следующая:

——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
Announcing Rolldown-Vite

Vite меняет сборщик на Rolldown. Rolldown написан на Rust и является частью экосистемы Oxc, в которой есть Oxlint, о котором я недавно писал.

Для удобной миграции сделан отдельный пакет rolldown-vite. Достаточно его поставить и для большинства проектов никаких больше правок не нужно. Однако, могут быть случаи, когда потребуются ручные правки или когда поведение изменилось. В этом случае поможет гайд по миграции

Основные причины переезда:
- 1 инструмент вместо esbuild+rollup
- Ускорение работы. Rolldown быстрый
- Дополнительные фичи, которые доступны в Rolldown, но недоступны в esbuild+rollup

Как ускоряется сборка в реальных проектах:
- Gitlab - ускорение с 2х с половиной минут до 40 секунд и уменьшение потребления памяти в 100 раз
- Excalidraw ускорил сборку в 16 раз (до 1.4 секунды)
- PLAID inc - также ускорили сборку в 16 раз
- Appwrite ускорили сборку и уменьшили потребление памяти в 4 раза
- Particl ускорили сборку в 10 раз

В общем, если вы используете Vite - рекомендую попробовать. Я свой пет проект постараюсь перевести в ближайшее время.

https://voidzero.dev/posts/announcing-rolldown-vite

#development #javascript #vite #rolldown #esbuild
Отзыв на обучение в Стратоплане

Продолжаю серию отзывов про обучение в Стратоплане. На этот раз отзыв на модуль "Работа с людьми".

Начнем с прикольных вещей - вы знали, что прерывать задачу может быть эффективнее, чем ее завершать?

В психологии есть Эффект Зейгарник-Овсянкиной. Его суть в том, что когда мы прерываем действие, не достигая результата, то внутри нас возникает острая потребность в завершении действия.

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

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

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

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

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

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

Всегда интересно узнать про то, что ты много раз наблюдал, но не замечал - когда отходишь от чего-то интересного и незавершенного и потом постоянно думаешь об этом, а потом возвращаешься и как будто не прерывался. Это могут быть и пет-проекты, и рабочие задачи, и игры (в последний раз я так играл в Age of Wonders 4 - к сожалению нельзя играть 12 часов в сутки, поэтому приходилось прерываться прямо по середине сценария, но возвращаться было очень легко)

Еще из прикольных вещей с обучения: лайфхак для карьерного роста:
- Берете успешное резюме с должности, на которую вы претендуете
- Пишете свое честное резюме
- Смотрите разницу - это то, куда вам надо расти

В целом, в поиске разницы между состояниями А (текущая должность) и Б (желаемая должность) нет ничего нового, но подход с резюме одновременно простой и интересный.

Из того, что не понравилось в модуле: модель Батерейка и шкалы мотивации.

Модель Батарейка - если вы когда то видели ретроспективу, где в начале надо указать свой "заряд" батарейки - то вы в целом понимаете что это. Но, оказывается, есть более менее описанная модель мотивации "Батарейка". Проблема в ней в том, что непонятно как её использовать т.к. все нормальные люди имеют заряд 30-50%, а остальные - либо выдающиеся люди, либо какие-то явные нарушения. Когда разбирались в примерах, оказалось что можно быть по поведению на 60+, а внутри 30-, хотя батарейка основывается на поведении. Короче, вообще не понял как использовать

Также была дана модель для развития сотрудников через 2 шкалы: шкала компетенций и шкала мотиваций. Обе шкалы от 0 до 10. Почему обе шкалы равнозначны и как сравнивать мотивации людей - непонятно. Цифры дают ощущение, что это какая-то строгая модель - но это не так. Лучше бы просто давали шкалы в виде классификаций - эксперт, опытный, новичок.





#stratoplan #note
A JavaScript Developer's Guide to Go

Недавно я постил ссылку на гайд по C# для JS-разработчиков. Здесь похожий контент, но теперь гайд по Go. Т.к. Go простой язык, то и гайд достаточно короткий - занимает ровно 1 страницу.

Гайд показывает основные концепции и показывает сходства и отличия Go и TS

https://prateeksurana.me/blog/guide-to-go-for-javascript-developers/

#development #javascript #go
Дайджест за 2025-06-23 - 2025-06-25

Announcing Rolldown-Vite
Vite меняет сборщик на Rolldown. Rolldown написан на Rust и является частью экосистемы Oxc, в которой есть Oxlint, о котором я недавно писал.

Для удобной миграции сделан отдельный пакет rolldown-vite. Достаточно его поставить и для большинства проектов никаких больше правок не нужно. Однако, могут быть случаи, когда потребуются ручные правки или когда поведение изменилось. В этом случае поможет гайд по миграции

Отзыв на обучение в Стратоплане
Продолжаю серию отзывов про обучение в Стратоплане. На этот раз отзыв на модуль "Работа с людьми".

Начнем с прикольных вещей - вы знали, что прерывать задачу может быть эффективнее, чем ее завершать?

A JavaScript Developer's Guide to Go
Недавно я постил ссылку на гайд по C# для JS-разработчиков. Здесь похожий контент, но теперь гайд по Go. Т.к. Go простой язык, то и гайд достаточно короткий - занимает ровно 1 страницу.

Гайд показывает основные концепции и показывает сходства и отличия Go и TS

——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
Релиз Prettier 3.6

Вышел Prettier 3.6, в котором за экспериментальным флагом можно запустить более быстрый CLI. Этот cli, судя по всему, разрабатывали полтора года, т.к. текущий пост ссылается на предыдущий про ускорение CLI от ноября 2023-го года

На сколько стало быстрее и за счет чего - пока не описано. Еще из обновлений - можно подключить плагин OXC, который подключает быстрый oxc парсер для JS и TS

Кроме этого сделаны различные доработки в разных языках. Если смотреть на JS и TS, то часть изменений это поддержка нового синтаксиса или депрекрейт экспериментального, а часть, как обычно, стабилизация и улучшение единообразия работы форматтера - то комментарии, то отступы в каких-то эдж-кейсах вставали не одинаково.



https://prettier.io/blog/2025/06/23/3.6.0

#development #javascript #prettier #releaseNotes #performance
Ecma International approves ECMAScript 2025: What’s new?

25 июня зафиксировали стандарт ECMAScript 2025.

Что зафиксировали: импорт-атрибуты (нужны для JSON-модулей), хелперы для итераторов, новые методы Set, немного улучшили RegExp, добавили Promise.try и поддержки 16-битных чисел с плавающей точкой

Import attributes
Добавили в язык возможность импортировать не JS код. Для этого понадобилось добавлять синтаксис, который бы объяснял движку или рантайму, что сейчас будет импорчено
import configData1 from './config-data.json' with { type: 'json' };

// Dynamic import
const configData2 = await import(
'./config-data.json', { with: { type: 'json' } }
);


Хелперы для итераторов
Для массивов есть удобные методы, а для итераторов - нет. Решили исправить эту несправедливость и перенесли часть методов на итераторы
const arr = ['a', '', 'b', '', 'c', '', 'd', '', 'e'];
assert.deepEqual(
arr.values() // creates an iterator
.filter(x => x.length > 0)
.drop(1)
.take(3)
.map(x => `=${x}=`)
.toArray()
,
['=b=', '=c=', '=d=']
);


Адаптированные для итератора методы
- iterator.filter(filterFn)
- iterator.map(mapFn)
- iterator.flatMap(mapFn)
- iterator.some(fn)
- iterator.every(fn)
- iterator.find(fn)
- iterator.reduce(reducer, initialValue?)
- iterator.forEach(fn)

Также сделали аналоги slice
- iterator.drop(limit) возвращает новый итератор без первых limit значений (по сути slice(limit))
- iterator.take(limit) возвращает новый итератор с первыми limit значениями (по сути slice(0, limit))

Еще сделали удобный метод для преобразования итератора в массив iterator.toArray()

Новые методы Set
- Создание нового сета из двух существующих:
- Set.prototype.intersection(other) - пересечение - только те значения, которые есть в обоих наборах
- Set.prototype.union(other) - объединение - значение из обоих наборов
- Set.prototype.difference(other) - позволяет достать множество, которое получится если из множества А убрать все элементы множества Б
- Set.prototype.symmetricDifference(other) - позволяет достать множество, которое содержит элементы которые входят только в одно из множеств
- Определение отношения наборов:
- Set.prototype.isSubsetOf(other) - является ли набор А - подмножеством набора Б
- Set.prototype.isSupersetOf(other) является ли набор А - надмножеством набора Б
- Set.prototype.isDisjointFrom(other) - возвращает true, если у множеств нет пересечений

assert.deepEqual(
new Set(['a', 'b', 'c']).union(new Set(['b', 'c', 'd'])),
new Set(['a', 'b', 'c', 'd'])
);
assert.deepEqual(
new Set(['a', 'b', 'c']).intersection(new Set(['b', 'c', 'd'])),
new Set(['b', 'c'])
);
assert.deepEqual(
new Set(['a', 'b']).isSubsetOf(new Set(['a', 'b', 'c'])),
true
);
assert.deepEqual(
new Set(['a', 'b', 'c']).isSupersetOf(new Set(['a', 'b'])),
true
);



Улучшения RegExp
RegExp.escape(text) позволяет вставить текст в RegExp и быть уверенным, что вставленный текст не сломает RegExp

 const regExp = new RegExp(
`(?<!“)${RegExp.escape(text)}(?!”)`,
'gu'
);


Флаги теперь можно применять не ко всему RegExp, а к отдельным группам
 /^x(?i:HELLO)x$/.test('xHELLOx') // true


Можно использовать одинаковые имена для групп
const RE = /(?<chars>a+)|(?<chars>b+)/v;


Promise.try
Promise.try немного упрощает создание промиса с синхронными функциями
 return Promise.try(() => {
const value = syncFuncMightThrow();
return asyncFunc(value);
});


Если функция syncFuncMightThrow бросит исключение, то Promise.try вернет реджектнутый промис.

Работа с 16-битными числами
По дефолту числа в JS представлены 64-битными числами с плавающей точкой. Но есть кейсы, когда необходимо вести все вычисления в 16 или 32-битных числах. В JS добавили разные хелперы для работы с такими числами, например Math.f16round делает округление в пространстве 16-битных чисел

console.log(Math.f16round(2**16)) // Infinity

console.log(2**16) // 65536


https://2ality.com/2025/06/ecmascript-2025.html

#development #javascript #ecmascript #releaseNotes
What's coming to JavaScript

После релиза нового EcmaScript в блоге Deno описали пропозалы, которые обсуждаются сейчас в TC39.

Stage 4
using уже доступен в Chrome, Firefox и Deno. using позволяет описать использование ресурса, который будет освобожден в конце текущего скоупа.
Например, нам нужно открыть файл для чтения и закрыть его после чтения. Вместо ручного закрытия, можно использовать новый Symbol.dispose и using

class FileHandle {
constructor(name) {
this.name = name; /* open file... */
}
[Symbol.dispose]() {
console.log(`${this.name} closed`); /* close file */
}
}
function readFile() {
{
using file = new FileHandle("data.txt");
// read from file...
}
// file.[Symbol.dispose]() was called here automatically
}
readFile(); // logs "data.txt closed"


Array.fromAsync - позволяет собрать массив из асинхронного итератора
async function* generate() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
}
const nums = await Array.fromAsync(generate()); // [1, 2]



Error.isError - метод, позволяющий проверять аргумент на то, является ли он инстансом ошибки. Этот метод нужен ровно по той же причине, по которой нужен Array.isArray - не всегда проверка err instanceof Error возвращает true на ошибки т.к. некоторые ошибки могут быть созданы в другом пространстве. Я, честно сказать, плохо помню всю эту тему с Realm'ами в JS, но помню что теоретически ошибка или массив могут быть сгенерированы в другом пространстве и прилететь в текущее.

Stage 3

Immutable ArrayBuffer
Как понятно из названия, добавлены методы для преобразования буферов в неизменяемые и наоборот
let buf = new ArrayBuffer(100);
let imm = buf.transferToImmutable();
// buf is now detached (byteLength 0), and imm is a new immutable ArrayBuffer of length 100
console.log(buf.byteLength, imm.byteLength); // 0, 100

// attempting to modify imm will throw a TypeError
imm[0] = 1; // TypeError: Cannot modify an immutable ArrayBuffer



Stage 2
Random.Seeded - добавляет возможность генерировать псевдо-случайные числа из сида.
const prng = new Random.Seeded(42);
for (let i = 0; i < 3; i++) {
console.log(prng.random());
// prints the same sequence on every run given seed 42
}


Number.prototype.clamp - функция позволяет привести число к промежутку. Например, мы делаем какой-то функционал, где стоимость услуги зависит от объема, но градация скидки за объем начинается от, например, 10 (без скидки), и заканчивается на 1000 (т.е. клиенты с объемом в 1000 и 1100 получат одинаковую скидку за объем). clamp позволяет как раз привести входное число к нужному диапазону

(5).clamp(10, 1000); // 10
(500).clamp(10, 1000); // 500
(1000).clamp(10, 1000); // 1000
(1100).clamp(10, 1000); // 1000


Stage 1
В Intl.NumberFormat добавлена возможность выводить висящие нули
new Intl.NumberFormat("en", {
minimumFractionDigits: 2,
trailingZeroDisplay: "auto",
})
.format(1.5); // "1.50"



Proposal-inspector - попытка стандартизировать сравнение объектов и вывод результата в человекочитаемом виде. Необходимо для стандартизации инструментов разных платформ (Node, Bun) и было бы полезно для тестовых фреймворков

Random Functions - добавляет пространство Random с вспомогательными функциями, которые обычно пишутся на коленке в каждом проекте
// Случайное число из диапазона
Random.int(-5, 5); // -1
Random.number(0, 10); // 8
Random.number(0, 5, 0.1); // 1.1 (0.1 - шаг)

// Выберет 2 случайных из массива
const name = Random.take(["Alice", "Bob", "Carol"], 2); // ['Alice', 'Bob']

// Выберет 1 случайный из массива
Random.sample(["Alice", "Bob", "Carol"]); // 'Bob'
// Перемешивание массивов
Random.shuffle([1, 2, 3, 4]); // [4,2,1,3]
const shuffled = Random.toShuffled([1, 2, 3, 4]);



https://deno.com/blog/updates-from-tc39

#development #javascript #ecmascript #deno #proposal
Announcing LogTape 1.0.0

Вышел релиз 1.0.0 библиотеки для логирования LogTape. Выглядит интересно. В фокусе проекта: перформанс, стабильность, интеграция с существующими решениями.

В первую очередь фокусируются на перформансе и возможности писать в консоль, не блокируя приложение. У меня был такой кейс, когда мы уронили прод из-за обильного использования console.log - до этого кейса я не задумался над тем, как вывод в консоль может влиять на перформанс приложения

Также в LogTape сделаны интересные интеграции как с внешними тулами, так и с экосистемой. Интеграции с внешними тулами это интеграции с AWS CloudWatch, Windows Event Log. А для экосистемы сделаны адаптеры для winston и pino - популярных библиотек для логирования

Пример интеграции с winston

Простая интеграция
/ Quick setup with winston
import "@logtape/adaptor-winston/install";

Кастомизируемая
// Or with custom configuration
import { install } from "@logtape/adaptor-winston";
import winston from "winston";

const logger = winston.createLogger({/* your config */});
install(logger);



В общем, выглядит интересно, стоит присмотреться

https://hackers.pub/@hongminhee/2025/announcing-logtape-1-0

#development #javascript #library #logging
Рекомендую вакансию: SkyPro ищет тимлида

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

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

Итак, в небольшую команду разработки SkyPro ищут тимлида. У ребят хорошая культура разработки - реальный agile (работа микро-итерациями), реальный CI\CD (реальный - это когда код разработчика постоянно интегрируется в общий бранч, а не только когда все завершено и протестировано и, дай бог, раз в день), пишут автотесты, поощряют автономность и самостоятельность, используют AI везде где можно.

SkyPro занимается образованием в IT. Построили успешный бизнес на идее "войти в айти", как яндекс практикумы, скилбоксы и другие. Команда занимается разработкой платформы для обучения, но также я точно знаю, что команда сама периодически участвуют в доработке своих курсов.

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

По тех. стеку - angular и php.

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

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

В треде пишите любые вопросы - вам ответит чел из skypro

https://vacancies.skyeng.ru/dev-team-lead-skypro?utm_source=msosnov

#note
Дайджест за 2025-06-30 - 2025-07-04

Релиз Prettier 3.6
Вышел Prettier 3.6, в котором за экспериментальным флагом можно запустить более быстрый CLI. Этот cli, судя по всему, разрабатывали полтора года, т.к. текущий пост ссылается на предыдущий про ускорение CLI от ноября 2023-го года

На сколько стало быстрее и за счет чего - пока не описано. Еще из обновлений - можно подключить плагин OXC, который подключает быстрый oxc парсер для JS и TS

Ecma International approves ECMAScript 2025: What’s new?
25 июня зафиксировали стандарт ECMAScript 2025.

Что зафиксировали: импорт-атрибуты (нужны для JSON-модулей), хелперы для итераторов, новые методы Set, немного улучшили RegExp, добавили Promise.try и поддержки 16-битных чисел с плавающей точкой

What's coming to JavaScript
После релиза нового EcmaScript в блоге Deno описали пропозалы, которые обсуждаются сейчас в TC39.


Announcing LogTape 1.0.0
Вышел релиз 1.0.0 библиотеки для логирования LogTape. Выглядит интересно. В фокусе проекта: перформанс, стабильность, интеграция с существующими решениями.

В первую очередь фокусируются на перформансе и возможности писать в консоль, не блокируя приложение. У меня был такой кейс, когда мы уронили прод из-за обильного использования console.log - до этого кейса я не задумался над тем, как вывод в консоль может влиять на перформанс приложения

Рекомендую вакансию: SkyPro ищет тимлида
Я не размещаю вакансии, рекламу или промо всяких разных материалов т.к. это сразу снизит качество контента - я банально не могу быть уверен в контенте, который мне приносят, а отвечать за него - мне.

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

——————————————

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
2025/07/07 06:23:27
Back to Top
HTML Embed Code: