Организованная Программерская Группировка
76 subscribers
75 photos
7 videos
40 links
Канал о веб (и не только) разработке от фронтэнд лида @egorshar
https://egor.sh
Download Telegram
Как и обещал пишу о том, что под капотом у 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
Ура! Гугл наконец-то промодерировали андроид-версию спустя неделю!

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

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

Итак, в приложении используется FlatList для вывода списка валют. Каждая валюта под названием имеет фиолетовый прямоугольник, который является и выводом значения и полем ввода одновременно. При выводе значения в текст число форматируется в соответствии с локалью пользователя через ReactIntl, отбивает тысячные, десятичные доли и тд. При этом инпут ввода - стандарный TextInput. Если мы заводим стейт и перерисовываем по клику то текст, то инпут - уже здесь у react-native начинаются затупы, подлагивания при появлении клавиатуры и ты чувствуешь, что что-то не то. React может и чувствуется, а вот native как-то не очень. Поэтому делаем хитро.

<View style={tw`relative`}>
 <TextInput
  ref={inputRef}
  defaultValue={valueRef.current}
  style={tw`opacity-0`}
  onChangeText={v => {
   setValues(currency, parseFloat(v));
  }}
  onFocus={() => {
   inputRef.current?.setNativeProps({
    style: { opacity: 1, zIndex: 1 },
   });
  }}
  onBlur={() => {
   inputRef.current?.setNativeProps({
    style: { opacity: 0, zIndex: -1 },
   });
  }}
  onEndEditing={e => {
   const v = e.nativeEvent.text;

   if (initialValueRef.current !== v) {
    setTimeout(
     () => setValues(currency, parseFloat(v), true),
     500,
    );
   }
  }}
 />

 <View
  pointerEvents="none"
  style={tw`absolute`}
 >
  <Text>
   <FormattedNumber
    value={value}
    style="currency"
    currency={currency.toUpperCase()}
   />
  </Text>
 </View>
</View>

У нас есть оберточный View, внутри которого с абсолютным позиционированием лежит Text с отформатированным значением, для его родителя указан pointerEvents="none", то есть клик по нему не обрабатывается. Под ним лежит прозрачный TextInput и когда мы кликаем на сумму валюты мы на самом деле ставим курсор в инпут, который на фокус становится непрозрачным и начинает нормально отображаться, а по блюру, соответственно, скрывается. Такой подход позволяет иметь полностью нативное ощущение при постановке курсора в инпут в списке неограниченного размера.

Следующая оптимизация начинается, когда мы вводим значение. Если мы сразу пересчитаем значение для всех валют (а их может быть выведено более 150), то опять же получим дерганье как в эпилептическом припадке, а не ощущение летающего нативного приложения. Поэтому в коде выше setValues вызывается 2 раза. Первый раз на onChangeText и тут мы берем индекс изменяемой валюты и пересчитываем только 10 сверху и снизу, чтобы перерисовка по мере ввода требовалась только 20 элементам списка максимум (тем, которые точно видит пользователь). Так мы получаем близкую к идеальной работу пересчета по мере ввода. А уже на onEditingEnd пересчитываем для всех и там добавим небольшой таймаут 500мс, чтобы клавиатура скрылась без тормозов.

Подводя итог, да, на react-native достаточно легко писать приложения сразу под обе мобильные платформы, но если вы правда хотите ощущения нативности, то на каждом шагу вам нужно будет продумывать вот такие нестандартные решения часто стандартных вопросов, либо идти на компромисы.
👍21🔥1
Сегодня утром я за один час сделал лендинг для прилы How Much In. Пока это самый крутой экспириенс по no-code запускам, что я пробовал. И это Framer.

Для начала тебя просят ввести словесное описание того, что ты хочешь наклепать. Мой финальный вариант был: landing page about free currency converter mobile app even without ads that called "How Much In" in white/violet color scheme without pricing section

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

Сгенерив несколько вариантов, я получил практически то, что финально вы видите на лендосе. Был немного другой фиолетовый, я руками поправил на цвета из моей иконки. Изначально был выбран другой шрифт заголовков, это можно тоже менять руками. Эта штука сгенерила булщит тексты, которые я частично самостоятельно скорректировал через ChatGPT, частично оставил прям то, что сгенерил AI Framer'а.

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

Довольно кусачая цена в 5 долларов в месяц при годовой оплате и отсутствие экспорта проекта, на что я надеялся, когда туда полез, но деньги зарабатывать тоже как-то надо ребятам.
🔥52👍1
Вот так вот выглядит интерфейс самого Framer
Впервые пробую запустить кампанию на Product Hunt для How Much In. Если не сложно поставьте плюсик.

На этом скорее всего посты про приложение закончатся, программа максимум для этого пэт-проекта выполнена. Поздравляю, вы прошли игру.
🔥3
Жизнь никогда не будет прежней, проверяйте
🤯6😁4👍1
Как найти крутого дизайнера на проект?

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

Все знают, что у телеграма бывают конкурсы по разным спецификациям. В том числе бывают и конкурсы дизайна. Для этого они даже запилили сервис Developer Challenges, там публикуют все свои проведенные конкурсы, а также их результаты. И даже ранжируют их по крутости, ведь от этого зависит кому какой денежный профит полагается.

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

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

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

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

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

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

И правда, я тут поймал себя на мысли, что версии фронтенда amoCRM, которую я прям с нуля начал, скоро будет 10 лет (лол, какой я старый). И если я сейчас с позиции прогера посмотрел бы на ту начальную версию, то естественно обплевался как там все плохо было сделано. Однако, это вообще не помешало продукту взлететь. Код всегда можно переписать, чем мы до сих пор занимаемся 🙃
👍82😁2
Собственно, касаемо переписывания кода. Наконец-то можно констатировать, что вся кодовая база amoCRM теперь полностью в ES6 со всеми современным плюшками языка.

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

Так что параллельно с разработкой других фич постепенно, папка за папкой, я переводил код (по паре папок так же помогли ребята из команды), мердж реквесты на 200, 300 и даже 600 файлов это норма для данного тикета. Но теперь ура, все получилось.
👏12🔥2🤯1
Немного заспойлерю, что я решил заиндимейкить. Как гласит первое правило индимейкера - не пытайся решать чужие проблемы, решай свои и скорее всего окажется, что есть еще люди, которым это тоже актуально.

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

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

Так появился Perf Ninja, который будет представлять из себя one-button-deploy сервис на NextJS. Выполняет только нашу простую задачу, данные хранит в вашей Supabase, а код крутится в вашем Vercel.

Такой коммитмент, чтобы не слиться.
👍5🔥1
Я тут сделал калькулятор для How Much In и по этому делу решил запоститься на HackerNews.

Если у кого есть там аккаунт, буду рад лишнему плюсику, хотелось бы вылезти в основную категорию show.
👍4
Организованная Программерская Группировка
Сегодня утром я за один час сделал лендинг для прилы How Much In. Пока это самый крутой экспириенс по no-code запускам, что я пробовал. И это Framer. Для начала тебя просят ввести словесное описание того, что ты хочешь наклепать. Мой финальный вариант был:…
И кстати дизреспект Framer, пришлось съехать с него. Я ж там оплатил на год подписку на минимальный тариф, потом гугл меня выкинули из play store из-за того, что не было страницы privacy, а когда я захотел создать ее, то фрэймер сказал, что за твои жалкие 60 долларов в год ты можешь опубликовать только 1 страницу и экспортировать тоже ничего не дадим.

Пришлось пожертвовать анимациями, экспортнуть просто через хромовское расширение Single File и переехать в мой любимый Vercel. Ну хоть гугл сразу разбанил.
👀7😁1
Всегда думай на шаг вперед

How Much In я сделал на бесплатной публичной апишке, которая работает хитрым способом через связку GitHub + jsDelivr.

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

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

Однако, так как я предусмотрел эту ситуацию - все, что мне пришлось сделать - настроить 302 редирект со старых ссылок и выпустить новую версию приложения с новыми ссылками. В итоге приложение продолжило работать без перебоев, мне это стоило 0 рублей, ну и на данный момент запросов с редиректом осталось менее 5%.
🔥5👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Прошла первая неделя как я безработный, но руки-то чешутся и надо что-то делать.

Вот сидел я себе, смотрел кейноут конфы Vercel Ship. Там показали возможность комментирования на сайте, сделанном на NextJS прямо кликом по месту. И я подумал ведь правда, когда мы работаем с дизайнером в Figma, мы можем оставлять комментарии прямо на артборде, а когда говорим про верстку, то обсуждение верстки (или в целом реализации интерфейса по макету) уходит куда-то в инструменты общения.

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

Кажется, может полететь, поэтому с выходных я начал пилить это расширение (на видео), хаха. Пожалуйста, отговорите меня или вдруг такое уже есть?
🔥8😁1🤯1
Media is too big
VIEW IN TELEGRAM
Апдейт по прогрессу с экстеншеном. Появилась авторизация, накидал модель предметной области, пока она будет простой:

- Проект (проект мы можем назначить на произвольный домен, условно есть проект X, я смотрю его на localhost, а заказчик приемку осуществляет на продакшене, дальше инвайтит меня в проект, я в расширении вижу этот проект X и назначаю его для localhost, ну и вижу на своем локалхосте комментарии заказчика при условии, что версия у нас одинаковая и верстка будет совпадать)
- Доступ к проекту (регулируем доступ к проектам для пользователей)
- Тред (точка на странице URL, к которой привязаны комментарии)
- Комментарий (ну тут, собственно, понятно)

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

И да, как же круто в 2к24 делать новые проекты, когда есть хотя бы shadcn/ui и ShipFast, хоть последний и стоит $200, но моя идея его покупки в комьюнити, посмотрим даст ли эта инвестиция какого-то профита для первоначального маркетинга или нет.
👍7👏4🔥3
Media is too big
VIEW IN TELEGRAM
Как говорится, я вас заебу одним аккордом, но прошел еще один день и вроде как комменты ожили, а это можно сказать событие.

Такими темпами к концу недели, думаю, что-то полуживое будет и в продакшене.

Feeling enthusiastic...
🔥14👏2👌1
Если у кого есть желание побыть бета-тестером, то вот тут можно поиграться:

https://www.testing-toolbar.com/shared/6655c4625663311108dff9a1/JvBYke6W-9vXY5WHdoWuX

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

Дальше заходим на эту страницу, мои текущие комменты на ней.

Запускаем экстеншен (у него пока калечная дефолтная иконка в виде какой-то красной загогулины от vite-плагина для создания экстеншенов), он должен подцепить авторизацию. Нажимаем на шестеренку и выбираем проект nextjs, обновляем страницу и снова запускаем экстеншен, дальше должны загрузиться комментарии в блоке Edge and Node.js Runtimes.
👍5
Контрактная разработка

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

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

Как показывает практика даже опытные разработчики не все знают об этом методе, поэтому поехали. Поможет нам mswjs. Эта штука умеет мокировать как бекенд реализацию, так и предоставлять моки для браузерных приложений. Суть такая, что эта штука поднимает service-worker, который перехватывает запросы вашего приложения, если запрос описан в моках, то отдаст мок, если не описан, то может падать, а может проксировать на реальный url.

При этом вы пишете настоящую реализацию, которую не надо потом доправлять. Все, что в конце потребуется - это выпилить мок хэндлер и начать ходить на реальные ручки. Если, конечно, ваш “контракт” фронта с бекендом не протух за время разработки, такое как мы знаем тоже частенько бывает.

Скрин как это работает на базе одного сайд-проекта.
👍11🔥5
Одна строчка, импакт огромный. Люблю такое.
👍6🔥5