Telegram Web Link
Дайджест за 2025-05-26 - 2025-05-30

ForesightJS
ForesightJS - библиотека, которая предугадывает траекторию мышки во время её движения. Большой вопрос, как это можно заиспользовать, но прямо на сайте либки простая демка - есть 3 варианта загрузки данных: по клику, по ховеру и по предикту. Очевидно, что кейс, когда библиотека заметила, что юзер идет к блоку, самый быстрый.

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

Snapdom
Зумеры изобрели скриншоты страниц. Ну точнее компания Zumerlab, которые делают Zumly, выложили библиотеку SnapDOM, которая делает экспорт DOM-элементов в виде картинок. По ссылке есть демка, где наглядно показаны разные кейсы.

https://github.com/zumerlab/snapdom

6 Ways Slack, Notion, and VSCode Improved Electron App Performance
Статья про основные перформанс фишки приложений на Electron. Разобраны кейсы популярных приложений: Slack, Notion, VSCode, Atom и другие

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

ESLint v9.0.0: A retrospective
В апреле прошлого года вышел Eslint 9.0.0 - мощный мажорный релиз. Команда Eslint выпустила ретроспективу по запуску новой версии eslint - выделили, что было сделано хорошо, а с чем вышли проблемки.


Announcing TypeScript Native Previews
Компилятор Typescript, написанный на Go, доступен для раннего использования. Говорят, что для большинства проектов компилятор ускорился в 10 раз. Компилятор доступен как npm-пакет и как расширение для vscode.

Играться уже можно, но следует помнить, что часть функционала еще не перенесена.

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

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
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/07/04 11:47:40

❌Photos not found?❌Click here to update cache.


Back to Top
HTML Embed Code: