xnimorz

28 октября 2019, Moscow

# Понедельник 67 твитов

Всем привет! Я @xnimorz. Работаю в @hh_ru. Прошел в hh.ru путь от фронтендера до тимлида и сейчас… twitter.com/i/web/status/1…

7:26

В какой-то момент я осознал, что люблю больше чистый язык, чем фреймворки, но удобство, которое дают при разработке… twitter.com/i/web/status/1…

7:31

Я для себя получил ответ в pet-projects и open-source проектах. Так, мой последний эксперимент был со Svelte:… twitter.com/i/web/status/1…

7:31

На этой неделе постараемся чередовать технические темы и soft skills. Пока план такой

7:32

Предлагаю начать с паранойи. И несколько вопросов: Сколько браузерных расширений у вас установлено?

7:37

Вы их проверяли, что они "белые и пушистые"?

7:39

Я свое знакомство с разработкой браузерных расширений начал еще в 2015 году с написания плагина, который заменял ne… twitter.com/i/web/status/1…

8:06

Уже затем я создавал плагин для нашей системы для HR менеджеров: chrome.google.com/webstore/detai… и после этого занимался пе… twitter.com/i/web/status/1…

8:08

Главная проблема с браузерными расширениями — их редко воспринимают как реальную угрозу.
Однако, у них есть все ин… twitter.com/i/web/status/1…

8:12

Расскажу несколько тру-стори, а потом уже перейдем к техническому разбору.

8:14

История 1 про безопасность: Cоздаю себе аккаунт в некоторой условной социальной сети, ввожу телефон и email. В наст… twitter.com/i/web/status/1…

8:22

Через пару дней на email \ телефон начинает приходить спам. Что происходит? Соц. сеть продает мои данные? Она взломана?

8:22

На самом деле все куда как проще. У пользователя стоит плагин, который делает какую-то полезную штуку для него. Но… twitter.com/i/web/status/1…

8:22

Затем передает это в BackgroundScript, который уже отправляет наши контакты в спам-базы, причем с именем, фамилией… twitter.com/i/web/status/1…

8:22

Самое грустное в этой истории, что отследить, что твой сайт кто-то "парсит" таким способом — практически нереально.… twitter.com/i/web/status/1…

8:22
@jsunderhood @xnimorz @hh_ru А можно подробнее об опыте на svelte ? Сколько уже натыкаюсь на стоить на хабре про не… twitter.com/i/web/status/1…

Да, конечно. Сразу предупреждаю — опыт не production, личный.
По svelte у меня есть один проект на github — маски… twitter.com/i/web/status/1…

@jsunderhood @xnimorz @hh_ru А можно подробнее об опыте на svelte ? Сколько уже натыкаюсь на стоить на хабре про не… twitter.com/i/web/status/1…

9:14

Учет финансов, синхронизация между всеми членами семьи, разделение прав и многое-многое другое.
Я периодически дел… twitter.com/i/web/status/1…

9:14

В какой-то момент, я проникся svelte и появилось желание разобраться, насколько он удобен, можно ли им пользоваться… twitter.com/i/web/status/1…

9:14

А потом при том же переходе на реакт появлялись боли: тут нужно PureComponent, там отписку правильную сделать, здес… twitter.com/i/web/status/1…

9:14

Немного по-другому у меня сложилась история со svelte.
Про плюсы svelte тут уже писали и мне лично svelte очень по… twitter.com/i/web/status/1…

9:14

1) Нестабильность API. Я разрабатывал на 3.12.1, а демку делал на другой версии (ниже). У меня в итоге сломался `bi… twitter.com/i/web/status/1…

9:14

2) Вам часто нужно будет разбираться в коде, который сгенерировал svelte. Особенно если вы делаете большое приложен… twitter.com/i/web/status/1…

9:14

3) Если вам нужно прокинуть класс, вам придется объявить его как :global(класс) codesandbox.io/s/svelte-input… (вот здесь в App.svelte пример).

9:14

4) Если вы делаете утилитарный компонент и вы хотите прокинуть все props в обычный элемент (например aria атрибуты… twitter.com/i/web/status/1…

9:14

5) Еще неудобство вот github.com/sveltejs/svelt…

6) Иногда вы зависите от порядка переменных: github.com/sveltejs/svelt…

9:14

Это те боли, которые у меня возникли за последние примерно 2 месяца.

9:14

История 2 про "случайно сломать статику сайта": блокировщики рекламы очень эффективно блокируют запросы к ресурсам.… twitter.com/i/web/status/1…

9:21

А все дело в том, что плагин просто решил, что STATic — это сбор статистики пользователя, поэтому радостно заблочил… twitter.com/i/web/status/1…

9:23
@DonnaInsolita @jsunderhood @xnimorz @hh_ru Посмотри доклад Климова, почему использовать Свелт может быть больно.

Если я правильно понял, то речь об этом выступлении? youtube.com/watch?v=0cFoEP…

@DonnaInsolita @jsunderhood @xnimorz @hh_ru Посмотри доклад Климова, почему использовать Свелт может быть больно.

9:25
@jsunderhood @sbaha88 И это - постоянная головная боль для авторов расширений.

А ещё куча дельцов, которые встраи… twitter.com/i/web/status/1…

9:34
@jsunderhood @foodenko Всё так. Стараюсь минимизировать вектор атаки, снижая количество установленных разрешений.
9:53

Последняя история: расширения прокси могут также зарабатывать на пользователях. Это это не только то, что они получ… twitter.com/i/web/status/1…

10:52

После публикации они правда сменили способ монетизации :)

10:52

Итак, набор проблем ясен, скрипт может выполняться в фоне, может внедряться на страницу. Остается открытым вопрос,… twitter.com/i/web/status/1…

12:10

Всегда лучше знать, кого берешь себе. Можно проводить кучу действий над площадками, чтобы выдрать код, а можно (во… twitter.com/i/web/status/1…

12:10

Этот плагин будет крайне полезен при установке дополнений. Открыли стор, запустили плагин, посмотрели — насколько… twitter.com/i/web/status/1…

12:11

В первых же строках его кода должно закрасться сомнение, что его стоит устанавливать себе на машину.
Он откуда-то… twitter.com/i/web/status/1…

12:11

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

1) Проверять каждое расширен… twitter.com/i/web/status/1…

12:15

2) Отключить обновление расширений, в которых не уверены или вообще всех: stackoverflow.com/questions/2765…

12:15

Что делать с проблемой мне как разработчику сайта? Я постараюсь дать ответ с разбором на HolyJs… twitter.com/i/web/status/1…

12:16
@jsunderhood А есть расширение, которое бы проверяло другие расширения на подозрительный код автоматически?

Хорошая идея, но мне встречать такое расширение не доводилось. Может быть кто-то встречал подобное?

@jsunderhood А есть расширение, которое бы проверяло другие расширения на подозрительный код автоматически?

12:32
@jsunderhood Все дело в том, что автор фильтров перестарался.

Тут больше играет роль то, что мы на основном сайте используем урл `/stat` для баннерки и мониторинга клиентской п… twitter.com/i/web/status/1…

@jsunderhood Все дело в том, что автор фильтров перестарался.

13:31

Ключевая проблема здесь — правило пишут для домена, и все поддомены автоматом наследуют эти правила

13:32
@jsunderhood В рабочем (Хром) — 1, в личном (Сафари) — 0

Круто! Я провел эксперимент и понял, что не смогу отказаться от трех плагинов :(

@jsunderhood В рабочем (Хром) — 1, в личном (Сафари) — 0

13:34
@jsunderhood Браузеры это проверяют автоматом перед паблишем, но не на 100%

В Firefox такая проверка присутствует и такой фокус обычно не пройдет. Аналогично в сафари.
В Chrome store же можн… twitter.com/i/web/status/1…

@jsunderhood Браузеры это проверяют автоматом перед паблишем, но не на 100%

13:42
@BasherTheJedi @jsunderhood Это делают веб-сторы. У Оперы вообще даже ручным режимом, если автоматика показала угрозу

В Firefox проводят (проводили, когда я паблишил) также в ручном режиме. Более того, там проверяют очень подробно, м… twitter.com/i/web/status/1…

@BasherTheJedi @jsunderhood Это делают веб-сторы. У Оперы вообще даже ручным режимом, если автоматика показала угрозу

13:46
@jsunderhood Им еще можно настраивать доступ, у меня один экстеншн(notion) имеет доступ ко всем сайтам, а гугл тран… twitter.com/i/web/status/1…

Да, это хорошо позволяет уменьшить аппетиты и чуть больше быть уверенным, что за вами не следят👍. Настраивается обы… twitter.com/i/web/status/1…

@jsunderhood Им еще можно настраивать доступ, у меня один экстеншн(notion) имеет доступ ко всем сайтам, а гугл тран… twitter.com/i/web/status/1…

13:58
@jsunderhood А это вообще нормально, что расширения( в хроме точно) имеют доступ кл всем твоим куки. Это разве не дыра в безопасности?

Любое расширение, которое получило пермишен к сайту (либо маска сайта, либо <all_urls>) может внедрять свой код на… twitter.com/i/web/status/1…

@jsunderhood А это вообще нормально, что расширения( в хроме точно) имеют доступ кл всем твоим куки. Это разве не дыра в безопасности?

14:36

httpOnly прямо обязательно для любых авторизационных кук. Такие куки недоступны со стороны js.
Также можно использо… twitter.com/i/web/status/1…

14:39

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

14:49

Скорее всего большинство из нас пользуется react или vue devtools. Им нужны пермишены для общения с вкладками, обра… twitter.com/i/web/status/1…

14:49

Если вы получаете обращение в саппорт "сайт тормозит", часто саппорту приходится объяснять пользователю, как сделат… twitter.com/i/web/status/1…

14:49

В тему плагинов и блокировщиков рекламы (особенно, если у вас хром) — пробовали ли вы Brave вместо Chrome + блокиро… twitter.com/i/web/status/1…

15:23
@jsunderhood Уже пол года им пользуюсь

Я тоже в какой-то момент попробовал Brave и понял, что он меня всем устраивает.

@jsunderhood Уже пол года им пользуюсь

15:39

Но с brave были некоторые сложности. Например, он блокировал сайт mvideo. Получилось зайти, только отключив guard

15:39
@jsunderhood А если использовать атрибут integrity для скриптов на сайте, в этом случае расширение сможет внедрить и выполнить js?

Обычно Content Security Policy — одна из первых штук, которая приходит в голову для защиты от плагинов. Сама по себ… twitter.com/i/web/status/1…

@jsunderhood А если использовать атрибут integrity для скриптов на сайте, в этом случае расширение сможет внедрить и выполнить js?

16:55

Integrity или Subresource Integrity идет вместе c Content-Security-Policy: require-sri-for script; что требует пров… twitter.com/i/web/status/1…

16:55

Плюс с поддержкой у require-sri-for все пока еще не радужно: developer.mozilla.org/en-US/docs/Web…

16:55

Куда эффективнее будет запретить все скрипты, включая inline, кроме своего домена, но и тут плагины будут исполняться.

16:55

Маленькое дополнение к svelte: пару дней назад выложили "The Return of 'Write Less, Do More'" от Rich Harris… twitter.com/i/web/status/1…

17:12

Не "Скрипты же действуют по-другому:", а "Расширения же действуют по-другому"

17:32
@jsunderhood Единственная возможность защитить приложение от браузерных расширений, на сколько я понимаю, описана т… twitter.com/i/web/status/1…

Здесь рассматривается только подмножество проблем — отправка данных, подписка данных ключом и получение данных. Сам… twitter.com/i/web/status/1…

@jsunderhood Единственная возможность защитить приложение от браузерных расширений, на сколько я понимаю, описана т… twitter.com/i/web/status/1…

19:04

Как пример: приложение вставляет свои данные к нам на сайт, для добавления комментариев: chrome.google.com/webstore/detai…
Са… twitter.com/i/web/status/1…

19:08

Мое выступление на HolyJs holyjs-moscow.ru/2019/msk/talks…
Как раз будет про различные векторы атак и защиту от них.

19:10
@boriscoder @jsunderhood В кейсе описана регрешн бага насколько я понял, а они у всех бывают. Хотя в целом, чем мол… twitter.com/i/web/status/1…
20:51

# Вторник 95 твитов

@jsunderhood @xnimorz @hh_ru Привет!

Хотелось бы услышать про организационную структуру фронтенда и отдельно про к… twitter.com/i/web/status/1…

Сегодня как раз поговорим о работе и процессах в компании.

@jsunderhood @xnimorz @hh_ru Привет!

Хотелось бы услышать про организационную структуру фронтенда и отдельно про к… twitter.com/i/web/status/1…

6:00

Как и обещал, сегодня поговорим про тех.деп хх и процессы. Я сейчас работаю в команде архитектуры, где 100% времени… twitter.com/i/web/status/1…

7:06

Что есть типичная задача в моей команде?
На самом деле они очень сильно разнятся. Начиная от внедрения SSR для реа… twitter.com/i/web/status/1…

7:08

Кстати, организовать удобную работу с иконками на большом сайте — это может быть (внезапно) не самой тривиальной за… twitter.com/i/web/status/1…

7:16
Предлагаю начать с паранойи. И несколько вопросов: Сколько браузерных расширений у вас установлено?

Результаты по количеству плагинов в браузере:

Предлагаю начать с паранойи. И несколько вопросов: Сколько браузерных расширений у вас установлено?

7:44

Команда архитектуры занимается всем, что позволит повысить скорость разработки или качество кода. Из того, что перв… twitter.com/i/web/status/1…

7:58

Все изменения делаются для всей фронтенд группы, а не локально. Иногда во время таких задач появляются разные open-… twitter.com/i/web/status/1…

7:58

Здесь будет тред, о том, как организован технический департамент HeadHunter (большими мазками) >>>

9:31

У нас нас есть страница на tech.hh.ru/about.html, где описано достаточно подробно все, какие технологии мы исполь… twitter.com/i/web/status/1…

9:31

1) Технический департамент на текущий момент — это более 130 человек и 25 команд. Каждая команда — отдельный unit,… twitter.com/i/web/status/1…

9:31

Поэтому стандартная конфигурация команды это 1 фронтенд-разработчик, 1 бекенд, 1 тестировщик и 1 тимлид. В зависимо… twitter.com/i/web/status/1…

9:31

2) Владение кодом общее. Поэтому если команде, которая занимается работодательскими фичами, нужно добавить что-то в… twitter.com/i/web/status/1…

9:31

3) Команды разбиваются по своим ролям: работодательские фичи, соискательские сервисы, поиск, реклама, команды сайд-… twitter.com/i/web/status/1…

9:31

4) Бывает так, что какая-то команда больше занимается определенной частью возможностей, например, созданием ваканси… twitter.com/i/web/status/1…

9:31

5) У каждой команды есть product owner, с которым команда прорабатывает задачи. Команда участвует в проработке зада… twitter.com/i/web/status/1…

9:31

6) Большинство задач выпускаем под AБ-тестами. Обычно на проде одновременно включено десятки (а то и сотни) тестов.… twitter.com/i/web/status/1…

9:31

7) Полезная-интересная штука: кроме бизнес-задач у нас есть понятие "технического налога" — это термин похож на тех… twitter.com/i/web/status/1…

9:31

8) Более того, есть соглашение, что 30% времени работы команды могут тратить на налог.

9:31

К предыдущему пункту — еще более хорошая новость, что договоренность про 30% соблюдается.

9:31

9) Код храним на Github, ревьювим код через pull request. Коротко про ревью — любой может участвовать, должен быть… twitter.com/i/web/status/1…

9:31

10) Релизы ежедневные. Сегодня сделал \ протестировал задачу — можно сегодня собрать релиз или завтра она автоматически попадет в релиз дня.

9:31

11) Самих релизов в день может быть много. Очень много. Они могут быть большими. Пару недель назад было 4 релиза фр… twitter.com/i/web/status/1…

9:31

Это не считая остальных сервисов, которых у нас много (так как идем в стороу микро-сервисной архитектуры).

9:31

Тредик с фактами о фронтенд части (компиляция tech.hh.ru/about.html и интересных фактов): >>

9:53

1) Фронтенд делится на 2 стека: старый и новый. Старый это ванильный js + jQuery, на сервере html рендерится через… twitter.com/i/web/status/1…

9:53

Стили пишем в less, используем АНБ подход для разграничения стилей АНБ — верстка независимыми блоками, одно из перв… twitter.com/i/web/status/1…

9:53

2) На новом стеке включен SSR везде. Миграция отдельная большая тема, о ней поговорим на следующий день

9:53

3) Есть UIToolkit — блоко. Работает на двух стеках и состоит более чем из 120 компонентов. Начиная от кнопок и зака… twitter.com/i/web/status/1…

9:53

4) Кстати, на styleguidist документированы и легаси компоненты. Для написания примеров у нас используется кастомный… twitter.com/i/web/status/1…

9:53

5) Код транспайлится бабелем (тайпскрипта у нас пока нет). Используем в том числе такие штуки как optional chainig:… twitter.com/i/web/status/1…

9:53

6) Есть самописные бабель плагины. Некоторые могут быть полезны всем, некоторые специфичны: github.com/hhru?utf8=%E2%…

9:53

7) Код автоматически проверяем eslint github.com/hhru/eslint-co… — наш конфиг. Для стилей используем stylelint. Pretti… twitter.com/i/web/status/1…

9:53

8) Все фронтендеры пишут прослойку на питоне — это сервис, который выполняет роль API Gateway. Получить запрос поль… twitter.com/i/web/status/1…

9:53

Код в прослойке очень простой, веб-сервер c открытым кодом: github.com/hhru/frontik

9:53

9) Юнит-тесты. Их пишем на новом стеке обязательно. Кроме юнит-тестов есть более 8000 сьютов автотестов. Автотесты… twitter.com/i/web/status/1…

9:53

10) В каждом PR мы сделали индикацию code-coverage в зависимости от base branch. Основное правило — желательно, что… twitter.com/i/web/status/1…

9:53

Если стало меньше и если увеличилось: pic.twitter.com/sboHyTQO8a

9:53

11) Fun Fact: такой простой прием позволил заметно повысить code coverage

9:53

12) У каждого разработчика, тестировщика в компании есть отдельная виртуалка, со всеми сервисами. Вся разработка св… twitter.com/i/web/status/1…

9:53

Накатка веток, запуск тестов, обновление стенда — все автоматизированно. Например, у меня в 8 утра всегда происходи… twitter.com/i/web/status/1…

9:53

Во второй половине дня поговорим про Kanban, визуализацию процессов и как удобная и хорошая визуализация помогает разработке.

9:54

В хх я работаю больше 5 лет. И за это время я сменил 5 команд. В разных командах процессы могут отличаться очень за… twitter.com/i/web/status/1…

12:26

Сейчас в ХХ используется Kanban методология. Обычно для новых разработчиков это: стендапы, отсутствие спринтов и пр… twitter.com/i/web/status/1…

12:28

Кроме разработки (product delivery) все разработчики участвуют в проработке проекта (product discovery). Как должен… twitter.com/i/web/status/1…

12:34

В книгах можно встретить понятие бутылочного горлышка (bottleneck). Идея такая: во время проработки отказатсья от и… twitter.com/i/web/status/1…

12:34

Каждая команда определяет свой состав участников на такие проработки. Где-то 2 человека от команды, где-то вся кома… twitter.com/i/web/status/1…

12:34

Команда вместе с продактом разбирает проблему, набрасывает идеи решения и описывает user story. Обычно применяются… twitter.com/i/web/status/1…

12:34

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

12:34

В хх мы построили систему, которая рисует графики, помечает долгие фичи и позволяет даже "гадать", что происходило… twitter.com/i/web/status/1…

12:34

Мы используем базовые инструменты — кумулятивная диаграмма, box plot, гистограмму по статусам и сводные таблицы.

12:34

Нашел хорошую иллюстрацию, которая описывает что позволяет визуализировать кумулятивная диаграмма: pic.twitter.com/O3mjwmD1my

12:34
@MrL1n @_bravit @PodlodkaPodcast @mobileunderhood @jsunderhood ещё им не покорён. возможно фронтендеры смогут своим… twitter.com/i/web/status/1…

Надо звать! :-)

@MrL1n @_bravit @PodlodkaPodcast @mobileunderhood @jsunderhood ещё им не покорён. возможно фронтендеры смогут своим… twitter.com/i/web/status/1…

12:40
Нашёл абсолютно волшебный сайт littlebigdetails.com с клёвыми маленькими фичами, делающими жизнь лучше.

Это великолепно :)

Нашёл абсолютно волшебный сайт littlebigdetails.com с клёвыми маленькими фичами, делающими жизнь лучше.

12:41

Часто может возникнуть вопрос: а чем отличается канбан от скрама?
Про это есть хорошая статья от Алексея Пименова:… twitter.com/i/web/status/1…

13:50

1) Отсутствие спринтов. Никто никогда не пытается "выпустить все задачи в пятницу, потому что спринт заканчивается"… twitter.com/i/web/status/1…

13:50

Если у меня задача сегодня протестировалась, то завтра она уже будет на проде. Кроме того, если очень хочется, можн… twitter.com/i/web/status/1…

13:50

2) Более явная вытягивающая система — "запросы" на задачи поступают от команд по мере образования вакуума на этапах… twitter.com/i/web/status/1…

13:50

Как только команда берет user story, в колонке "беклог" образуется вакуум. Это сигнал для продакта, что его нужно ч… twitter.com/i/web/status/1…

13:50

3) Визуализация — чем лучше визуализирован процесс, тем лучше команда понимает, в каком состоянии она находится, на… twitter.com/i/web/status/1…

13:50
@jsunderhood А зачем на проде то?

Не нужно при каждом вопросе подключать VPN для стенда, не нужно грепать по проекту — открыл сайт, выбрал нужный эле… twitter.com/i/web/status/1…

@jsunderhood А зачем на проде то?

13:53

Насколько важна визуализация процесса? Я для себя вывел, что хорошая визуализация решает 2 задачи:
1) Быстрее ориен… twitter.com/i/web/status/1…

14:36

Этот тред можно смело будет назвать — "о чем я бы хотел знать про визуализацию перед тем, как стал тимлидом"

14:36

Классический подход, который я встречал в куче мест: это когда заводят для задач разработчиков 5 колонок: туду, в р… twitter.com/i/web/status/1…

14:36

Тут мы сталкиваемся с первой проблемой. Если мы перевели задачку в тестирование, она тестируется или нет? Что с ней происходит?

14:36

Чтобы решить эту проблему, иногда возникает желание добавить метку или комментарий в задачку "ожидает тестирования"… twitter.com/i/web/status/1…

14:36

Это плохо тем, что любому члену команды, чтобы понять "а что там с задачей" придется открывать каждую задачу, искат… twitter.com/i/web/status/1…

14:36

Решением может быть разделение колонки Ревью на 2: "ревью: в процессе" и "ревью: готово". В этой системе тестировщи… twitter.com/i/web/status/1…

14:36

Решение легко масштабируется и на другие подобные проблемы. Мы получаем доску, на которой мы понимаем, что происход… twitter.com/i/web/status/1…

14:36

Вторая проблема: тестировщик находит критические баги в задаче. Выпускать нельзя. Здесь есть разные пути решения. М… twitter.com/i/web/status/1…

14:36

Зачем в этом случае такие навороты?

14:36

Задачка уже сделана, на нее уже потрачены силы\нервы\деньги\обсуждения. Приоритет такой задачи, скорее всего, выше,… twitter.com/i/web/status/1…

14:36

И тут мы подходим к такой штуке как определение приоритетов на доске.

14:36

Самый простой и "нативный" способ — это чтение справа налево по строкам. Т.е. мы сортируем наши swimlines по приори… twitter.com/i/web/status/1…

14:36

Члены команды при выборе очередной задачи проходят по этим swimlines и выбирают первую задачу, над которой они рабо… twitter.com/i/web/status/1…

14:36

В результате, если тестировщик перевесил задачку на разработчика, то разработчик, закончив текущую работу, открывае… twitter.com/i/web/status/1…

14:36

Преимуществом такого подхода является отсутствие излишних коммуникаций.

14:36

Этот подход можно использовать и для проведения стендапов. Идти по задачкам, справа налево. В теории, это позволяет… twitter.com/i/web/status/1…

14:36

Мы в двух командах пробовали сделать так для стендапа и каждый раз мы терпели фиаско. Потому что, во-первых, этот п… twitter.com/i/web/status/1…

14:36
У меня для вас подборка статей, как сделать качественный dropdown:

a11y-guidelines.orange.com/web_EN/exemple…;
—… twitter.com/i/web/status/1…

15:28
@jsunderhood Чувствуют-ли себя разработчики винтиками в системе?
Процесы - как по книге у Пименова - охренительные.… twitter.com/i/web/status/1…

Хороший вопрос! Если хочется просто "закрывать входящие таски и чтобы меня не трогали" то будет ощущения винтика. Н… twitter.com/i/web/status/1…

@jsunderhood Чувствуют-ли себя разработчики винтиками в системе?
Процесы - как по книге у Пименова - охренительные.… twitter.com/i/web/status/1…

16:00

HeadHunter не идеален, как и везде есть свои недостатки. Каждая команда может сама донастраивать процессы. Вот прям… twitter.com/i/web/status/1…

16:00

Поэтому главный инструмент, как и везде — общение и улучшение команды в которой работаешь, чтобы всем было комфортн… twitter.com/i/web/status/1…

16:00
@jsunderhood Зачем переводить задачу на тестировщика? QA просто берет из “to verify” и либо закрывает, либо перемещает обратно в “open”.

Переводить на тестировщика не обязательно, особенно, если есть отдельная колонка «ревью:готово», из которой тестиро… twitter.com/i/web/status/1…

@jsunderhood Зачем переводить задачу на тестировщика? QA просто берет из “to verify” и либо закрывает, либо перемещает обратно в “open”.

17:37

Потому что тестировщик должен писать в чат или делать какой-то другой call, что эту задачу нужно доделать. Все из-з… twitter.com/i/web/status/1…

17:37

А сакральным знанием «она уже готова, нужно ещё чуть-чуть» обладает только разработчик и тестировщик. И про эту зад… twitter.com/i/web/status/1…

17:37

Куда как проще тестировщику навесить задачку прямо на доске на разработчика, не меняя этапа. И как только начнётся… twitter.com/i/web/status/1…

17:37

Есть ещё одна причина тестировщика не идти / писать сразу в чат. Это асинхронность коммуникации. Разработчик может… twitter.com/i/web/status/1…

17:37

Правильно настроенная доска работает как single source of truth — сама может разрулить коммуникацию.

17:37
@jsunderhood Мы скорее не сталкивались с необходимостью это знать, на долго они там не задерживаются всё равно.

Хороший пример того, что не существует единого рецепта для всех.
Кому-то дополнительные колонки могут оказаться из… twitter.com/i/web/status/1…

@jsunderhood Мы скорее не сталкивались с необходимостью это знать, на долго они там не задерживаются всё равно.

18:02
@jsunderhood @boriscoder Делается очень просто: .parent-class :global('.child-class')
Подробнее: habr.com/ru/post/438834/

Клево! Вы все также создаете глобальный класс, но везде, кроме .parent-class он не будет иметь смысла, так как селе… twitter.com/i/web/status/1…

@jsunderhood @boriscoder Делается очень просто: .parent-class :global('.child-class')
Подробнее: habr.com/ru/post/438834/

18:37

Главное помнить, что это все еще css и если вы создадите просто :global(.child-class) то эти стили также применятся… twitter.com/i/web/status/1…

18:37
В моей карьере фронтендера было 2 жестких бага, на которые я убил кучу времени (примерно по 2 месяца) и понял, что… twitter.com/i/web/status/1…

Страшилки на ночь :)

В моей карьере фронтендера было 2 жестких бага, на которые я убил кучу времени (примерно по 2 месяца) и понял, что… twitter.com/i/web/status/1…

19:58
@jsunderhood @PaulMaly @boriscoder Критичные проблемы в Svelte 3 встречаются в сложных ситуациях, которые выходят з… twitter.com/i/web/status/1…
20:33

# Среда 93 твита

Вчера я спрашивал про иконки — было бы интересно послушать, что там нетривиального и как с ними работать. Иконки, д… twitter.com/i/web/status/1…

7:44

Тред про иконки. >>>

8:33

Ограничения в задаче: есть базовые иконки, которые используются везде. Есть специфические иконки, которые выполняют… twitter.com/i/web/status/1…

8:33

Сверху добавляем браузерную поддержку и желание, чтобы иконки кешировались, реиспользовались и работали на двух сте… twitter.com/i/web/status/1…

8:33

Накидываем, прототипируем варианты:

8:33

  • Inline svg. Идея проста: каждую svg вставляем inline в код. fill, stroke убираем и будем стилизовать иконку чере… twitter.com/i/web/status/1…
  • 8:33

    Код прототипа для inline варианта (вместе с кастомным webpack loader): gist.github.com/xnimorz/8dfe0c…
    Лоадер направляем на .svg иконки.

    8:33

    Выглядит просто и легко, но каждая иконка — это куча тегов в DOM, а значит куча данных, которые используются при SS… twitter.com/i/web/status/1…

    8:33

    В защиту решения: можно сделать поддержку многоцветных иконок, анимацию цветовых переходов.

    8:33

    2. Можем улучшить этот вариант и использовать inline svg + use директиву.

    8:33

    Идея такая: на этапе сборки превращаем все иконки в одну большую мега-иконку, где весь контент описан, например в `… twitter.com/i/web/status/1…

    8:33

    Код становится проще, нам уже не обязательно делать кастомный лоадер. Достаточно обычного react-компонента: gist.github.com/xnimorz/543dc8…

    8:33

    Вместо одной большой мега-иконки можно использовать другой подход: в компоненте icon храним singleton-Map, в ней от… twitter.com/i/web/status/1…

    8:33

    Если добавляется новая иконка, то вставляем эту иконку через `symbol`, помечаем в singleton и добавляем реальное ис… twitter.com/i/web/status/1…

    8:33

    Главная проблема подхода: у `<symbol>` должен быть id. А значит мы получаем опасность пересечений, если иконки не с… twitter.com/i/web/status/1…

    8:33

    Можно для иконок сделать решение аналогичное подходу css-modules и добавлять хеши например. Но мы начинаем строить… twitter.com/i/web/status/1…

    8:33

    Сама идея inline svg + use хороша и для многих проектов может зайти. Этот подход экономит и размер данных, и имеет… twitter.com/i/web/status/1…

    8:33

  • Спрайты. Старые-добрые спрайты. Сама иконка выглядит примерно так: gist.githubusercontent.com/xnimorz/e0f107… Через use задаем сост… twitter.com/i/web/status/1…
  • 8:33

    Теряем удобные анимации по сравнению с предыдущими случаями, получаем возможность работать с многоцветными иконками… twitter.com/i/web/status/1…

    8:33

  • Если вы не поддерживаете "старые" браузеры типа IE11, то можно выбрать хипстерский способ через filter. Работает… twitter.com/i/web/status/1…
  • 8:33

    Здесь есть даже готовый калькулятор таких стилей codepen.io/sosuke/pen/Pjo…

    8:33

    Главные минусы: вас будут не очень сильно любить за стили вида: filter: invert(17%) sepia(32%) saturate(5440%) hue-… twitter.com/i/web/status/1…

    8:33

    Здесь этот способ описан подробнее: css-tricks.com/solved-with-cs…
    Плюсы — удобно, все средствами css.

    8:33

  • Можно использовать css mask и затем через background-color задавать цвет. способ крайне простой, и нативно понят… twitter.com/i/web/status/1…
  • 8:33

  • Можно сделать свой иконочный шрифт. Про его проблемы не писал разве что ленивый. (отложенная загрузка, разное от… twitter.com/i/web/status/1…
  • 8:33

    Какое бы вы решение выбрали?

    8:33
    @jsunderhood Удобство это понятно, а что с оверхедом на размер бандла?

    Средняя длина имени - 50 букв, то есть 64 б… twitter.com/i/web/status/1…

    Сам бандл разбиваем на chunks по странице. Общий код для нескольких страниц выносится отдельно. В итоге:
    1) оверхед… twitter.com/i/web/status/1…

    @jsunderhood Удобство это понятно, а что с оверхедом на размер бандла?

    Средняя длина имени - 50 букв, то есть 64 б… twitter.com/i/web/status/1…

    9:01

    3) Мы проводили ряд АБ тестов направленных на улучшение и деградации производительности клиентского приложения, с ц… twitter.com/i/web/status/1…

    9:01

    И опять же данные сжимаем brotli, в итоге оверхед на страницу — меньше

    9:03
    6 ноября в Москве мы с HolyJS проведем Node.js Code+Learn.
    Это отличная возможность сделать вклад в разработку Node… twitter.com/i/web/status/1…
    10:09

    В опросе про иконки с большим отрывом лидирует вариант использовать inline иконки (с use тегом или без).
    Расскажу… twitter.com/i/web/status/1…

    11:59

    Если сейчас попытаться оценить решение, то
    по экономии размера, самыми эффективными будут решения через filter или… twitter.com/i/web/status/1…

    11:59

    Правильный выбор между этими решениями сделать сложно. Субъективно меня очень тянет к решениям с inline + use, filt… twitter.com/i/web/status/1…

    11:59

    Если вы не поддерживаете эти браузеры — рекомендую посмотреть в сторону filter или mask для иконок. Делается очень… twitter.com/i/web/status/1…

    11:59

    Выбираем из оставшегося.

    11:59

    Если рассматривать вариант просто inline без use. На моменте, когда вспоминается, что кроме React у тебя есть еще m… twitter.com/i/web/status/1…

    11:59

    В любой задаче приходится искать баланс. Решение должно позволять очень просто вставить иконку, но не должно быть к… twitter.com/i/web/status/1…

    11:59

    Пробуем вариант с inline svg + use. Само решение простое: мы инлайним + используем use при первой вставке иконки на… twitter.com/i/web/status/1…

    11:59

    Окей, это решается именем иконки — нам же все равно компонент вызывать с уникальным именем. А чтобы названия не пер… twitter.com/i/web/status/1…

    11:59

    Такое решение очень хорошо зайдет, особенно, если у вас single source of icons 😀.

    Поэтому, если задаетесь подобны… twitter.com/i/web/status/1…

    11:59

    Но на большом сайте можно столкнуться с тем, что самих иконок большое количество. Есть иконки UIToolkit, иконки отн… twitter.com/i/web/status/1…

    11:59

    В итоге, получаем, что у нас есть потенциальное место для коллизий и если не сводить все иконки в одно место при эт… twitter.com/i/web/status/1…

    11:59

    Остается вариант со спрайтами. Он дает чуть больший размер бандла по сравнению с inline + use и добавляет сложносте… twitter.com/i/web/status/1…

    11:59

    Возможные состояния у нас генерируются на less.
    Выглядит это так: миксину приходит набор состояний, например `.abst… twitter.com/i/web/status/1…

    11:59

    Затем через рекурсию создаются модификаторы: `icon_action, icon_primary icon_secondary` и модификаторы для hover, f… twitter.com/i/web/status/1…

    11:59

    Специфические иконки для сайтов генерируются по аналогичному механизму. UIToolkit предоставляет миксин, который сге… twitter.com/i/web/status/1…

    11:59

    Мораль этой истории?
    У нас есть N подходов и ни одного идеального. И это просто вставить иконку на страницу.

    11:59

    Справедливости ради сказать, если у вас нет поддержки ie11 и прочего, то inline + use, filters или mask вам хорошо подойдут

    13:02

    Давайте сегодня поговорим о миграциях.
    В случае в хх мы мигрируем с xslt + vanilla js + jquery на react стек.
    Я п… twitter.com/i/web/status/1…

    13:15

    Я, скорее всего, не открою ничего нового в самой миграции. Поэтому короткое резюме-спойлер:
    Мы переводим код на ре… twitter.com/i/web/status/1…

    13:24

    Микрофронтенды мы не делаем. Вместо этого — четкая структура проекта. Выглядит вот так: pic.twitter.com/Kixsb8WSYC

    13:24

    Каждая страницы — это отдельный chunk. На каждой странице, прямо внутри pages/PageName/component хранятся компонент… twitter.com/i/web/status/1…

    13:24

    Если компонент используется больше, чем на 1 странице, то он переезжает в shared.
    Chunk загружаем при запросе стра… twitter.com/i/web/status/1…

    13:24

    Так как при подобном переписывании кода получается много, он также выходит под фичей на часть пользователей. Если н… twitter.com/i/web/status/1…

    13:24

    Зачем вообще нужна миграция?

    13:25

    1) Скорость разработки — на новом стеке проще декомпозировать компоненты, люди находятся внутри одной технологии, ч… twitter.com/i/web/status/1…

    13:25

    2) Поддержка. Также вытекает из того, что поток данных четко направлен, все изменения проходят через единое место.… twitter.com/i/web/status/1…

    13:25

    3) Порог входа. У меня есть стойкое ощущение, что сейчас людей, которые больше хотят писать на условном реакте, про… twitter.com/i/web/status/1…

    13:25

    4) Хайп. Это момент, когда на рынке разработчики начинают крутить носом — у вас нет react, я к вам не пойду. Как бы… twitter.com/i/web/status/1…

    13:25

    Главная проблема миграции — бизнес хочет выпускать бизнес задачи, разработчики должны балансировать между техническ… twitter.com/i/web/status/1…

    14:01

    Какой алгоритм перевода страницы?

    Вначале нужен фундамент. Это вся инфраструктра — роутинг, дата-слой, разделение… twitter.com/i/web/status/1…

    14:03

    На этом фундаменте можно строить страницу.
    Обычно здесь все происходит по типовому сценарию: посмотрели какие комп… twitter.com/i/web/status/1…

    14:03

    Что при переходе важного?

    Наиболее критическим моментом для нас является наличие SSR. Потому что это SEO, это хор… twitter.com/i/web/status/1…

    14:04

    Тут мы подходим к важной теме SSR (server side rendering).
    Здесь мои коллеги уже писали о SSR в хх… twitter.com/i/web/status/1…

    14:15

    1) node.js не занимается походами на бекенды. Мы сделали SSR as a service. То есть есть питонячье приложение, котор… twitter.com/i/web/status/1…

    14:15

    Урл у нас всегда один `/render`. Информация о реальном урле и данных лежит в body запроса.
    Схематично это выглядит… twitter.com/i/web/status/1…

    14:15

    На сервере крутится Koa (выбирали между express, koa и hapi). express не взяли — были проблемы в секьюрности, hapi… twitter.com/i/web/status/1…

    14:15

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

    14:15

    Каждый инстанс ноды запускает внутри себя Clusters по количеству ядер выделенных контейнеру:… twitter.com/i/web/status/1…

    14:15

    Код вызова рендера очень простой умещается на десяток строк вместе с обработкой ошибок: gist.github.com/xnimorz/2a6283…
    То… twitter.com/i/web/status/1…

    14:15

    Это позволило нам сделать SSR не переделывая специальным образом клиентскую часть (а вызовы window.something и подо… twitter.com/i/web/status/1…

    14:15

    Мониторим сервер через okmeter: okmeter.io

    14:15

    Контейнеров node.js много и тут появляется задача: как выпускать обратно несовместимые релизы? Когда в питоне с нов… twitter.com/i/web/status/1…

    14:15

    С одной стороны можно сохранить обратно-совместимые релизы и на такие изменения делать 2-3 релиза паровозиком (друг… twitter.com/i/web/status/1…

    14:15

    Тут на помощь приходит "хитрый" метод: у питонячьего приложения и node.js рендер сервера единая версия. То есть пос… twitter.com/i/web/status/1…

    14:15

    Делим группу Node.js серверов на 2 и вначале катим релиз на половину машин.
    Когда релиз раскатился, катим релиз на… twitter.com/i/web/status/1…

    14:15

    Остается посыпать решение инфраструктурой:
    питон приложение идет в node.js с указанием версии. Node.js перед рендер… twitter.com/i/web/status/1…

    14:15

    Если нет, отправляем 503. Питон получает 503 и пытается заретраить запрос на другой сервер. количество ретраев = ко… twitter.com/i/web/status/1…

    14:15

    Можно пойти дальше и завести единое место с конфигом, которое будет балансировать и знать, где-какая версия раскаче… twitter.com/i/web/status/1…

    14:15

    Если у вас есть еще вопросы про SSR или миграцию — пишите, с радостью отвечу на что смогу :)

    14:19
    @jsunderhood А делали какое-нибудь сравнение этого подхода с подходом «1 процесс (ядро) на 1 контейнер» (то есть, без кластера)?

    Да, когда только внедряли проверяли, насколько будет рост, если использовать cluster и будет ли он.
    При включении… twitter.com/i/web/status/1…

    @jsunderhood А делали какое-нибудь сравнение этого подхода с подходом «1 процесс (ядро) на 1 контейнер» (то есть, без кластера)?

    14:36
    @jsunderhood Но это же ваще оценочное мнение, так ведь? Которое вообще ничего общего может не иметь с реальной жизнью.

    Отчасти да, отчасти нет. Поясню, крайне сложно для суждения привести абсолютно идеальные данные. Никто не будет дел… twitter.com/i/web/status/1…

    @jsunderhood Но это же ваще оценочное мнение, так ведь? Которое вообще ничего общего может не иметь с реальной жизнью.

    15:57

    В то же время, мы измеряем lead time всего процесса разработки и lead time только разработки. Если выбрать задачи,… twitter.com/i/web/status/1…

    15:57

    Это не на 100% идеальный способ, но чем больше задач делает команда на странице, тем более репрезентативна выборка.… twitter.com/i/web/status/1…

    15:57

    И тут я сам же поломаю свой довод :) во время переписывания происходит ещё рефакторинг кода, что упрощает дальнейшу… twitter.com/i/web/status/1…

    15:57

    Важный момент: мы измеряем lead time не для сравнений, а для рефлексии, чтобы понимать, какие вопросы и трудности у команды были.

    15:57
    @jsunderhood И где-то здесь ещё передают привет микросервисы ;)
    17:57
    @jsunderhood А что происходит с глобальными задачами из разряда - обновить какую-то либу на следующий мажор по всем… twitter.com/i/web/status/1…

    Все зависит от размера проблемы. Если задача достаточно большая, то работает +/- так:
    1) Задача описывается в jira,… twitter.com/i/web/status/1…

    @jsunderhood А что происходит с глобальными задачами из разряда - обновить какую-то либу на следующий мажор по всем… twitter.com/i/web/status/1…

    19:19

    2) Определяется приоритет задачи. Раньше мы пытались использовать для приоритетов RAF (Risk assessments framework)… twitter.com/i/web/status/1…

    19:19

    3) Команды, если планируют взять тех. задачу видят все задачи и выбирают исходя из приоритета + времени, которое он… twitter.com/i/web/status/1…

    19:19

    4) Если команда архитектуры понимает, что вряд ли кто-то возьмет эту задачу в ближайшем будущем, а профит от задачи… twitter.com/i/web/status/1…

    19:19

    Для синка у нас есть 2 типа встреч. Тимлидский статус-синк и синк фронтенд группы. (это помимо внутрикомандных стен… twitter.com/i/web/status/1…

    19:19
    @jsunderhood Я обычно использую <img src=my.svg> в доме, а затем динамически подгружаю и заменяю инлайновым <svg>

    Еще один способ решения задачи :)

    @jsunderhood Я обычно использую <img src=my.svg> в доме, а затем динамически подгружаю и заменяю инлайновым <svg>

    19:19

    # Четверг 81 твит

    @jsunderhood Ну а как вы на питоне вырезаете все фетч запросы что бы сходить на сервер за данными?

    Расскажу как работает роутинг:
    Для роутинга используем обычный react-router. Для SPA переходов между страницами ест… twitter.com/i/web/status/1…

    @jsunderhood Ну а как вы на питоне вырезаете все фетч запросы что бы сходить на сервер за данными?

    8:19

    Выглядит это вот так: gist.github.com/xnimorz/5a2783…
    preload для компонентов вытаскивается через React-loadable

    8:19

    За chunk с данными ходим, чтобы данные в стор записались в тот момент, когда chunk будет предзагружен и страница ср… twitter.com/i/web/status/1…

    8:19

    Чтобы серверная нода не слала запросы, мы в коде конфигурации стора проверяем наш environment и в случае сборки для… twitter.com/i/web/status/1…

    8:19
    Какое бы вы решение выбрали?

    Результаты голосования по иконкам. 60% за вариации inline иконок

    Какое бы вы решение выбрали?

    8:41
    @jsunderhood Еще в защиту такого подхода - большинство проблем можно нивелизровать, загрузив иконку через iframe.
    Л… twitter.com/i/web/status/1…

    Еще про иконки :)
    Но мне такой вариант кажется усложнённым, по сравнению с ленивой загрузкой и использованием use… twitter.com/i/web/status/1…

    @jsunderhood Еще в защиту такого подхода - большинство проблем можно нивелизровать, загрузив иконку через iframe.
    Л… twitter.com/i/web/status/1…

    10:04
    Понадобилось отрендерить табличку 500х50 ячеек, клик на каждую ячейку тогглит её в инпут и обратно. React убивает б… twitter.com/i/web/status/1…

    Я решал похожую задачу на реакте, и учитывая, что в реакте есть встроенное делегирование событий, проблема может бы… twitter.com/i/web/status/1…

    Понадобилось отрендерить табличку 500х50 ячеек, клик на каждую ячейку тогглит её в инпут и обратно. React убивает б… twitter.com/i/web/status/1…

    10:21

    Ну, и в подобных историях наиболее правильный подход: это сделать замер через performance и посмотреть, на что дейс… twitter.com/i/web/status/1…

    10:21
    @jsunderhood @PaulMaly Да, про него. Ага, понял. Ну да, можно наверное попробовать какой-то такой вариант. Потому ч… twitter.com/i/web/status/1…
    10:35
    Хм. My bad. Где-то накосячил и нагрешил на React. Он вполне себе отрендерил 25к ячеек и никто не умер @jsunderhood @andrey_sitnik

    К прошлому треду про производительность либ:

    Хм. My bad. Где-то накосячил и нагрешил на React. Он вполне себе отрендерил 25к ячеек и никто не умер @jsunderhood @andrey_sitnik

    10:55

    Мы тут немного поговорили про оптимизацию, в дополнение расскажу 3 маленьких и очень простых, но интересных момента… twitter.com/i/web/status/1…

    13:08

    1) При вызове setState, который мы получаем из хука useState реакт проводит сравнение prev и next результата (==).… twitter.com/i/web/status/1…

    13:08

    Это означает, что если вы сделаете что-то вроде const [a, setA] = useState(1); ... setA(1);, то компонент не будет перерендерен.

    13:08

    Но если ваш родитель ререндерится, то child также будет ререндериться, никаких сравнений props не будет, все полнос… twitter.com/i/web/status/1…

    13:08

    Вот тут небольшой пример codesandbox.io/s/fervent-shad…

    13:08

    Я пару раз сталкивался с непониманием коллег, почему в стейте поведение одно, а в пропс другое. Дело в том, что одн… twitter.com/i/web/status/1…

    13:08

    По этой причине, недостаточно просто обернуть все мемоизацией. Чтобы избежать вызова render функций, компонент долж… twitter.com/i/web/status/1…

    13:08

    Для функциональных компонентов memo также принимает второй аргумент. Он нужен для кастомного компаратора, аналогичн… twitter.com/i/web/status/1…

    13:08

    2) Важный момент, о котором многие забывают: контексту плевать, обернут ли у вас компонент в memo или он pure. Если… twitter.com/i/web/status/1…

    13:08

    Проверить и поэкспериментировать очень легко: codesandbox.io/s/agitated-wil…

    13:08

    Обратите внимание, что изменение контекста не просто обновляет компонент, но он получает еще и самый последний prop.

    13:08

    3) Все привыкли использовать useEffect для сайд-эффектов, каких-то DOM расчетов. Может появиться вопрос: а почему я… twitter.com/i/web/status/1…

    13:08

    Если хочется рассчитать ДО того, как компонент отрисуется (как раньше с componentDidUpdate), то стоит использовать… twitter.com/i/web/status/1…

    13:08

    Hint, если в codesandbox хочется снять performance можно открыть урл, который они предоставляют:… twitter.com/i/web/status/1…

    13:08

    Обратите внимание на разницу в количествах и характере paint :)

    13:08
    В @biocad_ltd, ищем QA-инженера, вместе со мной работать над системой управления лабораторным оборудованием.

    Сейча… twitter.com/i/web/status/1…

    14:02
    2) Важный момент, о котором многие забывают: контексту плевать, обернут ли у вас компонент в memo или он pure. Если… twitter.com/i/web/status/1…

    Напутал с ссылками на примере. Правильная ссылка вот: codesandbox.io/s/fancy-feathe…

    2) Важный момент, о котором многие забывают: контексту плевать, обернут ли у вас компонент в memo или он pure. Если… twitter.com/i/web/status/1…

    14:08

    Для истории с контекстом правильная ссылка codesandbox.io/s/fancy-feathe…

    14:08
    @jsunderhood Будет тред о том как стать хорошим специалистом? (не xslt 😁 спецом, а в общем)

    Вчера был вопрос о развитии. У меня нет хорошего ответа на него. Поэтому дальше будет тред о том, как я представляю… twitter.com/i/web/status/1…

    @jsunderhood Будет тред о том как стать хорошим специалистом? (не xslt 😁 спецом, а в общем)

    14:09

    Для меня есть несколько больших мазков в градациях. Джун => Мидл => а вот тут все сложнее.

    14:09

    Сюда традиционно добавляют senior, что это человек, который может взять задачу, проанализировать, выбрать подходящи… twitter.com/i/web/status/1…

    14:09

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

    14:09

    Давайте с вопросом развития начнем с простого и дальше будем двигаться к сложному. Начнем об обучении джунов. В хх… twitter.com/i/web/status/1…

    14:14

    Школа устроена следующим образом. На входе будущие студенты решают несколько задач онлайн, затем офлайн интервью. Э… twitter.com/i/web/status/1…

    14:14

    Как подготовиться к подобным интервью как раз писал предыдущий автор этого твиттера :)

    14:14

    Сама школа разделена на 2 части: лекции и работа над проектом. Лекции проходят 2-3 раза в неделю.

    14:14

    В прошлом году лекции записывали: youtube.com/watch?v=7tULJl…
    Обучение идет по 2-м направлениям фронтенд и бекенд. Бек… twitter.com/i/web/status/1…

    14:14

    У лекций есть ДЗ. Я обычно стараюсь после выдачи ДЗ отвечать на вопросы, проводить ревью решения студента как можно… twitter.com/i/web/status/1…

    14:14

    Список моих лекций есть здесь: xnim.ru/projects/schoo…

    14:14

    У меня была пара веселых моментов. Провожу лекцию по базовому js, в конце даю домашку. Добираюсь до дома (мне ехать… twitter.com/i/web/status/1…

    14:14

    Вторая история. Мои лекции часто расположены перед НГ. В таких случаях я даю дедлайн в новогодние каникулы плюс 2-3… twitter.com/i/web/status/1…

    14:14

    После блока лекций начинается практика. Студенты делятся на группы и занимаются школьными проектами. Я в свое время… twitter.com/i/web/status/1…

    14:14

    Эти проекты нужны, чтобы вчерашние студенты попробовали работу в команде, у них появились первые конфликты (возможн… twitter.com/i/web/status/1…

    14:14

    В последних двух школах студенты делали проекты, которые потом нашли свое использование. В школе 2017-2018 года я б… twitter.com/i/web/status/1…

    14:15

    Также знаю, что есть стажировки у avito start.avito.ru/tech, школа интерфейсов яндекса yandex.ru/promo/academy/… Возможно еще что-то?

    14:15

    Не могу не упомянуть очень крутой кейс от @idelpivnitskiy youtube.com/watch?v=Kw1gQT…
    Идель, привет :) Кстати, Идель т… twitter.com/i/web/status/1…

    14:15

    С началом пути в разработке разобрались. Дальше от средних-крепких джунов в мидлы и развитие мидлов. Это тот момент… twitter.com/i/web/status/1…

    14:23

    В части компаний есть менторы, где-то этим занимаются тимлиды, где-то делают основательный подход с составлением ИК… twitter.com/i/web/status/1…

    14:23

    Мне сложно дать рецепт, у меня нет правильного ответа на вопрос. Только мои личные наблюдения. Мне кажется, что раз… twitter.com/i/web/status/1…

    14:23

    Хочешь прокачаться во фронтенд скиллах — возьми ответственность за часть проекта, стань мейнтейнером страниц или пр… twitter.com/i/web/status/1…

    14:23

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

    14:23

    Без ответственности это работает сильно хуже. Как то так:
    — Привет. Я хочу развиваться давай обсудим?
    — Хорошо, у н… twitter.com/i/web/status/1…

    14:23

    Тут также работает следующее: без желания людей насильно "развивать" их не будешь.

    14:23

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

    14:23

    Кроме этого, в некоторых компаниях практикуется "добровольное менторство" — когда часть более опытных сотрудников,… twitter.com/i/web/status/1…

    14:23

    Если свести все в пункты, то:

    Я хочу развиваться:
    1) Брать ответственность, принимать решения
    2) Участвовать в обсуждения фронтенд-группы

    14:23

    3) Если в компании не видно точек роста, то смотреть на опен-сорс, сообщества в своем городе
    4) Если на 3-й пункт н… twitter.com/i/web/status/1…

    14:23

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

    14:23

    Если "Я хочу помогать сотрудникам в развитии", то:
    1) Ненавязчиво предлагать ответственность — ни в коем случае нел… twitter.com/i/web/status/1…

    14:23

    3) Давать сотрудникам задания сложнее их текущего уровня.

    14:23

    Как я пришел к таким пунктам? Вот мой личный опыт:

    14:23

    В хх я пришел в команду поиска. Нас было 2 фронтендера. За полгода текущие задачи поиска были закрыты и я заскучал.… twitter.com/i/web/status/1…

    14:23

    Настроили его подключение через npm, отделили от проекта, сделали сборку на gulp вместо make файла. Развили саму би… twitter.com/i/web/status/1…

    14:23

    Затем перешел в команду мобильного сайта, где взял ответственность на архитектуру резюмебилдера на клиенте. Очень б… twitter.com/i/web/status/1…

    14:23

    И затем перешел в проект talantix.ru, где был, по сути, создателем всей архитектуры проекта.
    В конце пу… twitter.com/i/web/status/1…

    14:23

    С каждым разом в том числе изучал этот вопрос и приходил к мысли: "если бы не ответственность, то всегда можно было… twitter.com/i/web/status/1…

    14:23

    Так я и пришел к выводам из начала этого треда :)

    14:23

    Я не затронул тему развития софт-скиллов в своем рассказе, это отдельная и очень сложная тема. Ответственность в ко… twitter.com/i/web/status/1…

    14:23
    С началом пути в разработке разобрались. Дальше от средних-крепких джунов в мидлы и развитие мидлов. Это тот момент… twitter.com/i/web/status/1…

    Начало пути в разработку: twitter.com/jsunderhood/st…

    О росте мидлов:

    С началом пути в разработке разобрались. Дальше от средних-крепких джунов в мидлы и развитие мидлов. Это тот момент… twitter.com/i/web/status/1…

    14:24

    Помогите мне определиться с темой на завтра: я думал о том, чтобы рассказать о performance и клиентских метриках ил… twitter.com/i/web/status/1…

    14:30

    Если что другая тема вполне может быть в субботу :) мне интересен порядок

    14:32
    @m0rg0t @jsunderhood Мы в @mtdvio делаем материалы и коммьюнити про холистическое развитие (вне рамок одной компани… twitter.com/i/web/status/1…
    15:40
    @jsunderhood Плюсую. В целом правильный общий совет.

    Стать сильным Senior можно, если рутинно берёшь на себя зада… twitter.com/i/web/status/1…

    15:40
    @jsunderhood Вообще всего это будет неявно и капать по капле. Пока в один прекрасный день ты не осознаешь, что ты и… twitter.com/i/web/status/1…
    15:59
    @jsunderhood Но при этом смотришь на других и все равно видишь что много где отстаёшь от багажа знаний других людей.

    Ощущение, что «все вокруг круче меня» складывается потому что Вова умеет лучше верстать, Маша сильнее в алгоритмах,… twitter.com/i/web/status/1…

    @jsunderhood Но при этом смотришь на других и все равно видишь что много где отстаёшь от багажа знаний других людей.

    16:03

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

    16:03
    @jsunderhood @Oleg75113370 Пару готовых рецептов подкину.

    Общего плана про планирование карьеры, основанные на на… twitter.com/i/web/status/1…

    16:04
    Помогите мне определиться с темой на завтра: я думал о том, чтобы рассказать о performance и клиентских метриках ил… twitter.com/i/web/status/1…

    В голосовалке победили пятничные байки :) Завтра будем говорить о разных смешных, интересных случаях из рабочей и н… twitter.com/i/web/status/1…

    Помогите мне определиться с темой на завтра: я думал о том, чтобы рассказать о performance и клиентских метриках ил… twitter.com/i/web/status/1…

    19:37
    @vfurso @jsunderhood Повлиять на бизнес анализ, продукт, решения других отделов разработчик практически никогда не… twitter.com/i/web/status/1…
    20:08

    # Пятница 73 твита

    Сегодня травим байки о разработке!
    Начнем прямо со вчерашнего фейла. У кого не бывает фейлов, тот явно что-то недоговаривает :)

    7:33

    Обновляю картинки-иконки в статике. Релиз выходит, и вроде бы все хорошо.
    Прилетает бага. На… twitter.com/i/web/status/1…

    7:33

    У нас единое приложение для hh.ru, jobs.tyt.by и других доменов. На основном домене… twitter.com/i/web/status/1…

    7:33

    Оказывается проблема с политиками кеширования, с nginx.org/ru/docs/http/n… На всех региональных сайтах политика жестч… twitter.com/i/web/status/1…

    7:33

    Все картинки у нас запрашиваются с GET запросом, если uri не поменялся, nginx отдаст старую картинку. Сравните:… twitter.com/i/web/status/1…

    7:33

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

    7:33
    @jsunderhood Ооо! А какие отличия между сайтами на разных доменах? А как организовано? С какими проблемами столкнул… twitter.com/i/web/status/1…

    Нет, про это не рассказывал. Попробую описать фактами:

    @jsunderhood Ооо! А какие отличия между сайтами на разных доменах? А как организовано? С какими проблемами столкнул… twitter.com/i/web/status/1…

    8:10

    1) Кодовая база одна, отличия между сайтами описываются явно в коде (даже до уровня if (domain === DOMAINS.KAZAHSTAN))

    8:11

    2) Есть необходимость учитывать страновую политику: сервера, определенные законы. Например, была история, когда в о… twitter.com/i/web/status/1…

    8:11

    Лично для меня (я не девопс все же), это главная особенность: в странах отличаются законы, эти законы необходимо уч… twitter.com/i/web/status/1…

    8:11

    3) Обычно мониторим все законы в странах и заранее пишем код. В нужный момент просто переключаем рубильник

    8:11

    4) Страновые сайты отличаются не только логикой в определенных местах, но и, например, кешированием статики, так ка… twitter.com/i/web/status/1…

    8:11

    5) Домены разруливаются на nginx, почти любой бекенд при необходимости может узнать о том, на каком сайте был вызва… twitter.com/i/web/status/1…

    8:11

    6) Каждому домену соответствует константа, констаны в том числе есть в конфигах yml, чтобы при сборке использовать… twitter.com/i/web/status/1…

    8:11

    7) Переводы хранятся в базе, каждый сервис подгружает переводы себе на старте. Используем marisa-trie структуру дан… twitter.com/i/web/status/1…

    8:11

    8) Возможно для меня привычно, но это все особенности, на первый взгляд. Возможно есть какие-то определенные вопросы?)

    8:11
    Совсем забегался и упустил выход интереснейшего интервью с @iamakulov 😢

    Всем любителям производительности и оптими… twitter.com/i/web/status/1…

    8:31

    Небольшая залипашка: matthewrayfield.com/goodies/inspec…
    (нужна консоль разработчика)

    8:44

    Следующая занимательная история:
    Теплое весеннее утро. Кто-то ползет к офису, кто-то, зевая, заваривает кофе. Приле… twitter.com/i/web/status/1…

    9:26

    Разработчики бегут к ноутам, начинают разбирать проблему... Все работает, все хорошо. Жалобы продолжают поступать.… twitter.com/i/web/status/1…

    9:26

    Начинаем проверять все возможные цепочки, какие запросы уходят, что происходит. Все равно все хорошо.

    9:26

    Потратив около 3 человеко-дня (3 разработчика на 1 день ушли в проблему), выяснилось, что им просто не повезло. Они не собачники 0_о

    9:26

    Все дело в том, что поставщик рекламы добавил новый баннер для пользователей, рекламирующий собачий корм. Этот банн… twitter.com/i/web/status/1…

    9:26

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

    9:26
    We are interested in what you think about your next 3-5 years.

    What do you personally want to focus on?

    This is… twitter.com/i/web/status/1…

    10:18
    @jsunderhood А разве сейчас не принято пихать рекламные банеры в iframe? Типа безопасность, вот это вот всё

    История давняя. Именно по результатам истории приняли два решения:
    1) Реклама ломать нас не должна
    2) Реклама должн… twitter.com/i/web/status/1…

    @jsunderhood А разве сейчас не принято пихать рекламные банеры в iframe? Типа безопасность, вот это вот всё

    12:14

    Пришлось отвлечься, сейчас делаем одну интересную штуку: на получение страницы создаем общий action, который инкапс… twitter.com/i/web/status/1…

    12:16

    Когда я говорил про layout, вспомнил одну штуку: вы пользуетесь performance вкладкой чтобы оценить время исполнения… twitter.com/i/web/status/1…

    12:18

    Кликаем на строку кода, получаем красоту: pic.twitter.com/CTmrJDtWAW

    12:18

    С сурсмапами у меня нормально не завелось :(

    12:18

    Детективная история. История вымышлена от начала до конца, любые совпадения абсолютно случаны. В главных ролях: ком… twitter.com/i/web/status/1…

    12:41

    А: Сайт не работает.
    С: Стандартное выяснение проблем, статусов ответа
    А: Уточняют, что открывают страницу, страниц… twitter.com/i/web/status/1…

    12:41

    С: Передает данные КР.
    КР: В консоли ничего нет.
    КР: (Замечают часы в углу скриншота, грепают логи)
    КР: За это вр… twitter.com/i/web/status/1…

    12:41

    КР: Сделайте har файл с запросами
    С: рассказывает как сделать har файл
    А: вот
    C: эй, КР, вот har файл

    12:41

    КР: так, что тут у нас... Так все ж хорошо?
    С: сейчас узнаем
    А: Да, мы чтобы записывать har файл файрвол отключали
    КР: :facepalm:

    12:41

    В чем соль — файрвол резал запросы и они просто не доходили до нас.

    12:41
    Этот момент настал!
    Я ищу работу - HTML-верстальщик, frontend-разработчик.
    Естественно, я ещё джуниор.

    Ссылки на р… twitter.com/i/web/status/1…

    12:51

    Сейчас будет сложная история с техническими подробностями. История о сложностях работы с переводами на сайте.
    Исто… twitter.com/i/web/status/1…

    13:19

    1) Переводов больше десятка мегабайт
    2) Не все переводы интерфейсные (интерфейсных только пара мегабайт), но тоже н… twitter.com/i/web/status/1…

    13:19

    Как решать такую проблему?

    13:19

    Мы пришли к такой модели:
    1) В реакт-компонентах появляется поле static trls поле, которое является обычной Map<Str… twitter.com/i/web/status/1…

    13:19

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

    13:19

    3) При сборке кода babel плагин выдирает поле trls, собирает большую мапу "страница: список переводов". Этот файл п… twitter.com/i/web/status/1…

    13:19

    4) На бекендах переводы подгружаются из базы при старте и затем время от времени получают обновления. В рантайме хр… twitter.com/i/web/status/1…

    13:19

    Кстати, плагин, который выдирает статические поля вот: github.com/hhru/babel-plu…

    13:19

    Казалось бы, хорошее решение, легко использовать.
    Все так, но в сентри начинают приходить баги, что перевода нет.

    13:19

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

    13:19

    Делаем первый заход, понимаем, что страница например bla-bla, а данные в сторе от страницы foo-bar.

    13:19

    Разбираемся в проблеме, понимаем, что в некоторых редьюсерах данные применяются вот так: (state, action) => bla-bla… twitter.com/i/web/status/1…

    13:19
    Quite a tricky thing in spread operator: you can spread `undefined` in object like `{...undefined}`, but you can't… twitter.com/i/web/status/1…

    В чем соль 1: Оператор ... очень хитрый оператор. Я писал об этом здесь: twitter.com/xnimorz/status… И поэтому он может… twitter.com/i/web/status/1…

    Quite a tricky thing in spread operator: you can spread `undefined` in object like `{...undefined}`, but you can't… twitter.com/i/web/status/1…

    13:19

    В чем соль 2: мы используем batch actions и делаем батчевый редьюсер. Если падает применение данных в одно из полей… twitter.com/i/web/status/1…

    13:19

    Переводы хранятся в сторе. И по стечению обстоятельств — переводы первыми вызываются на странице. Вот они и падают.

    13:19

    Окей, почему мы не получали правильную ошибку? Оказалось, потому что случайно поставили на promise, который обрабат… twitter.com/i/web/status/1…

    13:19

    Вот так один неверный reject привел к долгой истории и правкам редьюсеров.

    13:19

    Но на этом все не закончилось! Ошибка всплывает опять. Начинаем разбираться, находим проблему в фетчере и асинхронн… twitter.com/i/web/status/1…

    13:19

    Пять подобных итераций и полгода спустя мы из-за этой ошибки отрефакторили кучу мест, каждый раз получалось ее восп… twitter.com/i/web/status/1…

    13:19

    Немного расскажу о концепции батчевых экшенов и батчевом редьюсере в Redux
    В редьюсерах у нас много полей. Я не счи… twitter.com/i/web/status/1…

    14:02

    TL;DR Сразу решение: gist.github.com/xnimorz/352a6c…
    В коде привел объяснение подхода. Дальше в треде будет история: какую… twitter.com/i/web/status/1…

    14:02

    Мы сделали систему, где при SPA переходе вызывается middleware, она делает GET запрос самостоятельно на нужный урл.… twitter.com/i/web/status/1…

    14:02

    У нас нет списка "вызови такие-то экшены при открытии такого-то урла", вместо этого, мы проходим по полям JSON и со… twitter.com/i/web/status/1…

    14:02

    Базовый экшен — у каждого редьюсера у нас есть экшен, который занимается тем, что передает данные as is в редьюсер… twitter.com/i/web/status/1…

    14:02

    Мы сейчас идем к тому, чтобы такие редьюсеры описывались еще проще: в конфиге стора была запись currency: typicalReducer();

    14:02

    Таких экшенов на большой JSON получается много. Они все записываются в массив actions и затем мы делаем dispatch(actions).

    14:02

    Мы диспатчим сразу массив экшенов, который на уровне рутового редьюсера итерируется и применяется вот так (ссылка с… twitter.com/i/web/status/1…

    14:02

    Какие преимущества подхода:
    1) Мы не завязаны на порядок применения. Либо все редьюсеры разово применились, либо н… twitter.com/i/web/status/1…

    14:02
    @jsunderhood Добрый вечер! Расскажите, пожалуйста, подробнее о том, как удается при таком серьезном продукте и боль… twitter.com/i/web/status/1…

    У каждой команды свой продакт (1 продакт может быть заказчиком у нескольких команд). И у каждой команды свой беклог… twitter.com/i/web/status/1…

    @jsunderhood Добрый вечер! Расскажите, пожалуйста, подробнее о том, как удается при таком серьезном продукте и боль… twitter.com/i/web/status/1…

    17:05

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

    17:05

    Вместо этого у нас единый набор технологий на большей части проектов. Где-то есть специфика (например поисковой дви… twitter.com/i/web/status/1…

    17:05

    Тестирует задачу, пишет автотесты (иногда автотесты делаем после выхода задачи) Во время и после выхода релиза у на… twitter.com/i/web/status/1…

    17:05

    Большое количество фичей выходит под настройкой (переключателем). Если что-то идет не так, то команде достаточно пе… twitter.com/i/web/status/1…

    17:05

    Если все же баг случился через некоторое время после выхода задачи, то по blame видим, какая команда и назначаем на… twitter.com/i/web/status/1…

    17:05

    И если проблема произошла на странице поиск — баг летит в команду поиск. Они, в свою очередь, могут определить чей… twitter.com/i/web/status/1…

    17:05
    Пока вел @jsunderhood, мне сказали что бек на nodejs - это "поделка из желудей", а тут dartup.ru пров… twitter.com/i/web/status/1…

    Я за желуди ¯\_(ツ)_/¯

    Пока вел @jsunderhood, мне сказали что бек на nodejs - это "поделка из желудей", а тут dartup.ru пров… twitter.com/i/web/status/1…

    21:56

    # Суббота 103 твита

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

    6:37

    Я выступал на РИТ++ youtube.com/watch?v=4joeMk…, рассказывал о сборе метрик и частично затрагивал эксперименты с производительностью.

    6:39

    Материалы по докладу: github.com/xnimorz/Fronte…
    Сегодня подробнее поговорим про это.

    6:39

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

    6:39

    Желание трекать метрики и реагировать на них зародилось у нас очень давно. Вначале это был обычный набор метрик, на… twitter.com/i/web/status/1…

    8:28

    Затем мы сделали более серьезный заход на эту задачу и организовали подсчет таких метрик как FMP (first meaningful… twitter.com/i/web/status/1…

    8:28

    Дальше будут треды с подсчетом метрик.

    8:28

    FMP — от него хотим следующего: понимание нашего critical path, количества времени которое уходит на него. Дальше… twitter.com/i/web/status/1…

    9:07

    TL;DR: мы пришли к такому решению: gist.github.com/xnimorz/8ec4fc…
    Это позволяет нам трекать critical path, понимать, когда… twitter.com/i/web/status/1…

    9:07

    Дальше история того, как мы к этому шли и графики, графики!)

    9:07

    С одной стороны, FMP говорит о том, что нужно трекать, когда контент отобразился. И тогда код будет что-то вроде та… twitter.com/i/web/status/1…

    9:07

    Offtop, но если вы сделаете блокирующий вызов для того, чтобы кеш сработал, я вас удивлю: кеш может не сработать та… twitter.com/i/web/status/1…

    9:07

    Если затрекать такое время от gist.github.com/xnimorz/6b939a… и выводить на график, получим вот такую чушь: pic.twitter.com/j0mFLQiKek

    9:07

    Почему чушь?
    1) 99 перцентиль составляет больше 100 секунд. Представьте людей, которые настолько терпеливы? :)
    2)… twitter.com/i/web/status/1…

    9:07

    Вспоминаем вчерашнюю историю про "сайт грузится и не работает 30 секунд". Понимаем, что если пользователям приходил… twitter.com/i/web/status/1…

    9:07

    Почему так происходит? Если пользователь переключит вкладку, то raf не будет исполняться, пока вкладка не станет ак… twitter.com/i/web/status/1…

    9:07

    Какое может быть решение? Трекать активность страницы!
    В коде это будет так: gist.github.com/xnimorz/917a57… здесь скрипт,… twitter.com/i/web/status/1…

    9:07

    Насколько отличается первый и второй вариант? Вот графики:
    Первый вариант 95-я перцентиль (без трека visibility pag… twitter.com/i/web/status/1…

    9:07

    Вот вариант, когда убираем значения, если пользователь уходил со страницы, или открывал фоновую вкладку: pic.twitter.com/z63MCQDFd0

    9:07

    Здесь уже видим, что значения похожи на правду: 1 секунда загрузка резюме, самая тяжелая страница: 2.6 секунды.

    9:07

    У второго варианта есть проблема. Он не трекает многих пользователей, так как один из популярных паттернов у пользо… twitter.com/i/web/status/1…

    9:07

    Здесь может прийти идея трекать новые DOM метрики, которые уже есть в браузерах, но они также плохо учитывают неакт… twitter.com/i/web/status/1…

    9:07

    Как научиться трекать остальных пользователей? Исполнять скрипт, который не зависит от raf 🙂
    Это можем сделать, пр… twitter.com/i/web/status/1…

    9:07

    Это позволяет нам делать аналитику, потому что у нас уже есть renderTree.
    Делаем это вот так:… twitter.com/i/web/status/1…

    9:07

    Если сравнить со вторым вариантом, разница оказывается не такой большой, как можно было предположить 100-300мс. А о… twitter.com/i/web/status/1…

    9:07

    На график выводим 95-ю перцентиль. Т.е. у 95% пользователей страница отображается не дольше, чем за это время на гр… twitter.com/i/web/status/1…

    9:07

    95" график важного контента (+/- первый экран): pic.twitter.com/RTIy4vfenp

    9:07

    95" то же время, но с засечкой body: pic.twitter.com/ASnZ10M0A9

    9:07

    Для сравнения вот 50 перцентиль за тоже время у body: pic.twitter.com/S3XczudxEY

    9:07

    Эти графики не отображают мобилка \ десктоп. Но если это сделать, будет очень необычно.

    9:07

    Вот мобилки: pic.twitter.com/X5zLAW5rIE

    9:07
    @jsunderhood Померил посчитали, ок. Какие выводы это позволяет сделать?

    Чуть дальше я расскажу, что мы делали с графиками.
    А сейчас немного о том, зачем мы все затеяли.

    @jsunderhood Померил посчитали, ок. Какие выводы это позволяет сделать?

    10:29

    Почему это важно: перед задачей исследовательского характера, у тебя обычно есть гипотезы. Они могут быть подтвержд… twitter.com/i/web/status/1…

    10:29

    То есть, чтобы мы могли прийти к бизнесу и сказать: если мы потратим месяц разработки на улучшение загрузки вот это… twitter.com/i/web/status/1…

    10:29

    Это наша идеальная цель. Но на пути как обычно, появилась куча уточнений.

    10:29

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

    10:29

    Дальше TTI: TL;DR: gist.github.com/xnimorz/0b6080… Мы трекаем лонгтаски, ресурсы и не отправляем TTI, если пользователь ухо… twitter.com/i/web/status/1…

    11:06

    Изначально делали мы без visibility page API, но получили те же проблемы, что и с FMP. В коде нет raf, но есть setT… twitter.com/i/web/status/1…

    11:06

    Поэтому добавляем API и графики также стабилизируются: pic.twitter.com/c6kmRUGSS3

    11:06

    Чем крут этот график? у нас есть явный фаворит, оптимизацией которого нужно заниматься в первую очередь — страница вакансии.

    11:06

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

    11:06

    Чтобы не писать свой код для TTI, можно использовать готовое решение от google: github.com/GoogleChromeLa…

    11:07

    Для FID мы используем также готовое решение: github.com/GoogleChromeLa…

    11:08

    Для framework render \ init \ hydrate time делаем просто:
    ReactDOM.hydrate(root, reactRootNode, () => performance.… twitter.com/i/web/status/1…

    11:20

    Важное уточнение, мы считаем разницу, между началом рендера и этим колбеком.
    Это нужно, чтобы каждый этап был отдел… twitter.com/i/web/status/1…

    11:20

    Мы используем SSR, поэтому пользователь видит страницу еще до того, как пройдет гидрейт.

    11:20

    Как мы собираем метрики? Для сохранения данных мы делаем запрос на наш служебный урл `/stat`, в котором описываем наши метрики.

    11:25

    Затем эти данные парсятся и отправляются в хадуп. Кроме хадупа отображаем данные в okmeter.io. Собственно, все графики оттуда.

    11:25

    Пример такого запроса: pic.twitter.com/KbDoKfs5jx

    11:25

    okmeter платный, но всегда можно поднять Prometheus с grafana: prometheus.io grafana.com

    11:25

    Зачем вообще метрики на клиенте? Зачем так заморачиваться, если есть lighthouse? web page test?

    11:29

    1) Страницы динамические, на них меняется контент, есть код подрядчиков

    11:29

    2) У клиентов разные устройства. Мы получаем не репорт в вакууме, а реальные данные

    11:29

    3) Данные собираются постоянно (все обезличено), это открывает много возможностей для аналитики

    11:29

    4) Мы можем реагировать максимально быстро на деградации, как во время релиза, так и после

    11:29
    @jsunderhood Одно не могу понят, почему при проверке сайта, всегда разные показатели получаются. По паджу все ок а… twitter.com/i/web/status/1…

    Много процессов еще в системе запущено? Возможно, кто-то тянет одело процессорного времени на себя.
    И опять же: у с… twitter.com/i/web/status/1…

    @jsunderhood Одно не могу понят, почему при проверке сайта, всегда разные показатели получаются. По паджу все ок а… twitter.com/i/web/status/1…

    12:15

    Эксперименты с производительностью. В начале года мы запустили 4 эксперимента.
    два на улучшение производительности… twitter.com/i/web/status/1…

    12:40

    Эксперименты на улучшение производительности

    12:40

    1) Используем brotli вместо gzip. Это влияет на всю статику. Точные цифры экономии в Kб не вспомню, но это >100 Кб.

    12:40

    2) Используем кеширование через Service worker

    12:40

    На технических измерениях во время разработки, профит был заметен. Когда раскатили на клиенты большой производитель… twitter.com/i/web/status/1…

    12:40

    Мы сделали два вывода:
    1) Нужно будет повторить эксперименты с более сильной оптимизацией
    2) На небольшие оптимизац… twitter.com/i/web/status/1…

    12:40

    Затем мы запустили 2 эксперимента на деградацию. Эксперименты на деградацию нужно запускать очень осторожно, потому… twitter.com/i/web/status/1…

    12:40

    1) Мы замедляли инициализацию наших компонентов (TTI)
    2) Увеличили размер загружаемого css (FMP)

    12:40

    Про инициализацию компонентов. Мы сделали небесконечный цикл, который тормозил инит каждого компонента на небольшое… twitter.com/i/web/status/1…

    12:40

    Какое же было удивление, что бизнес-метрики ничего не почувствовали. Мы запускали эксперимент несколько раз (на раз… twitter.com/i/web/status/1…

    12:40

    Этот эксперимент позволил нам сделать вывод: пользователям главная ценность _нашего_ сайта — это возможность читать… twitter.com/i/web/status/1…

    12:40

    Так как текстового контента много, они не замечают, что сами компоненты становятся интерактивными через некоторое время.

    12:40

    Подтвердил нашу гипотезу эксперимент с увеличением загружаемого css. Это напрямую влияло на FMP. В бизнес-метриках… twitter.com/i/web/status/1…

    12:40

    Результаты экспериментов получились такие:
    1) Наиболее важный параметр, на котором нам нужно сосредотачиваться FMP.… twitter.com/i/web/status/1…

    12:40

    К прямой зависимости (некоторой формуле) денег от производительности мы, к сожалению, не пришли. Нашли только харак… twitter.com/i/web/status/1…

    12:40

    Что дают нам графики и подсчет метрик

    13:21

    1) Триггеры: если мы достигаем пика в 5/10 секунд (в зависимости от метрики), то к нам в чат прилетает сообщение о… twitter.com/i/web/status/1…

    13:21

    2) Динамика релиза: Как только выходит релиз мы видим на графике все деградации и оптимизации. Если деградация боль… twitter.com/i/web/status/1…

    13:21

    3) Также мы трекаем данные с клиента для аналитики: мы можем посчитать и сравнить метрики для части пользователей (… twitter.com/i/web/status/1…

    13:21

    Может появиться вопрос, а почему SSR за оптимизацию производительности не считаете?
    Почему с ним не проводили экспериментов?
    >>>

    13:25

    Я склоняюсь к тому, что SSR крайне важен, чтобы на сайте, который доступен неавторизованному пользователю его отклю… twitter.com/i/web/status/1…

    13:25

    Я писал, что можно не получить профитов от кеширования:
    Вот статья первая статья, для меня оказалась крайне полезн… twitter.com/i/web/status/1…

    14:05

    TL;DR: Используйте Cache API для статики в Service Worker. Этим вы экономите время исполнения кода, улучшаете TTI.

    14:06

    Дело в том, что не все браузеры кешируют файлы меньше 1Кб. За счет этого мы можем не получить профита от того, что… twitter.com/i/web/status/1…

    14:06

    Как устроено кеширование в хроме? Здесь на эту тему хорошо написано: v8.dev/blog/code-cach…

    14:06

    Вся информация дальше — это компиляция из этих статей. Эдакий TL;DR. Справедливо для chromium браузеров

    14:06

    У нас есть 3 способа "запуска" кода. Cold run, warm run и hot run: pic.twitter.com/0ihk6hR6Af

    14:06

    Cold run — пользователь пришел впервые. Браузер скачал файл, скормил его компилятору (транспилятору)

    14:06

    Warm run — пользователь пришел повторно. Браузер взял код из кеша, скормил его компилятору.

    14:06

    Hot run — пользователь пришел в 3-й раз за последние 72 часа.
    Браузер взял код и метаданные из кеша. Метаданные де… twitter.com/i/web/status/1…

    14:06

    Всем хочется исполняться на в hot run версии. Очевидно, что она экономит время.

    14:06

    Первый способ экономить время — не пишите код ¯\_(ツ)_/¯
    Кроме того, не забывайте про etag и заголовки для кеширования кода.

    14:06

    Есть интересный хак, чтобы забустить hot run. Используйте Cache API от Service worker

    14:06

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

    14:06

    Вот так сейчас выглядит загрузка hh.ru: pic.twitter.com/tbwFYUqV8U

    14:06

    Еще одна ссылка: youtube.com/watch?v=bZfULA…
    Здесь рассказываю о способах увеличения производительности и затрагиваю тему кеширования.

    14:19

    Еще приведу доклад @iamakulov о performance: youtube.com/watch?v=iEv1rF…

    14:19
    FMP — от него хотим следующего: понимание нашего critical path, количества времени которое уходит на него. Дальше… twitter.com/i/web/status/1…

    (1/2) Ссылки на темы за сегодня:
    Кеширование в chrome: twitter.com/jsunderhood/st…
    Профит от графиков:… twitter.com/i/web/status/1…

    FMP — от него хотим следующего: понимание нашего critical path, количества времени которое уходит на него. Дальше… twitter.com/i/web/status/1…

    15:07
    Я выступал на РИТ++ youtube.com/watch?v=4joeMk…, рассказывал о сборе метрик и частично затрагивал эксперименты с производительностью.

    (2/2) Зачем собирать метрики: twitter.com/jsunderhood/st…
    Зачем мы все затеяли: twitter.com/jsunderhood/st…
    TTI… twitter.com/i/web/status/1…

    Я выступал на РИТ++ youtube.com/watch?v=4joeMk…, рассказывал о сборе метрик и частично затрагивал эксперименты с производительностью.

    15:07

    Пара причин для этого:
    1) SEO — поисковым ботам нужно что-то индексировать
    2) отсутствие SSR заметно оттягивает вре… twitter.com/i/web/status/1…

    16:42
    @jsunderhood какой есть хороший ssr для реакта кроме некста?

    Я не могу взять и сказать: используйте next.js, gatsby или react-static. Зависит от решаемой задачи.

    @jsunderhood какой есть хороший ssr для реакта кроме некста?

    17:03

    Готовые решения имеют свои ограничения. Мы сделали свое простое решение без излишеств twitter.com/i/web/status/1…

    gats… twitter.com/i/web/status/1…

    17:03

    react-static никогда не пробовал, говорят удобен для статических сайтов. Но
    1) Статический сайт можно сделать на то… twitter.com/i/web/status/1…

    17:03
    @jsunderhood Ну Некст используется на проекте главным образом для seo оптимизации реакт приложения

    А вот csr сдел… twitter.com/i/web/status/1…

    Классный вопрос. На самом деле "все очень плохо".
    Мои коллеги смотрели, какие деградации для SEO будут, если исполь… twitter.com/i/web/status/1…

    @jsunderhood Ну Некст используется на проекте главным образом для seo оптимизации реакт приложения

    А вот csr сдел… twitter.com/i/web/status/1…

    18:25

    И пара статей:
    Для гугла: developers.google.com/search/docs/gu…

    Для яндекса: yandex.ru/support/webmas…

    18:25

    Коротко: что-то работает, но что получится — на ваш страх и риск.

    18:25

    # Воскресенье 60 твитов

    @jsunderhood @andrey_sitnik Для статического сайта, если не реакт, то другой шаблонизатор. Соль в том что (п)реакт… twitter.com/i/web/status/1…

    Здесь есть несколько особенностей:
    1) Полностью статический сайт всегда можно прекомпилировать и получить на выход… twitter.com/i/web/status/1…

    @jsunderhood @andrey_sitnik Для статического сайта, если не реакт, то другой шаблонизатор. Соль в том что (п)реакт… twitter.com/i/web/status/1…

    7:40

    2) Иногда сайт нельзя полностью прекомпилировать. Например, будут небольшие кусочки типа "комментарий пользователя"… twitter.com/i/web/status/1…

    7:40

    3) Главная же проблема в реакте для такой задачи — что на клиент обычно поставляют весь бандл кода, который большую… twitter.com/i/web/status/1…

    7:40

    А полезного кода, который отправит и красиво добавит комментарий без перезагрузки страницы — это от силы останется… twitter.com/i/web/status/1…

    7:40

    Если делается такой сайт, а условный (п)реакт, вью хочется, я бы рассматривал такой вариант:
    Сделайте 2 точки вход… twitter.com/i/web/status/1…

    7:40

    Это позволяет вам не делать лишние телодвижения на клиенте. Код, который ничего не делает, на клиент не попадет.
    К… twitter.com/i/web/status/1…

    7:40

    Единственное, еще и сама библиотека имеет свой размер. Например, вот реакт-дом: bundlephobia.com/result?p=react…

    7:40
    @jsunderhood В скраме дедлайн раз в две недели, а при канбане в умелых руках аврал и дедлайн каждый день, какое уж… twitter.com/i/web/status/1…

    Любой инструмент можно превратить в кошмар исполнителей. При удобном инструменте, который понимают, принимают и не… twitter.com/i/web/status/1…

    @jsunderhood В скраме дедлайн раз в две недели, а при канбане в умелых руках аврал и дедлайн каждый день, какое уж… twitter.com/i/web/status/1…

    7:56

    Поэтому Я бы сказал, что это другая проблема. Проблема "эффективных" менеджеров. Такие "друзья" могут встречаться ч… twitter.com/i/web/status/1…

    7:56

    Если у вас скрам, то не будем закладывать баги и мелкие задачи, вместо мелкой задачи возьмите пару фич. А потом на… twitter.com/i/web/status/1…

    7:56

    Если у вас waterflow, то дедлайн будет идти только от такого менеджера.

    7:56

    Если канбан, то менеджер не будет делить задачи по классам поставки — "ха, зачем? вы вот эту задачку закончили за 3… twitter.com/i/web/status/1…

    7:56

    В канбане такой "эффективный" менеджер не хочет разбираться, что у команды есть, например 3 класса поставки (сроки… twitter.com/i/web/status/1…

    7:56

    Если вы хотите попробовать канбан, но боитесь такого подхода со стороны менеджеров: оставьте оценку задач и прогова… twitter.com/i/web/status/1…

    7:56

    Мы успели обсудить много тем за неделю.
    Браузерные плагины, процессы, kanban, визуализация, иконки, миграция стеко… twitter.com/i/web/status/1…

    7:56

    Сегодня не будет много твитов. Предлагаю поговорить на ваши темы. Если вам интересно какое-то направление, какая-то… twitter.com/i/web/status/1…

    7:57
    @jsunderhood Берём приложения на React, и делаем что хотим, а всякие там комментарии и другие отчуждаемые элементы… twitter.com/i/web/status/1…

    Еще один вариант через server side includes :)

    @jsunderhood Берём приложения на React, и делаем что хотим, а всякие там комментарии и другие отчуждаемые элементы… twitter.com/i/web/status/1…

    8:29
    @jsunderhood Если доступа до ngnix нет или не надо - React-prerendered-component делает ровно тоже самое через Stre… twitter.com/i/web/status/1…
    8:29
    @jsunderhood Спасибо за продуктивную неделю! Вопрос: какой подход на собеседовании для кандидатов вы считаете наибо… twitter.com/i/web/status/1…

    Я занимаюсь собеседованиями в HH уже 3 года без одного месяца :) Сейчас наше техническое интервью — это часть вопро… twitter.com/i/web/status/1…

    @jsunderhood Спасибо за продуктивную неделю! Вопрос: какой подход на собеседовании для кандидатов вы считаете наибо… twitter.com/i/web/status/1…

    8:43

    За это время мы несколько раз переделывали наш подход к собеседованиям, потому что всегда "что-то не то". Был этап,… twitter.com/i/web/status/1…

    8:43

    Каждый раз, когда меняли собеседование мы в том числе пытались оценить: насколько подход удобный? Насколько собесед… twitter.com/i/web/status/1…

    8:43

    Сейчас наше собеседование состоит из 3 частей. Разговор о прошлом опыте и об удобных процессах в компании для канди… twitter.com/i/web/status/1…

    8:43

    В техническом интервью мы всегда хотели понять: умеет ли рассуждать и решать проблемы кандидат?

    8:43

    Нас очень вдохновила вот эта статья от @vas3k: vas3k.ru/inside/46/

    8:43

    В последней итерации мы сделали переходы между разговором о прошлом опыте и техническом интервью в виде небольшого… twitter.com/i/web/status/1…

    8:43

    Но не все так хорошо как на бумаге. Например, мы периодически скатываемся только в технические вопросы. Есть немало… twitter.com/i/web/status/1…

    8:43

    Есть кейсы успешных собеседований. И я прям рад во время таких интервью: мы разговариваем с кандидатом о его опыте.… twitter.com/i/web/status/1…

    8:43

    Например, кандидат делал обработку табличных данных, как в гугл доках.
    Мы разговариваем об этой специфики. Затраги… twitter.com/i/web/status/1…

    8:43

    Когда наступает в нашем воркфлоу этап технического интервью мы просто говорим о паре вещей важных для нас (например… twitter.com/i/web/status/1…

    8:43

    Мне кажется, у большинства нас есть примеры задач, который нас драйвили. Рассказывайте об этом на собеседованиях. И… twitter.com/i/web/status/1…

    8:43

    Также у меня есть пара провальных опытов, но уже в качестве собеседуемого. Самая главная боль — когда собеседующему… twitter.com/i/web/status/1…

    8:43

    И второй: когда собеседующий считает, что ответ должен быть не просто однозначным, но еще и слова должны быть точь-… twitter.com/i/web/status/1…

    8:43
    @jsunderhood Полностью согласен. Я проходил такое собеседование: двое интервьюеров и ноутбук с заданиями. Было не п… twitter.com/i/web/status/1…
    9:37
    @jsunderhood Самым интересным и эффективным до сих пор считаю способ с пробным днём в компании (это не так легко ор… twitter.com/i/web/status/1…
    9:42
    @maRx_flowers @jsunderhood Ещё веселее когда:

    Я с таким, благо, не сталкивался 🙂

    @maRx_flowers @jsunderhood Ещё веселее когда:

    9:46
    @maRx_flowers @jsunderhood Тестовый день — супер. Можно понять не только круг задач, но и присмотреться к обстановк… twitter.com/i/web/status/1…
    11:56
    @sexymuhamedik @jsunderhood В реакт бандл SSR встроен из коробки, хоть экспрессом раздавай, ещё и производительней next будет.
    12:07
    @almost_bergman @jsunderhood У меня была два таких дня и оба были успешные(получал оффер). В одной из компаний этот… twitter.com/i/web/status/1…
    12:07
    @maRx_flowers @jsunderhood а в чём поинт пробного дня? ты вряд ли сможешь сделать какую-то задачу (в сам проект ещё… twitter.com/i/web/status/1…

    Тут должен процесс у работодателя быть настроенным. Чтобы человек познакомился с командой и поковырялся в небольшой… twitter.com/i/web/status/1…

    @maRx_flowers @jsunderhood а в чём поинт пробного дня? ты вряд ли сможешь сделать какую-то задачу (в сам проект ещё… twitter.com/i/web/status/1…

    12:09
    @YouSysAdmin @maRx_flowers @jsunderhood Основной гайдлайн в Майкрософте нынче - задачи на интервью должны быть напр… twitter.com/i/web/status/1…
    12:54
    @7rulnik @jsunderhood @YouSysAdmin @maRx_flowers Как и везде, кандидат мучается - а мы издеваемся ;)

    Не могу не ретвитнуть 😀

    @7rulnik @jsunderhood @YouSysAdmin @maRx_flowers Как и везде, кандидат мучается - а мы издеваемся ;)

    13:25
    @7rulnik @jsunderhood @YouSysAdmin @maRx_flowers А если на серьезных щах, то кандидат драйвит, а интервьюер помогае… twitter.com/i/web/status/1…

    Хороший тред о собеседовании-задаче 🙂

    @7rulnik @jsunderhood @YouSysAdmin @maRx_flowers А если на серьезных щах, то кандидат драйвит, а интервьюер помогае… twitter.com/i/web/status/1…

    13:35
    @jsunderhood 1. Зачем разработчику математика? (Ответ «не нужна» не принимается)
    Какие софт-скиллы она тренирует?… twitter.com/i/web/status/1…

  • Зачем разработчику математика? (Ответ «не нужна» не принимается)
    Какие софт-скиллы она тренирует?
  • 14:22

    Расскажу одну историю: когда я учился в 11 классе, я брал уроки репетиторства у вузовского преподавателя высшей мат… twitter.com/i/web/status/1…

    14:22

    В самой олимпиаде занял первое место, но как подойти к задаче не осознал.
    На уроке разговорились с преподавателем… twitter.com/i/web/status/1…

    14:22

    К концу занятия (1.5) человек, у которого не было бекраунда в разработке дал четкий алгоритм, который решал задачу оптимальным способом.

    14:22

    Математика — это не только про найти интеграл.
    Это навык решать задачи, оценивать их и оптимизировать. А иксы ли у… twitter.com/i/web/status/1…

    14:22

    В той же высшей математике исходя из входных данных можно не знать \ забыть алгоритм нахождения интеграла — но его можно вывести.

    14:22

    Аналогично и в разработке.
    И да — это нормально считать иначе :)

    14:22
    @jsunderhood 1. Зачем разработчику математика? (Ответ «не нужна» не принимается)
    Какие софт-скиллы она тренирует?… twitter.com/i/web/status/1…

  • Адаптивность это софт-скилл? Как ее тренировать?
  • Влияют ли софт скиллы на тех скиллы?
  • 14:30

    Пересечение и взаимное влияние я наблюдал во время своей работы.
    Категоризовать: "ты однозначно софт скилл, ты — хард скилл" — мне сложно.

    14:30

    Например: обучаемость? она тоже бывает очень разная. Это может быть идеальная память на механические вещи. А может… twitter.com/i/web/status/1…

    14:30

    Но сказать — первый плохой, второй хороший — нельзя. У этих людей обучаемость прокачена по разным "веткам развития"… twitter.com/i/web/status/1…

    14:30
    @jsunderhood 1. Зачем разработчику математика? (Ответ «не нужна» не принимается)
    Какие софт-скиллы она тренирует?… twitter.com/i/web/status/1…

  • Роль HR отдела в тренинге софт скиллов
  • 14:35

    Мне удалось поработать с разными HR менеджерами. Некоторым было "глубоко все равно", что происходит в процессах ком… twitter.com/i/web/status/1…

    14:35

    Такие _хорошие_ hr менеджеры, могут выступать не просто консультантом \ источником бюджета, но и драйвером в прокач… twitter.com/i/web/status/1…

    14:35

    Затем выработать рекомендации, помочь с поиском подходящих курсов.

    В общем, да, роль HR отдела может сильно варьироваться в компании.

    14:35
    Мое выступление на тему "Есть ли жизнь после Senior?" в Харькове подъехало:
    youtu.be/CiSLUYwdyac?li…

    Смотрите, кри… twitter.com/i/web/status/1…

    15:46

    Спасибо, что были со мной эту неделю 🙂
    С вами был @xnimorz . В своем твиттере я пишу редко и обычно связанное с раз… twitter.com/i/web/status/1…

    15:48

    И большое спасибо @DmitryMakhnev и @rage_monk вы очень прокачали мой доклад и сделали его круче :)

    15:48

    github.com

    www.youtube.com

    gist.github.com

    other