cherkashin.dev
2.12K subscribers
255 photos
16 videos
277 links
Александр Черкашин. Бойскаут, Борец с перфекционизмом.

Для связи 👉 @cherkalexander

Фулстек разработчик в decisions.com. Работаю со стеком TypeScript, React, C#

Пишу о программировании и не только.


Блог: https://cherkashin.dev
Download Telegram
cherkashin.dev
Кажется, кто-то узнал, что программист приехал на отдых. Сначала аэропорт SSH, теперь номер 11101, а дальше что? Бустани канал, чтобы оставаться в курсе, а то мало ли что ... #vacation
Ну знаете ли, это уже не смешно, кто-то точно за мной следит.

Сначала думал, совпадение — ну ладно, один раз могло случиться. Но опять номер в отеле в двоичной системе.

В прошлый раз был 11101 = 29, в этот раз 1001 = 9. Это как-то связано с тем, что мне 29 через пару месяцев? Или кто-то передает мне пароль? Но от чего?

Так много вопросов и мало ответов…

#vacation
🤣152👍2💩1
🏗️ Как используется паттерн простая фабрика в исходниках хромиума

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

Этот паттерн используется в реализации всем нам знакомого (кроме бэкендеров) метода document.createElement('div').

Вместо длинного списка switch/case у нас тут словарь, где по имени тега выбирается функция-конструктор и сразу вызывается.

Код целиком можно посмотреть вот здесь 🔗.


// html_element_factory.cc

static void CreateHTMLFunctionMap() {
DCHECK(!g_html_constructors);
g_html_constructors = new HTMLFunctionMap;

// таблица соответствий тегов и функций-конструкторов
static const CreateHTMLFunctionMapData data[] = {
// тут конструкторы всех тегов div/span/ul/li/button/h1...
{ html_names::kDivTag, HTMLDivConstructor },
{ html_names::kSpanTag, HTMLSpanConstructor },
{ html_names::kMainTag, HTMLMainConstructor },
{ html_names::kUlTag, HTMLUlConstructor },
{ html_names::kLiTag, HTMLLiConstructor },
{ html_names::kButtonTag, HTMLButtonConstructor },
{ html_names::kCanvasTag, HTMLCanvasConstructor },
{ html_names::kH1Tag, HTMLH1Constructor },
// .... и так далее
};

for (size_t i = 0; i < std::size(data); i++)
g_html_constructors->Set(data[i].tag.LocalName(), data[i].func);
}

// функция — фабрика элементов
HTMLElement* HTMLElementFactory::Create(
const AtomicString& local_name,
Document& document,
const CreateElementFlags flags) {
if (!g_html_constructors)
CreateHTMLFunctionMap();

// находим функцию-конструктор по имени тега
auto it = g_html_constructors->find(local_name);
if (it == g_html_constructors->end())
return nullptr;
HTMLConstructorFunction function = it->value;

// создаем элемент
return function(document, flags);
}


Но это не самое интересное 🕵️‍♂️.

Я достаточно долго искал этот код на гитхабе. И не потому что мне было плохо, когда я пытался читать C++ код. Я видел, что HTMLELementFactory::Create вызывается, но описания самой функции в коде нет.

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

А генирируется html_element_factory.cc на основе:
- 📜 HTMLTagNames.in — списка тегов
- 🏗️ ElementFactory.cpp.tmpl — шаблон файла фабрики

#patterns #oop

@cherkashindev
👍123🔥3🤗1
🔄 Обновляем caniuse-lite

Когда стали использовать реакт, мы взяли стандартный create-react-app, в котором использовался browserslist. Конфиг был стандартный.


"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}


Потом мы, конечно, совершенно забыли как работает browserslist, и успешно игнорирывали следующее сообщение при билде.


Browserslist: caniuse-lite is outdated. Please run:

npx update-browserslist-db@latest

Why you should do it regularly: https://github.com/browserslist/update-db#readme


Так в чём проблема? 🤔

caniuse-lite - легковесная версия, той самой базы caniuse.com. Время идёт, появляются новые версии браузеров, а мы используем старую базу, и все наши запросы ">0.2%" работают с браузерами пяти летней давности.

То, есть запрос ">0.2%" выбирал браузеры, у которых доля рынка была больше 0.2% 5 лет назад.

А это значит, что
- async/await преобразуется в длинную партянку кода в ES5
- стрелочные функции () => {} заменяются на function() {}
- никаких let/const, только старокрестьянский var
- в код попадают ненужные полифилы

В общем, если давно не обновляли caniuse-lite открываем консоль и запускаем:


npx update-browserslist-db@latest


Если у вас pnpm монорепозиторий — используйте команду:


pnpm up caniuse-lite


Мы обновились и наши жирные бандлы прилично похудели.


407.31 KB (-100.86 KB) build/bundle-1.js
369.3 kB (-34.64 kB) build/bundle-2.js
220.67 KB (-18.86 kB) build/bundle-3.js


#javascript #tools
👍13🔥54
Всё достало, увольняюсь …
😁23💯8🤡4😱2🗿2
ИИ для прототипирования интерфейсов

До недавнего времени я использовал ChatGPT исключительно как помощника для генерации кода — вбросить запрос, получить сниппет, внести правки. Но все вокруг только и говорят об AI-агентах, курсоре, v0 и так я наткнулся на сервисы для онлайн генерации прототипов на основе ИИ.

Вот несколько подобных сервисов:
- BoltNew
- v0 by Vercel
- lovable

Можно сказать, что это онлайн IDE, где можно сгенерировать проект по запросу, увидеть результат, задеплоить и поделиться ссылкой на прототип.

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

А теперь немного про мой опыт 👇.

1️⃣ Первый опыт

Первый раз, когда я наткнулся на v0, я попросил его сгенерировать интерфейс Айфона по скриншоту (тут демка). Когда я увидел результат, то в восторге побежал показывать жене. А потом понял, что шутки про замену фронтендеров на ИИ перестали быть шутками 😅.

2️⃣ Опыт использования в работе

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

У библиотеки, есть большой набор демок, но то, что требовалось мне — отсутствовало. И тут я вспомнил про v0 и решил сам сгенерировать маленькие прототипы на каждую новую фичу.

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

P.S. итоговую оценку всё же стоило умножить на 2 😅.

3️⃣ Ещё пример

Также мы рассматривали вариант, сменить GoJS на @xyflow/react и тут мне снова помог V0. Примеры для @xyflow/react v0 генерировал намного лучше. За пару дней я набросал небольшой прототип, который точно писал бы неделю. Я сделал скриншот дизайна в фигме, и попросил v0 сгенерировать его с использованием библиотеки.

🛑 Минусы

Тут конечно, важно сказать, что часто эти сервисы:
- генерируют нерабочий код
- генерируют не совсем то, что вам нужно
- могут сломать весь проект после очередных изменений
- имеют ограниченное количество бесплатных запросов в день

Расскажите, пользуетесь ли вы подобными сервисами и какое у вас впечатление?

#Frontend #Ai
1👍83💊3
⚛️ State is tied to a position in the render tree

Помнится в одном из своих пет проектов у меня был баг — при переходе между страницами у меня не пересоздавался zustand стор из-за чего компонент PersonalStatistic использовал стор компонента CodeReviewCharts 👇


children: [
{
path: '/charts',
element: (
<ChartsStoreProvider createStore={createPersonalPageStore}>
<CodeReviewCharts />
</ChartsStoreProvider>
),
},
{
path: '/personal',
element: (
<ChartsStoreProvider createStore={createCommonChartsStore}>
<PersonalStatistic />
</ChartsStoreProvider>
),
},
]


Дело было в том, что контекст был одним и тем же компонентом ChartsStoreProvider. Тогда я просто добавил key для сторов и проблема ушла.


children: [
{
path: '/charts',
element: (
<ChartsStoreProvider key="charts" /*👈*/ createStore={createPersonalPageStore}>
<CodeReviewCharts />
</ChartsStoreProvider>
),
},
{
path: '/personal',
element: (
<ChartsStoreProvider key="personal" /*👈*/ createStore={createCommonChartsStore}>
<PersonalStatistic />
</ChartsStoreProvider>
),
},
]


Не помню было ли это в старой документации реакта, но в новой явно сказано:

State is tied to a position in the render tree

Состояние привязано к определённой позиции в дереве рендера.


То, есть проблема была в том, что при переходе на страницу /personal, ChartsStoreProvider оставался на той же позиции в дереве и поэтому использовался "неподходящий" стейт предыдущего провайдера.

Раньше я думал, что стейт живет "внутри компонента" — то, есть связан с инстансом конкретного компонента, как свойста в классе. Но документация явно говорит:

When you give a component state, you might think the state “lives” inside the component. But the state is actually held inside React. React associates each piece of state it’s holding with the correct component by where that component sits in the render tree.

Когда вы добавляете состояние (state) компоненту, может показаться, что это состояние «находится» внутри самого компонента. Однако на самом деле состояние хранится внутри React. React сопоставляет каждую единицу состояния с нужным компонентом, исходя из того, где этот компонент находится в дереве рендера.


Вот тут в демке это наглядно видно.

А ещё key можно использовать чтобы явно перерендерить компонент, если у него есть какой-то внутренний стейт.

#react
👍12😇21
Если вы этим пасмурным воскресеньем занялись поиском новой работы, загляните вот сюда — мой земляк запустил телеграм-канал с подборкой классных вакансий. Всё фильтруется нейросетями, так что в ленте только самое-самое.

Недавно, также появилась подборка МЕГАFront. Если хотите получить список самых лучших вакансий — напишите напрямую Саше.

Я вообще уже не помню, когда последний раз откликался на вакансии, тем более, что последние почти 8 лет, я вовсе не менял работу 😅. Обычно рекрутеры сами стучались в личку, и так я ходил по собесам. Но послдение пол года, никто не пишет, действительно ситуация на рынке изменилась?

Расскажите, как сейчас лучше искать работу? hh.ru? LinkedIn? Сетка? Телеграм-каналы с подборками?
👍411
🔥Сегодня наш первый релиз МЕГАПодборок 🎉

Мы сэкономили ваше время и отобрали лучшее за неделю в подборке "МЕГАFront" для фронтенд разработчиков:
- 80 remote-вакансий
- до 9500$
- в $, €, ₽
- для junior, middle, senior, lead
- 50+ каналов вакансий и сайтов
- 7 дней

Бонусом видео-инструкция о том, как грамотно откликаться 🔥
Запросить подборку: по ссылке
Please open Telegram to view this post
VIEW IN TELEGRAM
💩3👍211
Особенности событий порталов в React ⚛️

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

createPortal

Метод createPortal позволяет рендерить компонент вне текущей DOM-иерархии, но при этом он остаётся частью React-дерева.

Теперь читаем документацию

События из порталов распространяются в соответствии с деревом React, а не деревом DOM. Например, если вы нажмёте внутри портала, и портал обёрнут в `<div onClick>`, сработает этот обработчик `onClick`. Если это вызывает проблемы, либо остановите распространение события (stopPropogation()) внутри портала, либо переместите сам портал выше в дереве React.


Что у нас случилось

В проекте мы недавно переписали тулбокс — панель, из которой можно перетаскивать элементы при создании workflow.

Из-за ограничений мы отказались от нативного drag-and-drop и использовали старый кастомный хук на обычных mousedown`/`mousemove.

Что фиксили? 🪲

В общем, всё работал, но пользователь мог начать перестаскивать элемент нажав на всплывающую подсказку (описание на картинке).

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

Причина в том, что React-ивенты всплывают по React-дереву, а не DOM. Всё как в доке. А пофиксили это простым добавлением stopPropogation() в onMouseDown компонента подсказки.

#react
👍94😁1
🗿 Подводные камни при переходе с ES5 на ES6

Недавно мы с командой, наконец-то перешли с ES5 на ES6.

Всё прошло достаточно плавно, нам пришлось исправить всего несколько ошибок в рантайме. Почти все ошибки были в очень старых файлах, где были отключены проверки typescript с помощью @ts-nocheck.

Ошибка 1️⃣ — Action is not a constructor

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


const Action = () => {}; // ES6
const action = new Action(); // Action is not a constructor

var Action = function () {} // ES5
var action = new Action(); // Всё ОК



Ошибка 2️⃣ — Функции, объявленные через let, больше не попадают в window


let openAction = function () {}
window.openAction() // window.openAction is not a function

// Раньше let заменялся на var и всё работало
var openAction = function () {}
window.openAction() // всё ок


Дело в том, что когда переменная объявляется глобально через var, она автоматически становится свойством глобального объекта window. Подробнее тут.

Ошибка 3️⃣ — Cannot access variable before initialization

Одна из ошибок случалась, когда мы пытались получить доступ к переменной promise до её инициализации.


class Queue {
executing;

run(thenable) {
const promise = new Promise(async (resolve, reject) => {
// пытаемся получить значние promise
while (this.executing != promise) {
// ...
}
// ...
});
}
}

// Cannot access 'promise' before initialization
new Queue().run(Promise.resolve())


Раньше, const превращался в var и ошибки не было. Это связано с понятием временной мертвой зоны TDZ, которая не возникает у переменных, объявленных через var.

Были и другие ошибки, но они по сути вариации или комбинации тех ошибок, что я привел выше.

👉 Кстатии, размер бандлов уменьшился процентов на 20.

#TypeScript #JavaScript
👍113
🕸️ Я в Сетке

Я давно уже думаю, как диверсифицировать телеграмм и вести канал где-то ещё (а то вдруг с Дуровым что случится ...).

Я пробовал вести каналы:
- В Дзен — трафик нулевой, ни показов, ни просмотров
- На Хабре — тут получше, но нет удобного способа делать репосты из телеги
- На Пикабу — и просмотры есть и бот для репостов, но на пикабу я не сижу от слова совсем

Теперь решил попробовать Сетку, завел канал и пока вроде всё идет хорошо. Правда с форматирование кода — грусть грустная, надеюсь поправят. Если что Сетка — это рабочая соцсеть от hh.ru, что-то вроде LinkedIn.

В Сетке есть отдельный формат постов "Вопросы", а ещё лента, к которой мы так привыкли. И в результате, можно получить ответы от самых разных людей.

Вот некоторые из моих вопросов:
- Как изменилась работа в финтехе с появлением ИИ?
- Есть ли в России отечественные no-code или low-code платформы?
- Как получать зарплату от зарубежных компаний, если все Российские банки под санкциями?


В общем, если у вас есть сетка — добавляйтесь. А я пойду получу галочку)
🤡8👍32🔥2👏1
У меня есть проблема 😐

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

Когда я ничего не делаю, я чувствую тихий голосок внутри. Он шепчет, что я теряю время, а мог бы:
- 📖 прочитать книгу
- 🎓 пройти курс
- 🛠️ начать ремонт
- 🏋️‍♂️ сходить лишний раз в зал
- и т.д.
Он не дает полностью расслабиться и насладиться выходными в полную силу.

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

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

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

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

Так вот, если вы чувствуете что-то такое — знайте, вы не одиноки 👋😄. И если не получилось отдохнуть в этот раз, то обязательно отдохните на следующей неделе. 😉

#about_me
1👍2111
🤖 Онбординг ИИ

Что происходит, когда в команде появляется новый сотрудник? Правильно — он адаптируется и старается писать код в соответствии с гайдлайнами, принятыми в команде. А помогают ему в этом документация, линтеры и ревью коллег.

По сути, ИИ — это ваш коллега, которому вы делегируете задачи, и ему тоже нужно объяснить, как писать код. И здесь как раз пригодится документация, которую никто из ваших коллег не читает 😄, но ИИ — будет.

Многие ИИ-агенты поддерживают формат "правила/инструкции", где можно описать стандарты и архитектуру проекта. Это, по сути, обычный Markdown-файл, который будет добавляться к системному промпту при каждом запросе.

- В Cline — это custom instructions
- В Cursor — rules
- В Copilot — instructions
- В Windsurf — rules


Названия немного отличаются — но суть одна.

Примеры

1️⃣ У меня Copilot упорно пытался использовать pnpm, пока я явно не указал использовать npm.

2️⃣ На работе мы используем BEM и префиксы для всех имён классов, чтобы избежать коллизий. Cline, конечно, этого не понял, пока я явно не задал это в инструкциях.

3️⃣ На выходных решил набросать MVP пет-проекта из бэклога. Сначала написал ТЗ с помощью ИИ, положил его в .github/instructions/requirements-instruction.md и попросил Copilot написать проект по ТЗ. Он справился, потребовались лишь небольшие правки. Теперь при любых изменениях он уже знает требования.

4️⃣ Можно попросить ИИ использовать conventional commits при генерации сообщений к коммитам.

Некоторые примеры — на скринах.

#ai #frontend
👍122🤡2🔥1