Telegram Web Link
Максим Соснов. Двое за ноутом, не считая copilot’а, или Как внедрить парное программирование

Мое выступление на codefest про парное программирование и его применение в нашей команде.

Весьма обзорный доклад (как почти и все у меня). Посмотрите, если вы про парное программирование слышали только отдаленно или если вам интересна практика, но вы не знаете с какой стороны к ней подойти. Если вы уже применяете парное программирование в команде, то вряд ли в этом докладе для вас будет что-то новое (все таки целевая аудитория доклада как раз те, кто не применяет)

Для меня откровением оказалось, что самая скучная (по моему мнению) часть доклада являлась самой интересной для многих слушателей. Повод, конечно, сделать отдельный пост про парное программирование, но на сайд-активности остается мало времени, а их много :С

https://www.youtube.com/watch?v=T14D2GVHGgw&list=PL8761XQAJnrb2Z-Q50OocgfyAyAMlDDEs&index=14
https://vk.com/video/@codefest/playlists?z=video-65336816_456239569%2Fclub65336816%2Fpl_-65336816_29

#development #pairProgramming #extremeProgramming #codefest #speech
👍12
Давно не делился папками с телеграм каналами 🙃

Тут завели новую тг-папку, называется "Архитектура", но это обманчивое название - там много каналов от фронтенд-разработчиков (в том числе этот канал) 😁

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

https://www.tg-me.com/addlist/Pk3F9xr4il5lZTc6
🔥5👎3👍1
Please Stop Using Barrel Files

Статья про вред от использования barrel-файлов

Немного контекста, что такое barrel file. Это когда у нас есть папка dir с файлами someFile1.ts и someFile2.ts.
Мы могли бы импортировать их так

import { someFunction } from 'dir/someFile'
import { someFunction2 } from 'dir/someFile2'


Но есть паттерн barrel (в переводе бочка) файлов, когда мы в папке dir создаем index.ts, который ре-экспортит все внутренние сущности

dir/index.ts
export { someFunction } from './someFile'
export { someFunction2 } from './someFile2'


Использование
import { someFunction, someFunction2 } from 'dir'


Какие минусы выделяет автор у таких файлов:

Первый минус - циклические импорты. Тут автор дает какой-то странный юзкейс, когда мы в файлах внутри папки dir также делаем все импорты через index. В этом случае index импортирует модули, а модули импортируют другие модули через index. Это максимально странное использование паттерна

Второй минус уже более близок к реальности - barrel-file ведут к замедлению перформанса инструментов сборки. Когда в тулинге сборки появилась оптимизация по выбросу неиспользуемых экспортов, в сознании разработчиков это отпечаталось как "если я не использую экспорт, его стоимость для сборки - нулевая". Однако, это не так. Если вы используете jest для юнит-тестов, то вы напрямую можете столкнуться с этой проблемой, т.к. jest не занимается три-шейкингов и если вы импортируете 1 маленькую функцию из barrel-файла - вы, на самом деле, импортируете весь модуль.

Автор приводит в пример свой проект, где замена импортов на прямые ускорила сборку на 70% (также могу подтвердить такое по своему опыту борьбы с jest).

Также автор приводит в пример опыт Next.js, которые для борьбы с этой проблемой сделали фичу optimizePackageImports, которая заменяет импорты из barrel-файлов на прямые импорты во время сборки

Не смотря на минусы, такие файлы могут быть полезны, если используются по назначению: для организации публичного API библиотеки

https://tkdodo.eu/blog/please-stop-using-barrel-files

#development #javascript #barrelFile
👍21🔥31
Optimizing SPA load times with async chunks preloading

Небольшая статья про оптимизацию загрузки асинхронных чанков в SPA-приложении.

В чем вообще проблема: как правило, если у вас SPA, у вас есть роутинг, в который асинхронными чанками подключены страницы.

Если сильно утрировать, то в коде проекта есть что-то типа:
const routes = {
'/': import('pages/main'),
'/search': import('pages/search')
}


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

Примерно та же проблема есть и при навигации. Пользователь делает действие, которое должно перекинуть его на страницу search и снова ждет загрузки скрипта.

Что предлагает автор: надо написать свой плагин для сборщика, который будет инжектить скрипт загрузки нужного чанка. Звучит мощно

5 простых шагов для реализации идеи:
- Добавляем имена чанкам import(/* webpackChunkName: "main" */ "./pages/main")
- Пишем плагин (в случае автора - плагин для RSPack)
- Плагин получает стату сборки и из нее достает ссылку до именованного чанка
- В проекте заводится способ нахождения имени чанка по текущему урл
- Плагин инжектит скрипт в head, который на основе window.loocation.href находит нужное имя чанка и инжектит ссылку до чанка в link rel=preload.

Таким образом достигается ускорение загрузки страниц.

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

https://mmazzarolo.com/blog/2024-08-13-async-chunk-preloading-on-load/

#development #javascript #performance
👍9
React Switchboard

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

В общем, готовая библиотека на случай, если вам нужен быстрый способ настроить контекст или окружение.

https://github.com/coryhouse/react-switchboard

#development #javascript #react #library
👍8🔥3
Дайджест за 2024-11-05 - 2024-11-08

Максим Соснов. Двое за ноутом, не считая copilot’а, или Как внедрить парное программирование
Мое выступление на codefest про парное программирование и его применение в нашей команде.

Please Stop Using Barrel Files
Статья про вред от использования barrel-файлов.

Optimizing SPA load times with async chunks preloading
Небольшая статья про оптимизацию загрузки асинхронных чанков в SPA-приложении.

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

В общем, готовая библиотека на случай, если вам нужен быстрый способ настроить контекст или окружение.

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

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
👍91
Crafting a 13KB Game: The Story of Space Huggers

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

Данная статья - как раз одна из таких. Автор одной из игр делится тем, как создать такую игру. Здесь не так много технических деталей, связанных с JS, но зато очень много про сам гейм-дизайн и про принятие решений.

Хорошее чтиво на вечер

https://frankforce.com/space-huggers-how-i-made-a-game-in-13-kilobytes/

#development #javascript #game
👍11
Announcing Official Puppeteer Support for Firefox

Наконец-то появилась официальная поддержка firefox в puppeteer. Теперь можно использовать puppeteer для работы с firefox.

Из интересных технических деталей в статье: было два основных варианта для реализации интеграции с puppeteer:
- Использовать WebDriver BiDi протокол. Это штука, которая была стандартизирована еще w3c и поверх нее, как я помню, работает selenium
- Использовать CDP (chrome dev-tools protocol), по которому puppeteer работает с хромом, т.е. по сути надо имплементировать CDP в firefox; Или сделать интеграцию puppeteer с RDP - это аналог CDP но для firefox

Сначала попробовали сделать экспериментальную и ограниченную поддержку CDP в firefox. Но решили что лучше идти в сторону Webdriver BiDi, как более стандартизированная и кросс-браузерная штука.

https://hacks.mozilla.org/2024/08/puppeteer-support-for-firefox/

#development #javascript #puppeteer #firefox
🔥2
Common Causes of Memory Leaks in JavaScript

Хорошая статья про утечки памяти.

Статья начинается с разбора типов памяти в V8.

Есть:
- RSS (Resident Set Size) - все используемая память
- Heap Total - Память выделенная под JS-объекты
- Heap Used - Память, используемая JS-объектами
- External - Память под С++ объекты, прилинкованные к JS объектам
- Array Buffers - Память выделенная под ArrayBuffer. Используется для хранения бинарных данных

Получить текущее использования можно так

console.log('Initial Memory Usage:', process.memoryUsage());


Initial Memory Usage: {
rss: 38502400,
heapTotal: 4702208,
heapUsed: 2559000,
external: 1089863,
arrayBuffers: 10515
}



Основные причины утечки памяти:
- Плохая работа с данными. Например, когда данные уже не нужны, а мы все еще их храним (в глобальной переменной или в замыкании)
- Плохая работа с event listeners. Если их не удалять, после того как они стали не нужны, они будут также держать объекты и защищать их от сборки
- Замыкания
- Некорректной использование bind. Например, мы забиндили метод к this, но в методе this не используется. В этом случае из-за bind GC не сможет собрать то, на что забинжена функция (this).
- Циклические зависимости (пример в статье интересный - this.reference = this;

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

Сначала надо запустить процесс с записью лога node --prof server.js
Затем необходимо прочитать лог node --prof-process isolate-0x140008000-42065-v8.log > processed-profile.txt

Что выдаст в файл человеко-читаемый профайлинг, где описано, какие функции запускались, сколько времени заняли, какие объекты аллоцированы

https://www.trevorlasn.com/blog/common-causes-of-memory-leaks-in-javascript

#development #javascript #performance #memoryLeak
👍183🔥3😱1
How we shrunk our Javascript monorepo git size by 94%

У статьи очень кликбейтное название. Я сначала подумал, что чуваки комитили node_modules и теперь решили его удалить или что-то в этом роде. Но все оказалось куда интереснее.

Есть команда в Microsoft, которая разрабатываем в большом монорепо на JS. Называется это 1JS, в нем около 20 миллионов строк кода, 2500 пакетов, а клонирование требует 178 гигабайт дискового пространства и некоторые коллеги из Европы (странное уточнение от автора, ну да ладно) не могли его склонировать.

История про клонирование 178 гигабайт звучит очень странно т.к. я точно помню, что microsoft делала свою файловую систему для работы с огромными гит-репозиториями, которая решает проблему клонирования "лишних" файлов. Ну, видимо в репозитории 1JS это не так.

В репозитории есть 2 основных ветки - mainи versioned. В первой ведется разработка, во второй ведутся релизы. По сути ветка versioned хранит в себе изменения CHANGELOG.md и CHANGELOG.json. На удивление, обнаружилось, что именно эти файлы приводят к тому, что в дереве гита приходится хранить дополнительные 125 гигабайт данных.

Почему так? По умолчанию, алгоритм запаковки изменений и снапшотов в git для идентификации файла использует только последние 16 символов названия файла. Поэтому, если изменить repo/packages/foo/CHANGELOG.json, то git будет собирать diff и к repo/packages/bar/CHANGELOG.json (пересчитал символы, у меня получилось что 15 совпадают, а 16 отличается. Либо я не так считаю, либо что-то не так понял). Т.к. это монорепо с 2500 пакетов, то ченджлогов много и git считает дифф каждый к каждому (опять же, если я правильно понял).

Это можно поправить, увеличив окно для сравнения. Для этого ребята добавили возможность регулировать это окно в git for windows. После перепаковки репозитория, размер уменьшился с 178ГБ до 5ГБ.

Очень интересная история с неожиданной развязкой. Никогда бы не подумал что ведение ченджлога может привести к 94% затрат на размер репозитория.

https://www.jonathancreamer.com/how-we-shrunk-our-git-repo-size-by-94-percent/

#development #javascript #performance #monorepo #git #microsoft
👍173
Самые тяжелые NPM пакеты

Одновременно интересная и практически бесполезная таблица с самыми тяжелыми npm пакетами и тем, сколько мирового интернет траффика они потребляют.

Рассчет трафика достаточно простой: берем вес tar.gz пакета, берем количество загрузок в неделю, перемножаем, получаем трафик в неделю

Самый большой трафик создают swc, typescript, next, esbuild, aws-sdk, pnpm, prettier, date-fns

Jquery на 178 месте по трафика. React-dom - 28, сам React - 275.

В целом можно посмотреть за популярностью инструментов для сборки и самыми популярными либами.



https://docs.google.com/spreadsheets/d/1oYJxQgMA7lQ6-wNaBKNNDz6vr3Yaa1EDsI_Hakr4ROg/edit?gid=1891857584#gid=1891857584

#development #javascript #npm
👍8🔥5
Дайджест за 2024-11-11 - 2024-11-15

Crafting a 13KB Game: The Story of Space Huggers
Периодически проходит интересный челлендж - необходимо создать игру на JS, которая поместится в 13кб. Всегда интересно почитать, как люди делают полноценные игры и умещают их в такой крохотный размер.

Данная статья - как раз одна из таких. Автор одной из игр делится тем, как создать такую игру. Здесь не так много технических деталей, связанных с JS, но зато очень много про сам гейм-дизайн и про принятие решений.

Announcing Official Puppeteer Support for Firefox
Наконец-то появилась официальная поддержка firefox в puppeteer. Теперь можно использовать puppeteer для работы с firefox.

Из интересных технических деталей в статье: было два основных варианта для реализации интеграции с puppeteer:

Common Causes of Memory Leaks in JavaScript
Хорошая статья про утечки памяти.

How we shrunk our Javascript monorepo git size by 94%
У статьи очень кликбейтное название. Я сначала подумал, что чуваки комитили node_modules и теперь решили его удалить или что-то в этом роде. Но все оказалось куда интереснее.

Есть команда в Microsoft, которая разрабатываем в большом монорепо на JS. Называется это 1JS, в нем около 20 миллионов строк кода, 2500 пакетов, а клонирование требует 178 гигабайт дискового пространства и некоторые коллеги из Европы (странное уточнение от автора, ну да ладно) не могли его склонировать.

Самые тяжелые NPM пакеты
Одновременно интересная и практически бесполезная таблица с самыми тяжелыми npm пакетами и тем, сколько мирового интернет траффика они потребляют.

Рассчет трафика достаточно простой: берем вес tar.gz пакета, берем количество загрузок в неделю, перемножаем, получаем трафик в неделю

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

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
3👍2
setImmediate() vs setTimeout() in JavaScript

Хороший разбор того, как в NodeJS работает event-loop на примере разбора порядка вызовов setTimeout и setImmediate.

Посмотрите на этот код
setImmediate(() => {
console.log("setImmediate 1");
});

setTimeout(() => {
console.log("setTimeout 1");
}, 0);

setTimeout(() => {
console.log("setTimeout 2");
}, 0);

setImmediate(() => {
console.log("setImmediate 2");
});


Предположите, в каком порядке пойдет вывод в консоль?

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

setTimeout 1
setImmediate 1
setImmediate 2
setTimeout 2


Почему так происходит? Потому что event loop в NodeJS работает следующим образом:
- Таймеры
- Колбеки IO
- Хендлинг IO
- Check

Когда мы вызываем setTimeout(cb, 0) мы складываем задачу в ивент луп. Задачи берутся по одной и колбек таймаута разберется в фазе таймеров. Затем выполняются IO-фазы, а затем фаза Check. setImmediate как раз выполняется в фазе Check, причем с гарантией, что все задачи этой фазы разберутся сразу после IO.

Поэтому получается так, что
- Из ивентлупа забирается первый таймер
- Исполняется
- Проходит IO
- Выполняется Check, в рамках которого выполняются все setImmediate
- Goto start

При этом, если мы поставим таймер и immediate в рамках колбека IO, то можно получить другой результат

const fs = require('fs');

fs.readFile('example.txt', () => {
setTimeout(() => {
console.log("setTimeout after I/O");
}, 0);

setImmediate(() => {
console.log("setImmediate after I/O");
});
});



setImmediate after I/O
setTimeout after I/O


Так происходит, потому что setImmediate был зарегистрирован во время одной из IO фаз и в этом случае он будет выполнен сразу после IO. А колбек setTImeout будет взят позже из ивент-лупа

https://www.trevorlasn.com/blog/setimmediate-vs-settimeout-in-javascript

#development #javascript #setImmediate #setTimeout
🔥18👍6😱5
Организация базы знаний в obsidian

Наконец-то я настроил пайплайн выпуска постов так, что могу вставлять сюда контент без ссылок :) Поисследуем, насколько интересны авторские посты.

Что я имею в виду под знаниями:
- Шпаргалки по использованию инструментов
- Полезные ссылки
- Конспекты и интересные идеи
- MN-ки
- Заметки по проекту или разным областям

Давайте поговорим об организации своих знаний в каком-то инструменте. Кто-то этого вообще не делает (и хранит все в голове), кто-то по хардкоду переводит вообще все знания в какие-то инструменты

Самый необычный инструмент для хранения знаний, который я видел, это Trello. Чел (привет Костя) заводил карточку на trello-доске под каждую тему и в ее контенте и комментариях скидывал всякое интересное.

Самые популярные, из тех что я вижу у своих коллег, это notion и встроенные в ОС заметки.

Лично мне оба инструмента не нравятся:
- Notion чисто онлайн-инструмент - не очень отзывчивый, не очень быстрый. Зато, конечно, удобный, позволяет сделать красиво и позволяет настроить совместную работу. Но главный минус, для меня, это vendor-lock. Сложно перейти из Notion куда-то, сложно делать офлайн-бекапы. В случае если Notion решит вас заблокировать, то можно потерять все свои заметки
- Встроенные в ОС заметки как правило плохо шарятся между устройствами. В целом это очередной vendor-lock

В какой-то момент я перешел на работу с markdown-файлами. Почему так:
- Полный контроль над контентом. Это просто файлы - храню где хочу, легко бекапить, легко синхронизировать, можно открыть на любом тостере
- Markdown легко конвертировать в другие форматы. Например, посты в канал я пишу в markdown и телега их принимает. Заметки по работе я тоже пишу в markdown и в confluence есть конвертер из markdown в confluence формат
Конечно же есть и минусы:
- markdown формат весьма ограничен. Приходится, как минимум, отказаться от работы с таблицами
- Тяжело найти инструмент, который оставит полный контроль над файлами и позволит легко шарить эти файлы и работать с ними в режиме совместной работы

Я попробовал несколько разных инструментов для работы с markdown, но в итоге остановился на obsidian.

Obsidian - это приложение, которое создано вокруг идеи Zettelkasten. Сам метод Zettelkasten я не использую т.к. имхо, проблемы, которую решал Zettelkasten уже нет. Obsidian из коробки позволяет работать с папкой с markdown файлами как с базой знаний: можно линковать файлы друг с другом, организовывать вокруг тэгов, быстро рефакторить их (например, вынести часть заметки в другую и тут же оставить ссылку в текущем документе на новую заметку). Также obsidian очень мощный благодаря плагинам от сообщества: их много, они часто немного сыроваты, но в целом хорошо расширяют возможности Obsidian.

Используемые мной плагины:
- Outliner - позволяет удобно работать со списками
- Dataview - позволяет строить запросы по заметкам
- Excalidraw - позволяет рисовать диаграммы прямо в obsidian, используя excalidraw
- Whisper - позволяет наговаривать аудио, которое потом распознается в текст с помощью whisper
- Templater - позволяет создавать заметки по шаблону
- Tasks - добавляет работу с задачами - можно делать запросы в Dataview, ставить дедлайны, связывать задачи
- Meta Bind - позволяет создать удобные кнопки с кастомной логикой
- Advanced Slides - позволяет делать слайды на основе reveal.js. Использую для простых презентаций

С этими плагинами (и еще парочкой мелких) я веду 3 базы знаний:
- По каналу. Вот прям щас пишу в ней пост
- По работе. Там все задачи, заметки, MN-ки, ведение больших проектов, 1:1, слайды
- Личный. Там все общие заметки как по разработке, так и просто житейские. Также там конспекты по книжкам.

База знаний для канала синхронизируется через гит
База знаний по работе только на рабочем ноуте
Личная база знаний синхронизируется по гугл диску

А как вы организуете свою базу знаний?



#note #obsidian #knowledgeManagement
🔥21👍113
Legacy Modernization meets GenAI

Статья в блоге Мартина Фаулера про то, как они в ThoughtWorks используются нейронки для модернизации всякого легаси.

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

В ThoughtWorks есть клиенты, у которых есть легаси приложение без хорошей документации и которым нужно либо сделать в нем изменения либо переписать его. Как обычно происходили такие задачи: команда инженеров погружалась в код, ревьюила его, строила диаграммы работы системы, выделяла бизнес-правила. Это занимало около 6 недель на 1 модуль из 10к строк.

В ThoughtWorks придумали сделать систему, которая ускорит этот процесс - CodeConcise. Берется код, преобразуется в AST, анализируются связи между разными файлами на уровне кода (например, модуль А зависит от модуля Б, но только при использовании метода Х). По этой инфе уже работает CodeConcise, внутри которого нейронка

Использование CodeConcise ускоряет разбор легаси модуля с 6 недель до двух.

Что еще пробовали делать с кодом через нейронку:
- Удалять мертвый код - оказалось не очень эффективно, относительно тулов, которые уже есть в индустрии
- Переписывать код с 1го стека на другой - также оказалось не эффективно. Код оказывался низкого качества.

https://martinfowler.com/articles/legacy-modernization-gen-ai.html

#development #martinFowler #chatgpt #ai #refactoring
🔥8
Destroy on Friday: The Big Day 🧨 A Chaos Engineering Experiment – Part 2

Вы когда-нибудь задумывались, что будет, если отключить часть ваших серверов? Скорее всего - нет. А есть целая область знаний, которая посвящена этому - chaos engineering. Chaos engineering - это методика повышения отказоустойчивости систем через искусственное создание крупных сбоев.

Данная статья от honeycomb рассказывает, как ребята решили сложить 1 из 3х кластеров своих серверов и как отреагировала система. В целом, инфраструктура honeycomb справилась - трафик перераспределился и все работало.

Если вам интересна тема - зайдите в статью, посмотрите на графики - выглядят достаточно интересно

https://www.honeycomb.io/blog/destroy-on-friday-chaos-engineering-pt2

#development #chaosEngineering
👍51
Дайджест за 2024-11-18 - 2024-11-22

setImmediate() vs setTimeout() in JavaScript
Хороший разбор того, как в NodeJS работает event-loop на примере разбора порядка вызовов setTimeout и setImmediate.

В коментариях к посту указали, что статья не совсем точная. Поэтому если решите почитать статью - почитайте и комментарии

Организация базы знаний в obsidian
Наконец-то я настроил пайплайн выпуска постов так, что могу вставлять сюда контент без ссылок :) Поисследуем, насколько интересны авторские посты.

Давайте поговорим об организации своих знаний в каком-то инструменте. Кто-то этого вообще не делает (и хранит все в голове), кто-то по хардкоду переводит вообще все знания в какие-то инструменты

Legacy Modernization meets GenAI
Статья в блоге Мартина Фаулера про то, как они в ThoughtWorks используются нейронки для модернизации всякого легаси.

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

Destroy on Friday: The Big Day 🧨 A Chaos Engineering Experiment – Part 2
Вы когда-нибудь задумывались, что будет, если отключить часть ваших серверов? Скорее всего - нет. А есть целая область знаний, которая посвящена этому - chaos engineering. Chaos engineering - это методика повышения отказоустойчивости систем через искусственное создание крупных сбоев.

Данная статья от honeycomb рассказывает, как ребята решили сложить 1 из 3х кластеров своих серверов и как отреагировала система. В целом, инфраструктура honeycomb справилась - трафик перераспределился и все работало.

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

Спасибо что читаете, ставите реакции и отмечаетесь в комментариях. Если вы хотите помочь каналу - расскажите о нем своим коллегам или друзьям. Также оставляйте фидбек по формату, материалу и чему-угодно еще 🙂
👍51
Uncontrolled or controlled: A matter of perspective

Статья, разбирающая смысл термином Controlled Component и Uncontrolled Component. В целом, ничего нового, но разбор короткий и понятный

Давайте разберем на небольшом примере

Пример uncontrolled компонента
function Page() {
return <input name="search" />;
}


Пример controlled компонента
function Page() {
const [search, setSearch] = useState('');

return (
<>
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
name="search"
/>

<button onClick={() => setSearch('')}>Clear</button>
</>
);
}


В первом примере input, с точки зрения Page, является uncontrolled компонентом т.к. Page не контролирует состояние и работу input'а - input работает сам. Во втором примере и значение и обработка работы input'а контролируется компонентом Page

Это достаточно тривиальный пример

Давайте возьмем Counter вместо нативного инпута

function Counter() {
const [count, setCount] = useState(0);

return (
<>
<button onClick={() => setCount(count - 1)}>-</button>
<div>{count}</div>
<button onClick={() => setCount(count + 1)}>+</button>
</>
);
}


Это controlled или uncontrolled компонент? Чтобы понять это, надо посмотреть на компонент с точки зрения того, кто его использует

function App() {
return <Counter />;
}

С точки зрения App такой Counter - uncontrolled, т.к. он работает сам по себе и на его работу нельзя повлиять

Но Counter можно реализовать и как controlled компонент. В этом случае с точки зрения App код должен получиться примерно такой

function App() {
const [count, setCount] = useState(0);

return (
<>
<Counter value={count} onChange={setCount} />

<p>App state: {count}</p>

<button onClick={() => setCount(0)}>Reset</button>
</>
);
}


А можно пойти еще дальше и сделать так, чтобы Counter мог работать и как controlled компонент и как uncontrolled компонент. Если ему прокинули пропсы - значит будет работать как controlled, иначе - uncontrolled.

В общем, чтобы определить является ли компонент controlled или uncontrolled, надо посмотреть как используется компонент в вызывающем коде. Один и тот же компонент может быть как controlled так и uncontrolled в разных контекстах.

https://buildui.com/posts/uncontrolled-vs-controlled-a-matter-of-perspective

#development #javascript #react #controlledComponents
👍9🔥4
Adopting the compiler in Sanity Studio

Sanity Studio - приложение для создания и редактирования контента (не до конца понял каокго) с режимом совместной работы и постоянной синхронизацией. Приложение реализовано на React и команда решила попробовать подключить react compiler в свой проект.

Если совсем коротко: Sanity Studio подключили react compiler и он обнаружил проблемы в коде и ускорил рендер приложения.

Я сразу признаюсь, что не до конца вкурил про что там челы пишут (т.к. до сих пор не до конца понимаю что такое react compiler). Но основные поинты такие:
- eslint-plugin-react-compiler хорошо работает как детектор багов. Он находит места, которые работают неправильно
- babel-plugin-react-compiler вскрывает проблемы react-кода приложения

Когда ребята включили компайлер в коде своего редактора, куча e2e тестов попадала. Во время расследования, почему так случилось, выяснилось, что раньше тесты проходили, но это были ложно-положительные прохождения. Т.е. код изначально плохо работал в некоторых случаях, а react compiler сделал так, что эти случаи стали заметны.

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

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

В общем, звучит круто. Какие советы дает автор:
- Подключайте eslint-plugin-react-compiler и фиксите баги
- Подключайте babel-plugin-react-compiler на тестовых стендах чтоб убедиться, что приложение стало работать лучше и нет багов
- Используйте react-compiler-runtime чтобы ускорить приложение
- Инкрементально рефакторите код, который компилятор пропускает


https://github.com/reactwg/react-compiler/discussions/33

#development #javascript #react #reactCompiler #react18
👍16👎1
Storybook 8.4

Вышел Storybook 8.4. Основные фичи: улучшения компонентных тестов, уменьшение размера бандла, поддержка svelte 5, поддержка React Native, поддержка тэгов в историях

Теперь давайте разберем по-подробнее

Самый крутой апдейт релиза, на мой взгляд, называется Component Test in 1 click. Storybook много усилий вкладывает в использование инструмента в целях тестирования. В данном релизе добавили удобные кнопки в UI-сторибука для запуска разных видов тестов прямо из интерфейса (ui-тесты (chromatic), компонентные тесты, тесты доступности). Лучше, конечно, посмотреть гифку в блоге, чтоб посмотреть на то, как работает эта фича. Выглядит хорошо.

Следующий большой поинт - оптимизация бандла. Теперь storybook весит на 50% меньше, по сравнению с 8.0. Эта работа делалась итеративно и каждый следующий релиз становился все меньше. В посте также есть картинка, которая показывает изменение графа модулей по релизам - выглядит внушительно.

За счет чего удалось достичь таких результатов:
- Удалили fs-extra, handlebars, file-system-cache
- Заменили lodash ⇒ es-toolkitexpress ⇒ polka,  chalk ⇒ picocolorsqs ⇒ picoquery
- Оптимизации: включение продакшн-мода для react, опциональный prettier
- Бандлинг: Vite builder , React renderer , Addon-docs 

Как многие из вас знают, официально вышел Svelte5 (и как-то так вышло, что я в канале об этом не написал). Storybook теперь поддерживает svelte5 и также встроен в бутстрап svelte5 проектов.

Перейдем далее: React Native поддерживался в storybook 7, но поддержку для storybook 8 добавили только сейчас. Собираются и далее поддерживать совместимость с React Native

Другая полезная фича: тегирование историй. Если у вас большой сторибук, то бывает сложно там навигироваться. Да, там есть поиск по названию истории, но бывает так, что мы хотим выделить все истории, которые связаны с чем-то определенным, а сделать это невозможно. Теперь в Storybook появилась возможность указывать теги у истории и фильтровать истории по ним. Также можно визуализировать теги в виде беджей. Как юзкейсы, которые предлагает сам Storybook в посте: выделение новых компонентов (бейдж New! рядом с историей в навигации) и ведение версий (бейдж v1.0.0 рядом с историей в навигации)

https://storybook.js.org/blog/storybook-8-4/

#development #javascript #storybook #release #componentTests #svelte5
👍9🔥3
2025/10/02 21:10:28
Back to Top
HTML Embed Code: