Rose debug info
---------------

Подписаться на блог

Фиды

Рассылка

Фрирайтинг, заметки, шитпостинг и все подряд (18+)

Позднее Ctrl + ↑

Записал подкаст

Уже несколько лет думаю про то, что пора бы сделать подкаст. Но все это время я долго прокрастинировал, придумывал какие-то планы и откладывал, откладывал, откладывал. Зато пообщался с самыми топовыми подкастерами СНГшного JS-коммьюнити (спасибо, HolyJS и RndTech Conf).

В общем мотивация была, желание было, а пинка не было. Но, к счастью, недавно ребята из WebPurple подпнули меня, и я все-таки решил делать WebPurple Speech — коммьюнити-подкаст про айти, разработку и людей.

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

Сделал несколько выводов:

  • Подкасты проще, чем посты — нужно нажать только одну кнопку, чтобы начать запись.
  • Предварительная подготовка проще, чем я ожидал — накидать интересующие вопросы и все.
  • Никакой аппаратуры не требуется — айфон отлично пишет звук (не идеально, но я же любитель).
  • Хотел подкаст, а получилось интервью — надо было продумать, как диалог строить, а не просто вопросы задавать.
  • Обрабатывать материал дольше, чем писать его — особенно учитывая, что у меня еще и видео есть.

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

Не понял Clubhouse

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

Во-первых, мне сразу в голову прилетела ассоциация: вся идея — это тот же Zello или какая-то другая интернет-рация.

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

Во-вторых, помимо Зелло есть аналогичная функциональность в Телеграме (с недавних пор), Дискорде (и куче его аналогов), даже Фейсбук дает возможность собраться в комнаты по интересам и пообсуждать что-то голосом.

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

И вот теперь я никак не могу разобраться, а чего оно полетело-то так?
Продукт, который не дает ничего уникального, у которого нет каких-то явно выделяющих его фич, со старой идеей привлекает кучу пользователей — 1.1 миллиона за 6 дней.

Весь контент сразу пишется в /dev/null.

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

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

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

Хайп немного объясняет система инвайтов, которая добавляет некоторый шарм элитарности и пара этих крутых историй с выступлениями Цукерберга и Маска.

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

Либо я опять-таки ничего не понял, продолжаю наблюдение.

Блог переехал на Эгею

Долго я к этому шел, и вот свершилось — перевез бложик на Эгею.

Долго сидел на статических генераторах, аж 4 года (или больше), но по итогу желание быстро и удобно шитпостить победило. Особенно круто, что постить я теперь могу прямо с мобилки.

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

А еще у меня тут есть крутейшие заметки на полях, спасибо @mopsicus

Почему Эгея? Потому что простая, ничего лишнего, и админка есть. Ну и автор — клевый. И дизайн нормальный втащил, и типограф — все красиво и удобно. Разметка не маркадаун, конечно, но мне не привыкать юзать вики-разметку.

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

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

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

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

12 мес   blog

Применяем команды iOS

Относительно недавно я перешел на iOS, и меня долго мучало, куда бы приладить команды, которые позволяют что-то автоматизировать. Чего я только в них прикрутить не пытался, в моих случаях все упиралось в то, что триггер телеграма с отправкой сообщений попросту не работает. Но это, конечно, совсем другая история!

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

Хотелось бы сказать, что я не написал ни строчки кода для внедрения этой фичи, но нет, пришлось дописать в бота один GET-эндпоинт, который достает из QS координаты, проверяет токен и делает все то же самое, что делал бот.

Говорим iOS’у запускать каждый вечер экшен, в котором он получает геопозицию, достает из нее координаты и дергает GET-эндпоинт с пробросом координат в него. Метод запроса и экшены были подобраны так, чтобы iOS ничего не показывал и не требовал никаких действий со стороны пользователя.

2020   blog   development

Ошибки state-менеджмента React-компонентов

При работе с React у многих разработчиков, у которых с ним менее года опыта (или более, но понимания некоторых аспектов нет) возникает проблема с пониманием состояния компонента.

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

Это было проблемой, но решалась она быстро. С появлением хуков ситуация ухудшилась.

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

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

const component = ({ prop }) => {
  const [savedProp, setSavedProp] = useState(null);

  useEffect(() => {
    setSavedProp(prop);
  }, [prop]);
};

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

Эффект, который слушает изменения стейта, чтобы… вызвать коллбэк.

const component = ({ prop, onPropChange }) => {
  const [savedProp, setSavedProp] = useState(null);

  useEffect(() => {
    onPropChange(savedProp);
  }, [savedProp]);

  return (
    <Child prop={prop} onPropChange={setSavedProp} />
  )
};

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

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

Проблема FrontOps’а

TL;DR

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

Предыдущие два года на более, чем двух проектах я занимался такой деятельностью, которую обычно называют «FrontOps». Давайте разберемся, какие у фронтопса проблемы и как их решать.

Дисклеймер: По теме я не раз говорил на митапах Webpurple, но структурировать все в текст так и не вышло нормально. Пост — просто изливание кучи мыслей, не структурирован, хотя планировалось нечто большое на несколько иную тему, в черновиках лежал больше, чем полгода, но, как говорил Тим, надо признаться, что черновики не допишутся и публиковать как есть, вот публикую. Ниже все исключительно ИМХО.

Повествование я начну как обычно — с небольшого отступления в прошлое. Когда я начинал работать как разработчик, я никогда не был против задач не для разработчика (как сейчас считается): сервер настроить, сконфигурировать прокси, сборщик из пачки sh-скриптов подкрутить, еще что-то. Да, эти задачи я решал постольку-поскольку, не использовал всякие крутые штуки и инструменты, до поры до времени ни про вагрант, ни про ансибл не слышал, но задачи решал и мне в целом нравилось.

Что касается специализаций и развитий навыков, я приверженец T-shape подхода: в основном я фронтендер, но и в DevOps с бэкендом могу. Вот благодаря этому пересечению с девопсом я гордо могу назвать себя FrontOps’ом.

Появление FrontOps

Вторая часть слова — Ops. Когда говорят про Ops, вспоминается DevOps. Несколько обидно, что почему-то в DevOps не всегда включают FrontEnd, шутка про формошлепов на это есть свои причины, но начнем с того, что такое DevOps.

DevOps — методология взаимодействия специалистов по разработке (Dev) со специалистами по информационно-технологическому обслуживанию (Ops) и интеграцию их рабочих процессов друг в друга для обеспечения качества продукта.

Wikipeadia — DevOps

В диалогах я слышал что-то вроде: «Какие еще оперейшены во фронтоне?! Че там оперировать, статика же?», — наверно, поэтому как-то это все в отдельное направление и выделилось местами. Изначально, девопс — это больше про бэкенд и все, что около него, как-то так сложилось исторически, во всяком случая я чаще сталкивался с таким, что в рамках девопс-процессов о фронтенде никто особо не думал, и это как-то само должно было решаться. Ведь что нужно бэкенду? Кластер серверов, лоадбалансинг, умный деплоймент с нулевым даунтаймом, скейлинг и много всего сложного и интересного. А что на фронтенде обычно было? Отдать статику (часто через тот же бэкенд) и все, но сейчас времена другие.

В итоге, отпочковался фронтопс. Фронтопс — ничто иное, как перенос девопс-практик на фронтенд. Те же практики, те же решаемые задачи, просто с некоторой спецификой что ли. Девопс (и фронтопс, выходит, тоже) подразумевает работу по некоторому циклу из определенных шагов с использованием определенных техник и инструментов.

Проблема FrontEnd ~ Ops

Create... а дальше?

После того, как код написали, с ним еще много интересного происходит до того, как он начнет решать задачи пользователя и бизнеса, да и в процессе выполнения этих задач интересное не заканчивается. На бэкенде, разработчики в большинстве своем представляют, что с кодом происходит, после того, как он скомпилировался, так как по-другому там жить довольно сложно, надо все-таки понимать, кто там jar’ник запустил и какие и куда пакеты летают, бэкендерам даже надо понимать, что такое TCP, например (!!!).

В мире фронтенда ситуация несколько иная. На один мой комментарий в ревью «этот код не соберется вот по этой причине, вот линк, почитай, интересная штука» мне отвечали «я простой разработчик, это меня не касается» (утрирую, но примерно так было). WTF? В тот момент я понял, что что-то не так.

Откуда растут ноги этой проблемы? Из времен, когда разработка фронтенда заключалась в запуске сервера статики (и то не всегда) и изменения файликов, которые тут же отображаются в браузере, а деплой заключался в том, чтобы отдать файлики бэкендерам, а они там в jsp перегонят и сами разберутся, или загрузить файлики через FTP на другой сервер. Просто, круто, DX на высоте, код написал и все.

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

  • `git clone` — оп, код у меня;
  • `npm install` — ну, зависимости у меня, погнали;
  • `npm start` — ммм, *клик-клац-клик*, все, написал;
  • `git commit -a && git push` — отлично, таску в резолв.


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

Вроде бы задача понятна, но для многих разработчиков фронтенда она нерешаема по одной простой причине: они слишком отдалились от инструментов разработки и не успели подстроиться под их изменения, да и думать об этом часто не нужно, и «вообще пусть это девопсы делают, оперейшены все-таки». Но откуда девопс-инженерам знать о том, как код должен собираться вебпаком? А тем более о всяких узких местах, типа хранений шрифтов на том же домене, чтобы лишний dns-запрос не делался?

Много разработчиков на C++ вы знаете, которые не понимают, как линкуются библиотеки и не могут написать make-файл? А фронтендеров таких много, и это часто не проблема фронтендера, да и не проблема это, просто у нас много инструментов, которые легко устанавливаются и все делают сами.

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

Решаем проблемы

Фронтопс — это не только девопс + фронтенд, фронтопс — то, что нужно знать фронтенд разработчику, для того, чтобы быть действительно фронтенд разработчиком, ведь закомиченный код — далеко не результат работы. Нужно понимать, что с кодом происходит, куда он потом помещается и как доходит до пользователя.

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

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

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

Инструменты, о которых нужно иметь представление

  • Вебпак, бабел, бандлеры, таск-раннеры (Webpack, Babel, npm-scripts, Gulp) — изучите принцип работы сборщиков и компиляторов JavaScript, TypeScript, CSS, поймите разницу между Rollup и Webpack, изучите возможности npm-scripts и Gulp (хоть его и мало кто использует сейчас).
  • Форматтеры, линтеры, статические анализаторы (ESlint, Prettier, stylelint, SonarQube) — хватит спорить на ревью о том, где должна стоять запятая, хватит мутировать иммутабельные значения, автоматизируйте проверку этого.
  • Git и хуки (Husky, lint-staged, Learn Git) — изучите Git, для вас не должны быть проблемой ребейзы, которые заканчиваются конфликтами, используйте хуки для автоматического запуска проверок.
  • Тестирование (Jest, Mocha, Jasmine, Cypress) — изучите инструменты тестирования, способы их использования, виды тестов.
  • Дополнительные инструменты для проверок проекта (size-limit, Lighthouse CI) — проверяйте перформанс-метрики вашего проекта прямо на этапе непрерывных интеграций.
  • CDN, файлы, сервера и прокси (nginx, S3, CloudFront, Cloudinary) — изучите, как файлы могут храниться и раздаваться.
  • Мониторинг (Amplify, Sentry) — настройте мониторинги, отслеживайте, что происходит с кодом при использовании.
  • Деплой, сервера, докер (Ansible, Docker, SSH) — изучите подходы к деплою, варианты запуска приложений, научитесь работать с SSH и консолью — это действительно нужный навык.
  • CI/CD (GitLab CI) — изучите принципы и подходы к организации CI/CD, сделайте полезный пайплайн для своего проекта или оптимизируйте существующий.

UI library based on Chakra-UI bundling

Recently I tried to build some UI components library that based on Chakra-UI. At first my library didn’t contain react components and compiled using typescript and it worked perfectly. But after I added React components based on Chakra-UI and migrated build to webpack, I’ve got the next error from react hooks that were called inside Chakra-UI hooks such as useTheme:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
By the way, Chakra-UI repository has this issue about this error - ((https://github.com/chakra-ui/chakra-ui/issues/495 #495)).

What is the reason for this error? useTheme hook and Chakra-UI library in whole use react library. As a result library imports react and react-dom. When webpack bundling your library that includes Chakra-UI, it includes react and react-dom to bundle of your library. In brief, you import react to your project, also you import your library with Chakra-UI that contains react too, as a result — you have at least two React copies. And in fact, it’s incorrect hook call.

How to fix it? Use only single react instance in your app. If you’re using webpack you can mark react and react-dom libraries as external libraries for your components library:

externals: {
  // mark "react" and react-dom as external packages that will import using commons
  react: 'commonjs react',
  'react-dom': 'commonjs react-dom'
},
output: {
  path: path.resolve('./'),
  libraryTarget: 'commonjs2', // set library target
  filename: '[name].js',
  library: '',
}

Now bundle of your library doesn’t contain react and react-dom. We marked libraries as external and have pure require calls but doesn’t have library in bundle:

/***/ "react":
/*!************************!*\
  !*** external "react" ***!
  \************************/
/*! no static exports found */
/***/ (function(module, exports) {
  module.exports = require("react");
/***/ }),

/***/ "react-dom":
/*!****************************!*\
  !*** external "react-dom" ***!
  \****************************/
/*! no static exports found */
/***/ (function(module, exports) {
  module.exports = require("react-dom");
/***/ })

This way also can help you if you’re using hooks and creating your own UI library without Chakra-UI.

Ранее Ctrl + ↓