Организованная Программерская Группировка
76 subscribers
75 photos
7 videos
40 links
Канал о веб (и не только) разработке от фронтэнд лида @egorshar
https://egor.sh
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Я не люблю тыкать на чужие косяки, потому что они бывают у всех, но блять! Как? Неужели ни у кого глаз не задергался, когда делали/тестировали/релизили?
Salesbot Designer

Наткнулся я тут на опенсорсную либу для построения node-based редакторов - reactflow.dev и решил написать историю создания нашего в #amocrm Salesbot дизайнера. Тем более, глянув в дев-тулзы и код, оказалось, что схема работы либы архитектурно очень похожа на нашу, а учитывая что, судя по гитхабу и блогу, зарелизились они в 2020 году - есть мнение, что сэйлсбота они как минимум видели или даже изучали.
Дело было в 2018 году перед релизом и конфой в Сан-Франциско, у нас тогда уже был бот, который работал через JSON-спецификацию и использовался в основном в наших собственных аккаунтах, ну и у тех, кто работал с партнерами. Появилась задача сделать визуальный редактор, чтобы любой юзер мог без помощи разработчиков сконструировать хотя бы простой сценарий бота с запросом контактных данных, это и было показано в демо на презентации.

И вот сидя в Варшаве, ожидая сначала записи на собеседование на визу в США, а потом паспорта с вклеенной визой (вот было время, да?) я пилил наш конструктор ботов. Так как до этого я не делал таких задач сначала попытался поискать примеры на существующих решениях, погуглил D3.js, но каких-то готовых вариантов не нашел, поискал на гитхабе, тоже ничего толкового от чего можно оттолкнуться не нашлось. Это сейчас с такими библиотеками у них целая категория, а тогда ничего подобного не было.

Я начал экспериментировать в CodeSandbox, для начала пробовал рисовать на канвасе и зачем-то хотел решать коллизии стрелок, но меня вовремя остановили, остался вот такой прототип. Канвас не подошел еще и потому, что по дизайну нам нужно было редактирование “по месту” в перетаскиваемом блоке, а нормальной ui библиотеки для канваса, чтобы были все необходимые контролы (плюс они еще и должны быть в привычном для пользователя системы виде) - тоже не было.

Поэтому в какой-то момент мне пришла идея, чтобы блоки были обычными div-элементами, а стрелки рисовались на отдельной svg-ноде, которая бы лежала внизу под ними. Для drag’n’drop’а изначально я заюзал jQuery UI, так как она использовалась внутри amoCRM, а для зума и панорамирования в редакторе - jquery.panzoom.
Рабочая область src/workarea/index.js Cостоит из блоков и связей.

Блок src/workarea/block/index.js Вьюшка блока. Блок можно перетаскивать и добавлять в него экшены.

Экшен src/workarea/action/index.js Это базовый структурный элемент блоков, каждый блок должен содержать хотя бы один экшен. Примеры экшенов: сменить этап сделки, установить значение поле, отправить сообщение и тд.

Стрелки src/workarea/connections/connection.js Обычная стрелка от одного блока к другому. Каждая стрелка знает из какого блока она начинается (start_block) и в какой блок ведет (end_block). В этих свойствах хранятся модели соответствующих блоков. При перетаскивании у них обновляется x, y координаты, изменение которых слушают стрелки и также реагируют на изменение.

Стрелка goto src/workarea/connections/goto_connection.js Ведет не напрямую к конечному блоку, а рисует голубой прямоугольник с индексом конечного блока. Используется если goto ведет на какой-то предыдущий шаг, либо если goto перескакивает на несколько шагов вперед.
Спустя пару лет после создания конструктор ботов понадобился и в другом нашем проекте амо | корпоративный мессенджер. И вот тут я пожалел, что не подумал сразу о переиспользовании и довольно сильно на старте завязался на стек amoCRM. Так как пока конструктор был частью продукта он был построен на том же backbone + jquery, а вынув его в отдельную библиотеку для amoCRM получился хоть и небольшой, но оверхед по этим компонентам, однако, lazy-loading нас выручит и не будем сильно переживать по этому поводу.

Конечно, к тому моменту, когда потребовалось вытащить это все добро в самостоятельную библиотеку накопилось уже много опыта и что-то можно было сделать по-другому, но релиз был и в amoCRM и в мессенджере, поэтому времени было немного - я где-то за неделю-полторы распилил конструктор в отдельную библиотеку, выделил собственные сущности конструктора, внешние сущности типа полей (для amoCRM это поля сделок, например, а для мессенджера это собственные поля бота или формы внутри бота), избавился от зависимости от jQuery UI, переписав на нативные события, так как она довольно большая и все-таки грузить два ее экземпляра в amoCRM не хотелось.

Дальше конструктор нужно было оформить как переиспользуемый модуль. Вынес его в отдельный репозиторий в гите и на тот момент (это примерно 2020 год) я выбрал способ подключения в проект как git submodule, хотя сейчас бы рассмотрел lerna или модуль из внутреннего репозитория в package.json.

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

Во-первых, недавно я купил домен egor.sh. Да, 16к рублей на reg.ru в год и 83$ - 30% по нагугленной скидке за 5 минут на godaddy за 2 года.

Во-вторых, обновил основной фреймворк nextjs до 13 версии. Мне всегда он нравился как с точки зрения DX, так и фокуса на производительности работы. Вам не нужно ковыряться в конфигах, чтобы все само собиралось как в прод, так и в дев с оптимальными настройками.

В новой версии завезли React Server Components, по-моему первые из всех разработчиков фреймворков. Новую файловую структуру, мидлвэры для модификации запроса до того как он будет обработан. Например, у меня из запроса получается заголовок Accept-Language и по нему показывается английская версия, если предпочтительный язык браузера пользователя не русский.

Из коробки доступна оптимизация изображений, nextjs за вас сожмет картинку на лету и пользователь загрузит ее в минимальном обьеме для его устройства.

Ну и вишенка на торте это облачный сервис от создателей фреймворка - Vercel. Во-первых, интеграция с гитхабом через OAuth и все, что нужно потом сделать для деплоя приложения это пуш в мастер. Так же доступны тестовые стенды, env-переменные и все-все-все, что необходимо нормальному сервису. Во-вторых, сам фреймворк отлично интегрирован в эту систему и сжатие изображений, про которое я говорил выше, кеширует результаты на их же CDN. Так же в CDN можно закешировать результаты работы API-запросов, если требуется, и делается это минимальным количеством телодвижений в коде.

В общем, да, я в восторге от того как фреймворк и сервис развивается.

Ну и по-мелочи еще перевел стили на tailwindcss с поддержкой темной темы, попробовал в 3d с react-three-fiber (текстура для шара там мегабайт весит, поэтому грузится долго - пока было лень придумывать что-то с заглушкой, а с пол тычка не получилось).

Посмотреть вживую egor.sh или в коде https://github.com/egorshar/homepage
👍6
Tinkoff оказывается "пробует" в open-source, наткнулся на их github-аккаунт.

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

Забавно другое, это, собственно, их тот самый open-source. Бегло глянув репы, выглядит это как сборничек своих велосипедов, зачем-то вынесенный в паблик. Похоже, что основа кодовой базы или когда-то была, или до сих пор написана на Angular и решения оттуда так близки команде, что они пытаются перетащить их на рельсы других библиотек, это я про tramvai.
Или набор утилит utils.js с обязательным бенчмарком, что оно быстрее и тоньше lodash, только самым первым почему то сравнивается импорт полной библиотеки lodash, но это ладно, так положено во всех бенчмарках, лол.

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

Выше у меня был пост про самое начало amoCRM и выбор в пользу requirejs вместо своего модульного загрузчика (это вопрос 2014 года, если что), вот с тех пор я стараюсь по-максимуму использовать готовые решения вместо своих велосипедов, а уж тем более если они признаны сообществом как стандарты.
Хороший пример организации большого и сложного приложения на nextjs 13 (написано на typescript). Причем это не стартер, а прям прилага, которую можно изучать как пример того, как выглядит современное веб-приложение с использованием данного фреймворка. Тут и новый роутинг, и серверные компоненты, и остальные новые фичи. Ну и темная тема в комплекте, конечно 🫡
Million.js

Бывают моменты, когда важна производительность. И нет, это не те моменты, когда на ревью ты видишь какую-нибудь работу с плейн-объектами с экономией на спичках, а потом человек обращения к DOM-дереву не кеширует.

Когда-то в мир пришел React и все начали повторять как мантру, что он очень быстрый из-за своего механизма virtual-DOM. Кто-то может даже слышал мем 'the virtual DOM is fast', often said to mean that it's faster than the *real* DOM. Пошло это с конфы 2013 года с кор разрабом React, который это сказал. Правда потом он поправился в духе, что “вы можете написать что-то на ассемблере и превзойти компилятор C, так же как вы можете руками манипулировать с DOM и сделать что-то быстрее, чем React, но с React вы можете разрабатывать не задумываясь о производительности, а приложение будет по умолчанию быстрым”. Если хотите почитайте первоисточник из блога svelte.

Если коротко, то virtual-DOM это всегда оверхед, потому что для синхронизации состояния приложения с реальным DOM-ом (так называемой “реконсиляции”) будет всегда происходить дополнительная работа браузера.

И вот тут на сцену в белом выходит Million.js (если что у них на сайте прикольная демка, можете поиграться).

Суть его работы в статическом анализе, с помощью которого динамические части виртуального DOM выделяются в некую мапу EditMap, в этой мапе грубо говоря хранятся инструкции для редактирования реального DOM-дерева и при изменении состояния компонента реальный DOM обновляется напрямую через этот EditMap. Однако, хоть они и заявляют, что “just wrap your React components” - у всего на свете есть своя цена. Поэтому есть куча ограничений, например, нельзя в conditional return или вывод дочернего JSX. Вот например, что нельзя из доки (а мы ведь это все часто используем):

function IllegalComponent({ name, initial }) {
const [count, setCount] = useState(initial.count);
const greeting = `Hello ${name}!`;

if (count > 10) {
return <div>Too many clicks!</div>; // don't use conditionals
}

return (
<div>
{greeting}
<button onClick={() => setCount(count + 1)}>
{<div>{count}</div> /* don't pass JSX */}
</button>
</div>
);
}

Подытожим, либа не является каким-то общим решением всех бед производительности. Если эти проблемы у вас появились, то начните с профилирования приложения, нет ли лишних ререндеров (если в контексте реакта, начните с wdyr). Нет ли долгих синхронных операций, которые блокируют main-тред. И только если вы точно локализовали проблему и она действительно находится в конкретном месте, которое поддается такому пути решения, то используйте. Тем более вес самой библиотеки меньше 4KB.
Не все про веб, попалась тут репа какого-то китайского PhD Candidate и знаете - пора, как в эпоху короновируса закупались защитным масками, закупаться фольгой, чтобы делать шапочки. На самом деле github используется только как площадка для публикации научной статьи, поэтому вот сайт, там статья и еще немного картинок.

Короче, эти умельцы научились по сигналам из аппарата МРТ с помощью модели Stable Diffusion генерировать видео “что сейчас видит человек, который подключен к аппарату”. На картинке коты сверху это видео, которое показывается человеку, коты снизу это сгенерированные нейросетью кадры на основе сигналов, считанных из головного мозга.

WAT?

Да, пока для того, чтобы залезть к вам в мозг нужен этот огромный шкаф для МРТ, но с такими разработками мыслепреступления в недалеком будущем не такой уж и антиутопией кажутся.
1
Нашел тут интересный пост про анимацию курсора в многопользовательских приложениях. И как всегда задача, которая с первого взгляда не кажется такой уж сложной, под капотом скрывает много всего интересного и отвечает на вопрос зачем у вас в универе была высшая математика (или нет, если вы гуманитарий).

Во-первых, если тупо раз в, к примеру, 120 мс обновлять позицию курсора, то уже анимация получается рваной, так плюс, что в реальной жизни к такому тротлингу надо прибавить еще от 5 до 15 мс. Итог в реальном приложении с сетевыми лагами будет еще хуже.

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

Следующий вариант решения - это spring animations. Тут отличие от обычной transition-анимации в том, что используются не только координаты до и после, но и текущий импульс. За счет этого анимация получается более плавной.

И финально есть еще более крутой вариант это использование кубического сплайна (Spline Interpolation). Это метод, когда новые точки строятся относительно набора уже известных точек и между ними рисуется параболическая кривая. Из-за того, что нам нужно накопить немного точек, чтобы знать как построить кривую между ними, получается небольшая задержка перед рендерингом, но это небольшая цена за практически близкий к реальному путь движения курсора на экране.

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

Когда мы говорим про React и стейт-менеджмент почти всегда мы думаем про Redux и это не значит, что других нет, просто это уже такой стандарт и все им пользуются (и не всегда оправданно), что я как-то и не следил, что нового в этой теме появляется.

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

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

import { create } from 'zustand'

const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}))

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

function BearCounter() {
const bears = useBearStore((state) => state.bears)
return <h1>{bears} around here ...</h1>
}

Либа небольшая по размеру, имеет 30к звезд на гитхабе, решает многие дефолтные проблемы гонок, потери контекста и тд. Ну и посмотрите какой параллакс из 2013 у них на сайте.
👍41
Когда в начале 2022 года после всем известных событий на vc всплывали посты об импортозамещении Figma ничего кроме улыбки у меня это не вызывало и все вот почему.

Принес вам ссылку на пост кофаундера и CTO фигмы, где в 2015 году он рассказывает, что фигма это как бы уже тогда и не совсем веб-приложение. Да, вы запускаете его через браузер, но что там под капотом?

Реализовано это счастье на C++ с использованием в 2015 asm.js, а в 2017 WebAssembly. Если у вас вопрос почему, то в тексте есть все ответы, но вот несколько важных поинтов:

– на стороне C++ они полностью управляют памятью без использования JavaScript Garbage Collector, который тоже конкурирует за ресурсы в main треде приложения и влияет на отзывчивость интерфейса, и в целом такой подход с использованием прекомпилированного кода на C++ позволяет иметь от 2x увеличения производительности в том числе, что браузер не занимается работой по интерпретации его в рантайме;

– html и svg дают много оверхеда и для задач фигмы чаще всего намного более медленные, чем 2D Canvas;

– всякие эффекты типа блюра, blend modes и масок, актуальные для графических приложений, реализованы по-разному между браузерами;

– также как и рендеринг текстов, который отличается между браузерами и операционными системами, в этом мы и сами (как любители пиксель-перфекта) не раз убеждались в своей практике, но там есть пара ссылок, где можно почитать подробнее (ссылки старые, но заверяю, что ничего за эти годы не поменялось);

– собственно, сами браузеры тоже проблема - каждый реализует разный набор возможностей, где-то что-то поддерживается, где-то что-то нет, в статье говорится про кастомные курсоры, которые в каждом браузере работают через разные форматы (SVG for Firefox, -webkit-image-set for Chrome and WebKit, and the ancient .cur format for IE).

И все это значит, что нельзя обучить чела на курсе по React-разработке за пару месяцев и пустить его пилить фичи в продукт. Поэтому и в никакое импортозамещение таких сложных продуктов я не верю, тем более что из-за сложности в опенсорсе ничего похожего не найти. Это все-таки не Rocket.Chat форкнуть, налепить свой логотип и сказать, что мы запустили аналог Slack.
🤯1🙈1
Scroll anchoring

Короче, погрузился я тут в одну тему и решил, что можно про нее даже написать сюда.

Когда мы делаем какие-то chat-подобные приложения, когда при подгрузке контента надо актуализировать позицию скролла мы это обычно делаем так:
– получаем scrollHeight до изменения контента;
– производим манипуляции по изменению;
– получаем scrollHeight после изменений;
– считаем дельту и на эту дельту смещаем скролл.

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

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

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

Поэтому если вы делаете чат приложение и сами управляете скроллом после загрузки данных или других манипуляциях с контентом внутри скроллируемой области, то добавляйте это свойство:

.scroller {
overflow-anchor: none;
}

И будет вам одинаковое поведение для всех браузеров без танцев с бубном.
🔥5👍1🤯1
webpack в amoCRM

Есть у меня статья двухлетней давности, про начало сборки фронта в amoCRM. Можно найти по тегу #amocrmbundling, а можно и долистать вверх, я не сказать, что очень много написал за эти два года, а сейчас будет пост на целых 2 сообщения 😅

В общем в итоге я выбрал require.js. Изначально, исходя из ее популярности на тот момент, и что она покрывала наши собственные потребности. Она позволяла в дев режиме собирать фронт в рантайме, подгружая файлики по сети, а в продакшене подгружать уже собранные чанки, чтобы количество запросов на статику в продакшене не было таким диким. Плюс разработка у нас построена через дев-сервер, на котором крутятся все сервисы и фронт загружался тоже с хоста разработчика. Сейчас уже смешно, а когда мы в Сан-Франциско проводили конфу и мне надо было оттуда прогать конструктор ботов - было не смешно, когда пинг оттуда до дев-сервера, находящегося в Мск доходил до 2 секунд на статичный файл. Приходилось один раз загружать фронт, выключать disable cache в хроме и вручную прописывать пути файлов, которые я редактировал, и которым при загрузке надо подставить рандомный хеш, чтобы именно для них кеш сбросился, иначе загрузку страницы можно было ждать пару минут.

В дальнейшем на базе require.js построилась система загрузки виджетов, которая с одной стороны дала гибкость для доработки продукта сторонними разработчиками, с другой, до сих пор вставляет палки в колеса при различных рефакторингах и переделках внутренних компонентов. Тут можно сказать, что сами виноваты, что не предоставляем описанный SDK, только по которому можно было бы разрешать работать с модулями системы, но имеем то, что от нас требуется всегда думать об обратной совместимости всех переделок, так как любая из них может рандомно выстрелить в одном из виджетов.

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

Вот с переходом на webpack получилась ровно такая история. Первый раз не получилось потому что у меня не было решения как встроить сборку webpack в наш монолит, я сконвертил конфиг require.js в конфиг webpack, довел до плюс/минус заводимого состояния, но дальше было две проблемы:

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

2. У нас оставалась система виджетов, которая работает на require.js и использует наши модули в рандомном количестве, поэтому надо было оставить возможность использования наших модулей для виджетов.

По итогу при первом подходе к этой задаче оба вопроса остались нерешенными, начался очередной релиз и я замариновал ветку до лучших времен. И да, прикольно потом, когда актуализируешь такую ветку после релиза - прилетает что-то около 5000 коммитов из гита, сразу думаешь сколько же мы там накодили за несколько месяцев?
Продолжение поста выше... #amocrmbundling

Как в итоге решились оба вопроса?

Во-первых, я завел куку для дев-окружения, что-то типа use-localhost со значением Number, с помощью которого можно указать порт, на котором крутится webpack-dev-server. При получении запроса бекенд смотрит, если мы в дев-окружении и есть эта кука, то хост статики выставляется localhost с номером порта из значения куки. Таким образом теперь фронт грузится с локальной машины, проблемы Сан-Франциско теперь быть не может.

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

window.define('${requirejsModuleName}', function(){
return module.exports;
});
window.require(['${requirejsModuleName}']);

Таким образом если необходимый модуль для виджета был загружен с рантаймом страницы, на которой загрузился пользователь, то для этого модуля не будет вызван никакой дополнительный запрос в сеть, мы зарегистрировали экзепляр от webpack в регистре модулей require.js.

Если модуль не был загружен, то require.js сходит за ним в сеть на наш сервер, так как конфиг и структура файловой системы для require.js не изменились. Проблема была только с вендорными либами, которые лежат в папке node_modules, которая в свою очередь на продакшен не деплоится, но для этих модулей я прописал в конфиге пути на cdnjs. Поэтому если какая-то вендорная либа, которую захочет подгрузить виджет не загружена в рантайме, то виджет подгрузит ее с cdnjs.

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

Дальше был такой же долгий процесс перехода на es6, но это уже, как говорится, другая история.
😎2
Всем привет, начало будет странным, но потом все будет понятно.

Надо было мне в Турции купить солнцезащитный крем, в отеле цена была каких-то конских 44 евро за обычную нивею. В итоге в городе в аптеке нашлась такая за 500 лир, я переводил это все в рубли с помощью конвертера валют, которым уже давно пользуюсь (когда живешь на 2 страны очень нужный инструмент) и меня триггернуло.

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

В общем так в отпуске родился мой небольшой пэт-проект, который я решил сделать полностью бесплатным без какой-либо рекламы и опен-сорсным. Пока готова версия для iOS, но скоро приедет и андроид.

Ссылка на AppStore.

P. S. Если под постом наберется какое-то количество реакций, то запилю пост о том, как оно работает.
👍15🔥8👏2
Как и обещал пишу о том, что под капотом у How Much In. Начнем с не менее важной части, чем само приложение - откуда данные?

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

Поэтому первым решением было сделать кеширующую API-прослойку. Если посчитать, что обновление мы будем делать раз в час, то 24 * 30 = 720. То есть даже укладываемся в бесплатный лимит, но все-таки я больше про интерфейсы, чем пилить какую-то апишку. Конечно, лезть в весь этот бекенд мне не хотелось, поэтому, еще немного поискав, я нашел вот эту репу https://github.com/fawazahmed0/currency-api

Какой-то хороший человек делает выгрузки курсов раз в день и кладет результаты в свой публичный репозиторий. А дальше красиво, не многие знают, но есть такой публичный CDN - JSDelivr. Он кроме хостинга всяких публичных библиотек занимается зеркалированием публичных GitHub-репозиториев размер которых до 50 МБ. Сам я нашел это когда мы делали сайт-визитку в amoCRM и оказалось, что Taplink, например, использует такой подход для раздачи статики на своем продакшене. Просто деплоят фронт в публичную репу на гитхабе, а в продакшене ссылки на статику ведут на эту репу через jsdelivr.

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

Это было просто, пришел на помощь Yandex.Cloud с их API Gateway и решилось все одним YAML файлом примерно следующего содержания:

paths:
/{path+}:
get:
parameters:
- name: path
in: path
required: false
schema:
type: string
responses:
'200':
description: API endpoint
content:
'application/json':
schema:
type: "string"
x-yc-apigateway-integration:
type: http
url: https://cdn.jsdelivr.net/gh/fawazahmed0/{path}.min.json

Таким образом мой эндпоинт сейчас просто проксирует запрос на jsdelivr и эту публичную апишку: https://api.how-much.in/currency-api@1/latest/currencies

Вопросы? Откуда берутся данные? Честно - сам толком не понял, в issues чувак не отвечает, но вроде плюс/минус курс совпадает. Обновление раз в день? Да, но цель была не потухнуть на этапе разработки бекенда, а выпустить приложение, поэтому пока пусть будет так - для ознакомительных целей, чтобы примерно перевести сумму в другую валюту достаточно - эталонной точности нет, но и не надо пока. Если интерес останется, то сделаю currency-api@2 и оно будет обновляться чаще и показывать более точно.

На этом пока все, итак вроде много получилось, про интерфейс и react-native в следующих сериях.
👍9