Как научиться думать генераторами

12.05.2025, Ссылка на статью

Генераторы. Наверное это самая недооценённая фича ES6, которая привносит совершенно иной стиль написания кода и логики. Самый простой генератор можно представить как итератор алфавита:

function* genreateAlphabet() {
    yield 'а';
    yield 'б';
    yield 'в';
    // ...
    yield 'я';
}

А теперь надо разобраться: генераторы и итераторы. Генераторы – тип функций, которые возвращают итераторы, и чтобы создать итераторы сами генераторы не нужны, т.к. они просто удобный синтаксический сахар. А если вспомнить о фичах итераторов, то генераторы можно использовать вместе с деструктуризацией, что гарантирует выполнить код только необходимое количество раз:

const [firstChar, secondChar] = genreateAlphabet();
 
console.log({ firstChar, secondChar }); // { firstChar: 'а', secondChar: 'б' }

Итераторы, а точнее итерируемые протоколы, позволяют лениво исполнять код по требованию. Ленивое исполнения кода позволяет проще работать с тяжелыми вычислениями, т.к. требуется меньше времени исполнения кода на каждой итерации, чем при обработке всего массива данных за один раз. Итерируемые протоколы прекрасно работают через различные объекты, например String, Array, Map и Set, и цикл for..of также поддерживает его.

Ленивое исполнение кода

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

Генераторы могут поменять отношение к стилю написания кода, т.к. внутри них можно инкапсулировать логику, написание которой требует изменение нескольких мест. Например, Алекс МакАртур приводит следующий пример: при нажатии кнопки необходимо последовательно отобразить скользящую среднюю некоторой цены за последние пять лет, начиная с самого начала. Для работы нужно только среднее значение одного окна за раз, и могут даже не понадобиться все возможные элементы в наборе, т.к. пользователь может не кликнуть по кнопке нужное количество раз.

let windowStart = 0;
 
function calculateMovingAverage(values, windowSize) {
    const section = values.slice(windowStart, windowStart + windowSize);
 
    if (section.length < windowSize) {
        return null;
    }
 
    return section.reduce((sum, val) => sum + val, 0) / windowSize;
}
 
loadButton.addEventListener('click', () => {
    const avg = calculateMovingAverage(prices, 5);
    average.innerHTML = `Average: $${avg}`;
    windowStart++;
});

В таком коде имеется 3 части: смещение окна для скользящего среднего, функция расчёта скользящего среднего и обработка клика по кнопке, в которой объединяются предыдущие две части. Такой код можно преобразовать в генератор, что избавит код от нескольких мест объединения логики:

function* calculateMovingAverage(values, windowSize) {
    let windowStart = 0;
 
    while (windowStart <= values.length - 1) {
        const section = values.slice(windowStart, windowStart + windowSize);
 
        yield section.reduce((sum, val) => sum + val, 0) / windowSize;
 
        windowStart++;
    }
}
 
const generator = calculateMovingAverage(prices, 5);
 
loadButton.addEventListener('click', () => {
    const { value } = generator.next();
    average.innerHTML = `Average: $${value}`;
});

В варианте с генератором вся логика инкапсулирована внутри функции-генератора, и для корректной работы нужен только его экземпляр и обработка клика по кнопке. И самое важное – обработка клика больше ничего не знает о дополнительных связях, они скрыты в реализации генератора. Можно пойти дальше и избавиться даже от экземпляра генератора:

for (const value of calculateMovingAverage(prices, 5)) {
    await new Promise((resolve) => {
        loadButton.addEventListener(
            'click',
            () => {
                average.innerHTML = `Average: $${value}`;
                resolve();
            },
            { once: true },
        );
    });
}

Таким образом полезно относиться к генераторам как к инструменту, который позволяет инкапсулировать логику, избавляться от высокой связности кода и избавляться от рекурсий в коде.

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

Будущее линтеров и почему Oxlint захватывает рынок

10.06.2025, Ссылка на новость

Линтеры – незаменимые помощники в разработке приложений, которые находят ошибки и уязвимости в коде, иногда проверяют код-стайл (хоть это и не их главное предназначение), проверяют следование определенным принципам (например передачу зависимостей в хуки в React) и имеют еще много разных фич.

Основным линтером для индустрии является ESLint, который предоставляет крайне гибкую настройку статического анализа, вплоть до конфига для определенного файла. Конечно, пока ESLint становился лучше и лучше у него были соперники: JSLint, JSHint, TSLint и другие. Некоторые из инструментов до сих пор используются и развиваются, некоторые – полностью утратили свою полезность в использовании.

С недавних пор команда Oxc (Oxidation Compiler) разрабатывала свой аналог линтера на Rust, который способен соперничать с ESLint и Biome. Спустя два года нам представили первый стабильный релиз – Oxlint 1.0, который из “коробки” поддерживает более 500 правил из ESLint и некоторых популярных плагинов к нему.

Oxlint существенно быстрее ESLint – разработчики уверяют о 50-100-кратном улучшении производительности и это потрясающе! С нативным линтером скорость разработки и CI/CD повышается, ну и DX не остаётся в стороне.

Улучшение Developer Experience

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

Повышение скорости линтера положительно скажется как на скорости CI/CD, так и на опыте разработки.

Oxlint предлагает интеграцию с ESLint для миграции с него, причем можно будет оставить в ESLint только то, что не получается мигрировать. Отдельно хочется отметить вывод линтера – он шикарен 😍

Пример вывода сообщения линтера

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

Storybook 9 – тестируем компоненты в браузере

03.06.2025, Ссылка на новость

Storybook 9 – крупный релиз популярной библиотеки для представления возможных состояний поведения UI. В новой версии мы получили очень крутые возможности: различные виды тестирования компонентов, инструменты для генерации Сторей, возможность использования глобального контекста Сторей и тэги для Сторей.

Тестирование компонентов совсем не то, что ожидаешь от решения, показывающее состояние компонентов, тем не менее мы получили несколько видов тестирования внутри Storybook:

  • Юнит тестирование:
  • Тестирование компонентов;
  • Тестирование доступности (a11y);
  • Покрытие тестами.

Добавленные виды тестирования работают через Vitest, который является современным инструментом написания тестов, в том числе e2e через Playwright.

Интеграция тестирования в интерфейс Storybook’а

Добавление тэгов к Сторям позволяет намного удобнее работать с их большим количеством, показывая и тестируя только те, которые действительно необходимы.

Пример фильтрации тэгов

Дополнительными улучшениями релиза являются уменьшение веса библотеки, что уменьшает вероятность конфликтов среди используемых пакетов, а также улучшенная работа с Vue, Svelte и React Native.

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

Jest 30 – быстрее, легковеснее, лучше

04.06.2025, Ссылка на новость

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

В новом релизе подняли версии библиотек, подняли требуемую версию TypeScript, улучшили плагин для ESLint’а, дополнили поддерживаемые форматы файлов и улучшили работу с промисами, исключив ложноположительные срабатывания.

Самым ощутимым преимуществом являются оптимизации и улучшения работы с памятью, которые повлияли в основном на серверное тестирование. Улучшение ускоряет тестирование проекта на 30-50% и уменьшение используемой памяти до 80%.

Ускорение времени тестирования

Важной оптимизацией ускорения тестов является избавление от barrel-файлов (когда в index-файле импортируем много других файлов) с помощью инструментов, например babel-plugin-transform-barrels или no-barrel-file.

Дополнительными фичами нам завели улучшенную работу с ECMAScript модулями, поддержку новейшего ключевого слова using, ассиметричные проверки для массивов, повторы для тестов и ещё несколько интересных и полезных фич.

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

Firefox 139 – да здравствует Temporal

27.05.2025, Ссылка на новость

Вышел Firefox 139 и получил несколько приятных и важных обновлений. Из интересного добавили улучшенную работу с переводами страниц, причем даже внутри расширений, поправили темизацию, добавили превью ссылок с выводом полезной информации – время чтения информации и ключевые моменты из текста. Для разработки самым важным является релиз Temporal – лучшей версии Date. Также несколько улучшений получили и некоторые фичи: улучшили поиск в <details />, поправили getSelection(), улучшили работу <dialog /> и улучшили работу WYSIWYG-редакторов, поправив браузерные стили для элемента <br />.

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