melikhov.dev – Telegram
melikhov.dev
4.63K subscribers
110 photos
2 videos
2 files
203 links
Фронтенд, фронт-бек и около. Всё, что в голову пришло. Иногда котики.
Download Telegram
А я напомню, что таких долгоживущих веток делать конечно же не надо. Хорошая ветка живёт день-два и уезжает в main (ну или в версию, если у вас одновременно несколько веток живёт).

И не забываем ребейзить и сквошить.

https://news.1rj.ru/str/mefody_dev/119
💯28👎3🤔2🤝2😁1
Хорошее замечание, что при таком подходе можно перегрузить QA. Ответ тут в том, что QA не должны быть узким местом. Разбираем монолиты на библиотеки и микросервисы, покрываем всё автотестами, подключаем ручное QA только в критичных местах, либо на релизную ветку.

Цель CI в том, чтобы код постоянно вливался и шарился между всеми. Чем раньше мы упрёмся в проблему, тем менее она болезненна. К сожалению, это не особо совместимо с ручным QA, либо придётся приставить по одному QA к каждому разработчику. И что должен этот QA делать с неготовой задачей, закрытой флагом от прода? Только проводить регрессы и смоуки. А с этим автоматика отлично справляется.
👍27
Прохладная история про LCP и SPA

Есть такая метрика в Core Web Vitals — Largest Contentful Paint (LCP). Устроена она достаточно банально — просто показывает время от старта запроса до рендера самого большого элемента на странице. В Яндексе измерение метрик скорости построено так, что мы не просто смотрим на каждую метрику в отдельности, у нас есть специальный индекс скорости, который высчитывается из совокупности Web Vitals.

И вот, на новогодних праздниках мы наблюдаем неплохой такой прирост этого индекса. А после праздников — падение назад. Казалось бы, логично, упала нагрузка, всё побежало быстрее. Но нет, рост рейтинга скорости начинается за неделю до нового года и падает он назад ровно через неделю после окончания праздников.

Начинаем вспоминать и понимаем, что включали на праздники новогоднюю анимацию в меню. Тааак. Вот оно! Наши страницы в сервисе — это чистые SPA, серверный рендер приносит только менюшку. Дальше включается лоадер, который тянет конфиги с бэка и рисует контент. И в нормальных условиях LCP возникает после ответа бэка. А когда мы добавили картинку в меню, то получили новый Большой Элемент, который начал рисоваться значительно раньше. LCP подросло и подтянуло за собой общую метрику.

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

А мы будем думать, как добавить немного хорошего быстрого SSR.
😁42👍26🏆64🎄3🔥2🎉1🐳1
Случайно наткнулся на относительно живой форк request в котором хотя бы латают уязвимости — @cypress/request

Хотя, конечно, пожелал бы команде сайпреса слазить уже с request и, тем более, request-promise, который вообще на bluebird.

Но если вам временно нужна затычка вместо оригинального request, то, наверное, сойдёт.
👍103🤔3
Как-то совсем без большого хайпа ребята запустились. Не то, что Bun, где из каждого утюга кричали.
Костылик для GitHub Action

Вот читаете вы про Statoscope, например, и видите в статье готовое решение, как прикрутить его в GitHub Actions. Чтобы полный отчёт грузился на S3, а краткий — прямо в комментарии к пулл-реквесту.

Вот, такой вот yml для воркфлоу https://github.com/statoscope/statoscope.tech/blob/main/.github/workflows/ci.yml . И вот есть в нём большой подвох, если вы прикрутите это к публичному репозиторию — в случае PR из форков GitHub не даст вам доступа к секретам. И пермишенов на публикацию комментариев не даст. Связано это с тем, что в GitHub actions в триггере


on:
pull_request:


весь код для воркфлоу берётся из текущей ветки, а, следовательно, он может быть изменён и креды утекут. Я не нашёл способа изменить поведение и заставить GitHub Actions всегда брать воркфлоу-файл из main-ветки. Получается, нужен костылик.

Костылик получается такой:

1 На пулл-реквест мы делаем нужные дела в ветке (например, собираем отчёт статоскопа)
2 Паблишим отчёт и информацию о пул-реквесте в артефакты гитхаба
3 Создаём ещё один воркфлоу. Триггером будет


on:
workflow_run:
workflows: [Наш первый воркфлоу]
types:
- completed


4 Выкачиваем наш артефакт


- name: Download Artifacts
uses: dawidd6/action-download-artifact@v3
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
run_id: ${{ github.event.workflow_run.id }}

5 Этот воркфлоу запущен из main и у него есть доступ к секретам. Паблишим в S3 и пишем ссылку в комменты PR.


Дополнительно — в исходном решении избыточным выглядит mustache, достаточно взять обычный советский темплейт литерал. А для публикации отчёта в комменты PR удобно использовать https://github.com/marocchino/sticky-pull-request-comment

Ещё раз:

На пул-реквесте собираем артефакт и сохраняем его
https://github.com/datalens-tech/datalens-ui/blob/main/.github/workflows/statoscope_tests.yml#L38

На main ветке распаковываем артефакт и паблишим в S3 и комменты PR
https://github.com/datalens-tech/datalens-ui/blob/main/.github/workflows/statoscope_tests_report.yml#L19
👍36🔥6🤯32❤‍🔥1💋1
Forwarded from mefody.dev
«Я💛Ф» CTF 2024

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

Если считаете, что разбираетесь во фронтенд-технологиях, заходите сегодня после 20:07 по минскому времени, чтобы поучаствовать в гонке за призами.

https://ctf-2024.ilovefrontend.ru/
29💩5
Ещё раз — старт в 20:07 по GMT+3.

Пока можете вспомнить прошлые

https://ctf.ilovefrontend.ru/
https://ctf-2023.ilovefrontend.ru/
https://ctf-2024.ilovefrontend.ru/
👍18🔥5💩2
Сейчас, когда А* уже официально банкрот и прошла через делистинг на Nasdaq, хочется немного порефлексировать про свой опыт в этом интересной компании. Я же туда заходил, когда она была ого-го, единорог, гремела на рынке! Но через 4 месяца ушёл, не выдержал, возненавидел.

Первое и самое главное, испытательный срок — это двусторонний процесс. Не только компания смотрит на тебя, но и ты смотришь на компанию. И компания может его не пройти. Это нормально.

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

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

Левая рука выбрала Пайтон, а правая решила на Скале. Левая нога деплоится через Тимсити в Кубер, а правая предпочитает Дженкинс и EC2. Везде одни синьоры, но критерий синьорства определяется тимлидом. В это время обе руки крутят один и тот же вентиль, разными способами и в разные стороны. Потому что не договорились.

Всё это очень весело, пока инвестиции не проели.

* все совпадения с реальными компаниями случайны.
👍47🤣15🔥8😢43🤔3🤡3🤝2
Техника тысячи маленьких пиаров — это когда ты параллельно с большими рабочими задачами постоянно находишь какие-то мелкие штуки и улучшаешь, улучшаешь, улучшаешь и свой проект и остальной опенсорс каждый день.
🔥56👍11🤔65👎2👏2🤡2🤓1
Блуждающий ECONNRESET

Достаточно частый кейс в node.js-разработке, когда мы видим в логах блуждающую ошибку ECONNRESET при запросах в другой бэкенд. Начинаем искать, идём на вторую машинку, а там тишина, ошибок в логах нет. Как обычно отвечают — у нас всё хорошо, проблемы на вашей стороне.

Одна из причин это включенный keepalive. Идея keepalive в том, что мы можем переиспользовать коннекшены, не создавать новый коннекшн на каждый запрос. Клиент стучится на сервер, открывает коннекшн, удерживает его и при следующем заходе обращается к уже созданному коннекшену. А что произойдёт, если клиент удерживает коннекшн дольше, чем сервер? Т.е. сервер имеет например keepalive_timeout 4, а клиент создал http.Agent с timeout: 5? Мы и получим тот самый ECONNRESET.

И даже при равных значениях можно достаточно легко войти в состояние гонки:


import http from 'node:http';

const server = http.createServer((req, res) => { res.end('some stuff') });

server.keepAliveTimeout = 5000; //default

server.listen(1337, '127.0.0.1', startSendingRequests);

function startSendingRequests() {
const keepAliveAgent = new http.Agent({keepAlive: true, timeout: 5000});

setInterval(() => {
http.get('http://127.0.0.1:1337', {agent: keepAliveAgent}, (res) => {
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
}).on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
}, 5000)
}


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

Во-вторых, документация node.js предлагает такой паттерн ретрая:


.on('error', (err) => {
// Check if retry is needed
if (req.reusedSocket && err.code === 'ECONNRESET') {
retriableRequest();
}
});


UPD

И конечно важно помнить, что причины, по которым коннекшен может быть закрыт со стороны сервера — разные. Таймаут keepalive лишь один из случаев.
🔥91👍3910
WASM и Докер

Есть одна штука в андроид смартфонах, которая мне бесспорно нравится — это бесконечная лента интересных ссылок по свайпу влево с главного экрана. Буквально вчера подкинули статейку. Оказывается, в оригинальном Docker Engine (который на containerd), можно красиво запускать упакованные в контейнер wasm-приложения. Из уже поддерживаемых рантаймов: WasmEdge, Spin, Slight и Wasmtime.
Штука эта есть в Docker Engine в бета-режиме достаточно давно. Но я-то на OrbStack ушёл. И там пока из поддержки только такой ишью https://github.com/orbstack/orbstack/issues/585

Так ли оно нужно, я пока честно говоря не понял. Но прикольно смотреть куда идёт WASM.
👍25🤔52👎1🔥1
Готовил на Субботник классный доклад про песочницы на Node.js (vm, vm2, v8 isolates, wasm QuickJS и т.д.) и их проблемы. Но, к сожалению, накладка, не попадаю физически. Зато будут другие классные доклады, а свой расскажу как-нибудь попозже.
🔥47😢25👍13
Скоро запускается открытый лекторий летних школ. Заглядывайте 10-го, кто хочет послушать как я буду 2 часа нудеть про Node.js. Другие лекции тоже интересные!
👍57🔥21😍114
Очередной забавный кейс с npm

Есть у нас приложение, которое поднимает стенды с приложеньками, «ферма» называется. Вот просто, качает нужную ветку из git, делает условно npm ci && npm run build && npm run start и поднимает инстанс, на который мы натравливаем E2E. Да-да, мы знаем про докер, но пока не успели.

И вот буквально позавчера ловим странный баг. В одной из веток не устанавливается несколько зависимостей. Просто нет их node_modules. Локально не повторяется. Захожу на ферму, дёргаю npm ci из консоли — всё ок. Зависимости не ставятся:

1) только когда npm ci вызывается из самой фермы через child_process.exec,
2) только на конкретной ветке.

Ооок. Я магию не люблю, потому сажусь разбираться. Посмотрим что там в env. Ого, а там npm_config_legacy_peer_deps: 'true' . П-нятненько почему зависимости не ставятся, они же peerDeps.

Две загадки:

1) Откуда legacy-peer-deps залетает в env,
2) Почему он влияет не всегда.

Что ж, ответ на первую. В папке самой фермы в .npmrc лежит legacy-peer-deps=true. Когда мы её запускаем через npm run start npm читает .npmrc и прокидывает в env всю свою лабуду в npm_config_*. А child_process.exec запускает дочерние процессы с process.env родителя.

Ответ на вторую загадку. npm ci --legacy-peer-deps не разрушал приложение, потому что ставил все зависимости как и было написано в package-lock.json. Но в конкретной ветке случилась коллизия, зависимость поставили и в devDependencies и в просто dependencies. Вот после этого npm ci перестал доверять package-lock.json и пересчитал всё дерево, уже тихо применяя к нему правило --legacy-peer-deps.

Люблю я эту работу.
🔥67💊25👍15🥴15🤓1
melikhov.dev
Скоро запускается открытый лекторий летних школ. Заглядывайте 10-го, кто хочет послушать как я буду 2 часа нудеть про Node.js. Другие лекции тоже интересные!
Бэкстейдж, кстати. В этот раз сильно меньше недоволен результатом, получилось упихнуть в полтора часа больше полезного и гораздо меньше воды. Уже не медь, но до золота ещё пара итераций нужна.
🔥103👍228🤮2👎1😁1😍1
Никита молодец, будь как Никита и его команда!
👏20
Forwarded from mefody.dev
CodeRun. Большой запуск

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

Сегодня мы выходим из беты! Случилось то, к чему я шёл несколько лет. Очень волнительно 🙂

Теперь у нас есть свой маскот Кодерун, новый брендинг, мультифайловые задачи, подборки, переработанная навигация, профиль участника. И будет ещё больше, бэклог ломится от интересных идей!

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

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

А всей большой команде CodeRun хочу выразить огромную благодарность за то, что помогли реализовать мою старую мечту — сделать классный тренажёр с интересными задачами для тех, кто хочет развиваться и прокачиваться. Люблю вас! 💛

https://coderun.yandex.ru/
53👍29🔥19👎2🥰2👏1
Николас Закас (автор ESlint) поделился своими размышлениями про безопасное использование Bun и Deno. Хорошие поинты:

1 Не используйте API, специфичные для Deno или Bun. Это затруднит смену рантайма если что-то пойдёт не так с этими двумя. Придерживайтесь Node.js API, которые уже поддерживаются в Deno и Bun.

2 Используйте префикс 'node:' для внутренних модулей Node.js. И Deno, и Bun поддерживают большую часть внутренних модулей Node.js, но они могут идентифицировать эти модули только при наличии префикса 'node:'. Node.js прекрасно работает при использовании префикса 'node:', поэтому вы можете обеспечить совместимость во всех трех средах выполнения.

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

4 Используйте package.json для указания зависимостей. Deno рекомендует вам использовать deno.json или jsr.json для указания ваших зависимостей, но он также может использовать package.json.

5 Также всегда запускайте на CI проверки совместимости с Node.js. Node.js это отличный запасной вариант, если вы используете Deno или Bun, поскольку не привязан к какой-либо одной компании. Чтобы оставить возможность быстрой смены рантаймов полезно всегда запускать тесты в CI в Node.js даже если вы переходите на Deno или Bun.

Благодаря отличной совместимости Deno и Bun с Node.js API, сейчас проще, чем когда-либо писать единый код для всех трёх сред выполнения. Трюк заключается в том, чтобы нацелиться на Node.js, а затем использовать функции совместимости Deno и Bun. Таким образом, если в любое время произойдет смена рантайма, ваше приложение сможет работать без особых проблем.
👍8510🔥2🥱2🫡1