Андруша пишет код – Telegram
Андруша пишет код
1.25K subscribers
137 photos
1 video
1 file
218 links
Download Telegram
Уродливое, но родное

В прошлой заметке я попытался показать почему редакс, по-моему мнению, плох. Существуют даже конкуренты. И их много. И они неплохи на фоне редакса.
Конкуренты:
- jotai
- zustand
- mobx
- effector
- reatom

Эти все инструменты как минимум не хуже чем редакс. Некоторые из них даже становятся популярными и растут как ни в себя по скачиваниям, но от редакса люди не отказываются. Почему?

Под предыдущим постом люди написали и про привычки, и про рекламу от Абрамова, и про "работает - не трож". Но основная проблема, как мне кажется, абсолютно в другом: Разрабы библиотек не умеют в маркетинг. Совсем не умеют. Каждый из разрабов думает "ой какой красивый, быстрый и лакончиный код позволяет писать моё решение". Но никто не думает "как интегрировать мою либу в текущие решения?". Ведь каждый из нас каждый день начинает новый проект, который будет отличаться предыдущих. Как по методологиям, так и по практикам. Верно же?

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

И это касается не только стейт менеджеров. Это касается всей индустрии. Никто не делает адаптеры со старых решений на новые. Возьмём, к примеру, библиотеки для запросов. axios и got - это сверхпопулярные библиотеки, чтобы сделать простую вещь - отправить запрос в сеть. С 18 версии в ноде появилась нативная поддержка fetch, которая позволяет сделать куда меньшие и более мощные библиотеки. Но что мы видим? Никто не делает какой-нибудь fetchios, который имеет тот же API, но fetch под капотом. Этим махом можно спокойно срезать половину размера. Но нафига козе баян? Мы лучше сделаем ky, который ни с кем выше не совместим.

Так и живём...
4👍3🤡3💩1
https://nodejs.org/api/esm.html#importmetadirname

Славься мир. Больше никаких

import { dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
👍16🤡3💩1
Ограничения - цэ добро

После https://news.1rj.ru/str/xavescor_code/77 я решил доказать это на практике, заменив xhr внутри axios на fetch. Это позволило бы и уменьшить размер аксиоса и позволить людям перейти на более простое, вебосовместимое решение.

Но я столкнулся с проблемами, о которых должен думать разраб библиотеки, но о которых не подумали разработчики аксиоса:
Целковый. Каждая новая перегрузка апи должна решать новый спектр задач. К примеру, у реатома хук useAtom может принимать как атом, так и функцию, которая возвращает значение. Эти перегрузки не взаимозаменяемы. AxiosHeaders же может принимать в себя кучу разных типов, которые потом очень хитро превращаются в строку при превращении в хедеры. И эта хитрость очень сильно мешает как во внутренней реализации, так и при написании адаптеров. Но если бы AxiosHeaders принимал только строки, то и реализация была бы проще, и клиентам было бы не особо сложнее.
Приведу другой пример: Куча либ позволяет принимать в себя как тип T, так и Array<T>, а внутри уже T приводится к [T]. Даже если специальная функция в npm: arraify. Но, заставив пользователя писать не foo(x), а foo([x]) мы бы сэкономили и на размере либы, и на упрощении контракта.
Вывод: все приведения типов должны быть снаружи библиотеки, а не внутри. Делайте апи максимально скудным. Это очень упрощает жизнь и в тестах, и в реальной жизни

Полушка. Обновляйте библиотеки и меняйте устаревшие решения на современные. Аксиос для тестирования в браузере использует karma + jasmine. А для того чтобы отслеживать запросы, они мокают xmr. Ну, это хорошее решение, пока у нас не появился второй примитив для отправки запросов. А сейчас нормальным решением является какой-нибудь playwright, который через вебдрайвер уже получает информацию о запросах от браузера, а не с помощью моков конкретной стуруктуры. В итоге из-за кривых тестов мне для проверки своей реализации нужно ещё переписать тесты

Четвертушка. РАЗНЫЕ ТЕСТЫ НА РАЗНЫЕ ОКРУЖЕНИЯ. axios - делаем запросы по-разному. Я не знаю что в голове у людей, которые пилят аксиос, но у них 2 набора тестов: для ноды и не для ноды. Причём это РАЗНЫЕ ТЕСТЫ. Они не пересекаются. И дело не в моках. Я проверял. Тесты реально разные и проверяют разную логику. Axios - библиотека, которая работает по-разному в разных окружениях. Велкоме.

Так и живём...
👍7🤡4💩1
Ожидания == реальность

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

Так вот. FF мёртв, как минимум по ожиданиям разрабов. Потому что у меня нет обоснования как можно было допустить багу в такой базовой вещи как AbortController.
https://github.com/microsoft/playwright/issues/29101

Буду благодарен, если вы тоже проверите у себя эту багу, так как у меня сейчас только 1 ноут под рукой. Проверка отнимет от силы 2-3 минуты вашего времени.
🤡3👍2💩1
https://9to5mac.com/2024/01/25/third-party-default-browsers-engines/

Раз в 10 лет ЕС кардинально меняет рынок браузеров. В 2012 ЕС убил десктопный IE, а в 2024 походу он пришёл за мобильным сафари. Тестеры поздравляю, вам чуток работы подъехало.
4🤯2💩1
Недавно эпол частично прогнулась под ЕС в рамках сайдлоадинга https://www.macrumors.com/2024/01/25/ios-17-4-alternative-app-marketplaces-eu/ и люди опять оказались людьми:
"Почему государство указывает компаниям как вести свой бизнес? Если я захочу устанавливать приложения откуда-то снаружи, то я могу пойти на Android".
Это забавно, так как почему-то люди думают, что мир крутится вокруг них. Хотя это не так. В данном случае, почему-то никто не думает о разработчиках сервисов, которые для успеха должны иметь приложение и там, и сям. Без исключений. Но нет, второй стороны не существует, а мир крутится вокруг меня.

Эта же история напомнило мне что компании перестают быть плохими, когда достигают целей(Так как можно просто не видеть неудобную информацию). Пример прост: Амиго, Яндекс.Браузер и прочие. Де кась "эти продукты плохие, так как распространяюлись предустановками или же параллельными установками вместе с другим софтом". Возможно, открою Америку части людей: Google Chrome распространялся точно такими же методами. В 2012 году существовал сверхпопулярный продукт, которым пользовался практически каждый пользователь интернета - Abode Flash. И, не поверите, флеш устанавливал хром, если ты забывал снять галочку. Огромное количество миллионов инсталяций принесла эта "плохая" практика. И я даже не вспоминаю истории про гугл.тулбар, который устанавливался в IE вообще при любом чихе.

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

А так же всем людям советую искать в первую очередь факты, которые не подтверждают вашу точку зрения, а опровергают. Так куда проще добраться до истины.
👍8🤡6💩1
🤡6😭5👍1💩1
Forwarded from UX Live 🔥
😲🤯😮
Это просто ОХУЕННО!
Жаль не знаю даже имени этого героя из комментариев который придумал этот метод, но это фантастически быстро и удобно!

Создал пустую группу сейчас
Запустил стрим внутри неё
Включил запись экрана и выбрал окно
Файлик с видео просто упал в сохраненки 🤯🤯🤯
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡7💩1
Interop 2024

В девяностые и нулевые были войны браузеров, когда каждый придумывал свои стандарты, который позволяли делать веб лучше, функциональнее, удобнее. Но это привело к огромной проблеме: такое понятие как кроссбраузерность было редкостью. В десятые ситуация стала куда лучше, так как разработчики браузеров стали общаться и несовместимости почти пропали. Но почти - это не полностью.
Веб стал настолько огромным, что невозможно уследить за всем, чтобы всё было одинаково. Но мы живём уже в двадцатых. И появился новый проект: Interop xxxx. И уже было 3 итерации 2021, 2022, 2023. И каждый год браузеры выбирают сферу, в которой они унифицируют своё поведение. И самое клёвое в этом проекте, что это не какой-то caniuse с просто написанной статистикой. Это набор тестов, которые непредвзяты и каждый может проверить работает ли та или иная штука в браузере и появилась ли деградация.

И вот настал 2024, а значит пора ставить новые цели. И цели были поставлены: https://hacks.mozilla.org/2024/02/announcing-interop-2024/. Так же в конце статьи вы можете увидеть ссылки на других вендоров, которые описали собственный взгляд на этот проект.

Самое удивительное для меня в Interop XXXX то, что в него вписалась Apple. А значит жить нам будет куда проще.

Текущую статистику вы можете увидеть тут: https://wpt.fyi/interop-2024?stable
👍41💩1
https://twitter.com/Hinkali4/status/1753172405260812770

Почему-то в 2024 году люди всё ещё не научились в цифровую гигиену.
Делюсь великим секретом: не смешивайте работу и личную жизнь. Максимально разграничивайте их. На работе старайтесь пользоваться исключительно рабочими мессенджерами(Slack, MS Teams, etc.). Если работа лезет в телегу(привет, Яндекс!), то не поленитесь и заведите отдельный рабочий аккаунт. К примеру, у меня это @XaveScorWork.

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

Если опустить вопрос коммуникации, то я так же советую вам обзавестись отдельным рабочим оборудованием, отдельным календарём, отдельной почтой и отдельным всем-всем-всем. Не надо работать с устройств и аккаунтов, где вы держите личные данные. Смешивание работы и личной жизни - цэ мэрзость. Цэ рэально мэрзость. Чем дальше будет ваша работа от вашей личной жизни, тем лучше вы будете себя чувствовать.
👍4💩2
Ну, время написать что-нибудь и о программировании. Сейчас я занимаюсь рефакторингом одной нашей внутренней библиотеки, вторая версия которой будет иметь куда более удобный, как нам кажется, интерфейс.
Но есть 2 важных НО:
1) нужна совместимость со старым контрактом
2) либа принимает на вход функции из кодгена, и для комфорта разрабов кодген должен корректно приниматься как старой версией либы(для обратной совместимости), так и новой(для нового кода).

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

type Attach1<P, X> = P
type Extract1<A> = A extends Attach1<any, infer X> ? X : never;


type Attached1 = Attach1<{a: number}, string>;
type Extracted1 = Extract1<Attached1>; // unknown

https://www.typenoscriptlang.org/play?#code/C4TwDgpgBAgswEMDGALAjAHgAoBooA0A+KAXiiwChRIoBRAD2ACdlhMZiyYoJGIA7ACYBnWPGToMCfiDwBLfgDMITAsQD8BKAC4o-CADcVAbgpnq0OIlQRBaUmOuSA3gl38ArgFsARioC+eMLMCgDmhKYWdIwsSMC29mQMzKzs4jZ2EVAA9NlQHvwA1vwA9gDu-BRAA

Но если добавить ограничения, что тип P - это всегда объект, то можно сделать костыль:

type Attach2<P extends object, X> = P & {___private?: X}
type Extract2<A> = A extends Attach2<object, infer X> ? X : never;


type Attached2 = Attach2<{a: number}, string>;
type Extracted2 = Extract2<Attached2>; // string

https://www.typenoscriptlang.org/play?#code/C4TwDgpgBAgswEMDGALATAHgApQgD2AgDsATAZygHsAjAKwiWABooANAPigF4ocAyKAG8A+qLAAnAJYA3BIQD8ALjYBfAFChIUAKIFxyYJhiceMXAWLlY8ZOgw16jFpKIAzCOLad5bKMqIQ0h4A3GphmtBwiKgQJGjc1tF2ggj+AK4AttQeKixkwFJEAObsoRE6egax8Ty6BQZGNjFxpVAA9G1Q+YVFakA

Да, это некрасиво и ts будет показывать внутреннее поле. Но в рантайме можно туды ничего не класть и тогда всё будет типа ок. Кмк, для обратной совместимости с кривыми контрактами, вполне хорошее решение. У нас в библиотеке этот способ позволяет на уровне кодгена запихивать в типы любую дичь, которую можно потом достать из слоя обратной совместимости
👍4💩2
Даже jquery выпускает новые релизы https://blog.jquery.com/2024/02/06/jquery-4-0-0-beta/

А реакт все сидит на версии 18.2.0
😁13💩2🔥1
Если внезапно вам приспичит верстать письма, то есть супер дока по поддерживаемым фичам webview в разных почтовых клиентах

https://www.caniemail.com
👍71💩1
Вчера мне для кодгена нужно было генерировать цепочку выражений для ts:

type X = {} & {a: A} & {b: B} & ...

Пустой объект был нужен, так как {x: X} генерился по условию, в зависимости от заранее описанной спеки

Но вот какая засада:
type X = {} - это не пустой объект. Я даже не помню что это, но точно не пустой объект. ESlint-typenoscript для таких выражений рекомендует Record<string, never>, но это ломает первое выражение.

Но есть пакет, содержащий утилити типы, которые работают так как вы ожидаете: https://github.com/sindresorhus/type-fest

К примеру, пустой объект тут выглядит уже нормально https://github.com/sindresorhus/type-fest/blob/main/source/empty-object.d.ts

Не горячо, но советую. Упрощает жизнь, так как можно забыть о тупняках тайпскрипта.
👍3😈3💩2
Сейчас каждый фронтенд разраб знает об nvm. О тулзе, которая позволяет очень просто устанавливать почти любую версию ноды, но не каждый читает доку к nvm.

А если почитать доку, то можно там найти сверхудобную автоматизацию https://github.com/nvm-sh/nvm?tab=readme-ov-file#deeper-shell-integration
Она позволяет автоматически включать нужную версию ноды, в зависимости от директории, которая сейчас открыта. Вы можете не переключаться каждый раз руками через nvm use

#база
👍15👎2🔥2💩1🤡1
Не так давно мой хороший знакомый https://news.1rj.ru/str/kelin2play/573 задал простой вопрос: как подчистить ненужный мусор со своего компьютера.
Очевидное решение для меня - windirstat, но в комментариях подсказали ещё wizTree.

На примере этих продуктов можно проследить какая пропасть в между современными продуктами и хорошим маркетингом: на странице windirstat на первом же экране понимаешь как хорошо эта программа решает вашу проблему. У wizTree же - куча текста, в который надо вчитываться. И даже пролистывание главной не помогает.

Если вы в компании верстаете или дизайните вашу продающую страницу, то пытайтесь вмешиваться и не делать так как сделано у wizTree. Я, лично, ненавижу вчитываться в километры текста, когда вижу что-то новое. Да и никто не любит. Это сложно.
👍5💩3
Попробую вам сегодня продать GitHub Copilot. Эта штука всё же сносит мозг даже после года использования.

Главная вещь: правильно описанные типы позволяют почти не писать логику вовсе. Copilot реально понимает что тебе надо. Да, этот код нужно чуток подрихтовать, но даже в таком виде его спокойно можно отправлять в прод.
👍7🍌1
React.memo и React.forwardRef - это постоянная заноза в заднице с точки зрения типов, если вы в проекте используете TS.
И о решении одной из этих заноз написал https://news.1rj.ru/str/ru_react_notes/404

Подобное решение может казаться верным, но только в случае если вы не понимаете как работает React.forwardRef. Потому что React.forwardRef возвращает ОБЪЕКТ. Да, можно много рассуждать верно или нет это с точки зрения архитектуры, но имеем что имеем.
А в предложении поста говорится "а давайте обманём рантайм и скажем, что возвращается функция".

function fixedForwardRef<T, P = {}>(
render: (props: P, ref: React.Ref<T>) => React.ReactNode
): (props: P & React.RefAttributes<T>) => React.ReactNode {
return React.forwardRef(render) as any;
}

Не обманывайте себя. Да, кажется, что это необходимое зло, но это не так. Простой пример. Вы рефакторите уже существующий компонент и хотите добавить к нему ref. И вот тут вы не можете гарантировать, что его не вызывают как функцию. Потому что, увы, это так. В проектах куча говна, в котором встречается любой код, который не запрещён ESLint'ом. А и запрещённый им тоже есть.
Поэтому максимальными силами старайтесь сохранять все инварианты существующего кода.

По этой причине более корректным решением будет

function fixedForwardRef<T, P>(
render: (props: P, ref: React.Ref<T>) => React.ReactNode
): (props: P & React.RefAttributes<T>) => React.ReactNode {
const Forwarded = React.forwardRef(render);
return (props: P & React.RefAttributes<T>) => {
return <Forwarded {...props} />
}
}

Как минимум потому что все вызовы компонента напрямую продолжат корректно вызываться.
https://github.com/tc39/proposal-set-methods

Ого, какая штука, оказывается есть. Походу кто-то всерьёз решил заняться над комфортом работы с коллекциями. Оно аж уже в Хроме и Сафари есть. Походу пора ставить полифилы и вовсю использовать
👨‍💻2