Buy tickets for the next conference JavaScript fwdays’24 conference!

Crafting a Third-Party Banking Library with Web Components and React [ukr]

Talk presentation

This talk will be about how Unit built White-Label UI Components in React while making them completely native. We will discuss rendering React in Web Components, communication with them via native JS events, and the modularity of each Component.

German Smolyar
Unit
  • Software Engineer at Unit
  • Proud Father of an Amazing Daughter
  • Enthusiastic about Software Engineering across Backend and Frontend domains
  • Passionate about Innovative Architectural Solutions
  • Former radio host
  • His journey began as a PHP developer, and now he specializes in combining Scala and TypeScript
  • Hailing from Zhytomyr, from 2017 calls Tel Aviv his home
  • LinkedIn

Talk transcription

Всім привіт! Дуже дякую, що приєдналися. Я правда хотів розпочати свою доповідь по-іншому, але розпочав з того, що якщо, не дай Бог, ви почуєте сирену – не хвилюйтесь, це може бути не у вас, а може бути тут у мене в Тель-Авіві. Але взагалі, я думаю, що ні Хамас, ні Москалі не завадять нам сьогодні почути історії, класні презентації про технологію, TypeScript, React і т.д. І взагалі, я вважаю, що якщо хтось хоче зашкодити світ, то краще б писав собі на PHP і все, аніж робив те, що вони роблять зараз. Тож розпочнемо, і розпочну я з того, що ви не одні, слава Богу, в цьому світі. І якщо ви будуєте сьогодні систему, і в вашій системі повинні бути якісь банківські фічі, такі як аккаунт, карточки або щось інше, не потрібно будувати банк самому. Потрібно інтегруватися з банком або інтегруватися з якою-небудь банківською системою чи використовувати Embedded Banking.

Коли ми говоримо про якусь інтеграцію, виділяють три види, три типи інтеграції. Це Custom Coding, Low-Code і No-Code Solutions. Custom Code – це коли ви інтегруєтеся на рівні API, у вас є повна гнучкість, ви можете писати що завгодно, адаптувати це як завгодно, під що завгодно. Low-Code – менше гнучкості, але це залежить, сьогодні ми побачимо це. Але я для себе виділяю те, як інтеграцію на рівні фронтенду. І No-Code Solutions – це коли вам взагалі не потрібно писати коду, або потрібно просто вбудувати якусь одну строчку коду, і все буде працювати. Отже, цим сказаним я раджу представити вам сьогоднішню свою доповідь, яка називається "Crafting a Third-Party Banking Library with Web Components and React". Трошки про себе, мене вже представили.

Мене звати Герман Смоляр, я – software engineer у компанії UNIT, народився в Житомирі, вивчав Кібербезпеку у Житомирському військовому інституті імені Сергія Павловича Корольова. Чи є хтось в Житомирі, будь ласка, пишіть у Discord, тут радий вас бачити, Житомир справді існує. У минулому я був радіоведучим, також я працював багато на весілях. Я б міг розпочати це з шановна гостя "Друга родина", але не буду. У 2017 році я переїхав у Ізраїль, тут і живу, починав свій шлях з PHP, і правда, сьогодні мій основний фокус на двох мовах програмування – це TypeScript і Scala.

Отож, коли ми говоримо про побудову сторонньої бібліотеки, ми будемо розглядати це з двох сторін. Зі сторони розробника, який будує бібліотеку, і зі сторони розробника, який використовує бібліотеку. Обидві сторони мають спільні і відмінні риси. Давайте розпочнемо з того, що хоче той, хто буде використовувати бібліотеку. Той, хто хоче використовувати бібліотеку, він не хоче писати багато коду, зрозуміло, тому що якщо б я хотів писати багато коду, я пішов би і просто побудував би самостійно. Він не хоче, щоб бібліотека, яка буде інтегруватися, зашкодила його аплікації. Що я маю на увазі? Я маю на увазі, що якщо, наприклад, бібліотека down, щось сталося, я хочу, щоб моя аплікація працювала і ніякої шкоди не було. Мінімально читати документацію, хто любить читати доки. Дизайнери, якщо ми говоримо про front-end інтеграцію, дизайнери повинні бути, звісно ж, задоволені. Я не хочу аджастити, писати багато CSS, щось інше. Я хочу, щоб мої дизайнери насолодилися бібліотекою. Я, звісно ж, хочу, щоб вона працювала в моєму фреймворку, і вони повинні бути швидкими. Ніхто не хоче ділей в сьогодні. Всі хочуть, щоб аплікації працювали швидко. Що ж хоче той, хто будує? Він також не любить писати багато коду.

Розробники взагалі ліниві, ми не любимо писати багато. Ми не хочемо, щоб ті, хто використовує якусь комплейну, постійно скаржився на баги. Ми не хочемо, щоб у нас були баги. Ми не хочемо писати специфічні фічі під клієнтів, тобто ми не хочемо якихось фічер-флагів для спеціальних клієнтів або іфів у коді, типу, якщо це клієнт A, то кнопка тут повинна бути червоного кольору. Ми також хочемо писати з улюбленим фреймворком, тому що всі ми любимо щось, у всіх нас є свій улюблений фреймворк, і ми хочемо залишатися в ньому і продовжувати писати там.

Ми також хочемо, щоб наша бібліотека працювала абсолютно скрізь, тобто, як я вже сказав, в усіх браузерах, у всіх фреймворках, і, більше того, можливо, навіть на всіх пристроях, тобто не тільки на десктопі, можливо, також і на планшетах, і на мобільних пристроях. Про це ми поговоримо сьогодні трошки з Годом. І іноді в бізнесі, коли ми маємо справу з реквайерментами, є ситуації, коли нам потрібно деплоїти якісь hotfixes. Наприклад, якщо ми працюємо як банкінг as a service, і іноді виникають регуляторні зміни, ми хочемо, щоб ці зміни могли відобразитися без необхідності втручання наших клієнтів.

Тож, давайте поговоримо про те, які опції у нас є для побудови, тобто який інтерфейс ми запропонуємо для тих, хто хоче використовувати. Тож, ми можемо будувати для React, Angular, Vue, Ember, будь-якої бібліотеки. Але це не дуже добре. Не дуже добре, по-перше, тому що, як ви всі знаєте, JavaScript змінюється щодня, постійно з'являються нові фреймворки, і ми просто не встигаємо за ними. Ми не хочемо адаптувати для кожної бібліотеки, і у бізнесу не завжди є кошти на це, оскільки це вимагає команди для кожної бібліотеки.

Ми могли б використовувати iFrames, але з iFrames є проблеми. Я буквально вчора обговорював із ChatGPT, чому iFrames – це не найкращий варіант. ChatGPT зауважив, що, по-перше, iFrames дуже ефективні з точки зору безпеки. По-друге, iFrames не дуже добре справляються із responsiveness, тобто, якщо вам потрібно написати якийсь media query, то вам доведеться ламати голову, як зробити це нормально, щоб воно працювало у iFrames, і що робити, якщо бібліотеки не дуже responsive.

Наприклад, ми можемо використовувати класичний підхід з exposing functions. У нас є глобальний об'єкт, названий ObjectUnit, і ми можемо використовувати константу, наприклад, unit, яка дорівнює new unit, і потім unit.render, unit і так далі. Але і тут є проблема. Якщо користувач не дуже досвідчений і не розуміє асинхронності у JavaScript, та того, що бібліотека може завантажитися трошки пізніше, ніж використовується код, то він може використовувати функцію, яка ще не існує, і це може створити проблеми та головний біль у його аплікації.

Чи є у нас ідеальний інтерфейс? Немає нічого ідеального в світі, але є ще один інтерфейс, про який ми сьогодні поговоримо, і цей інтерфейс називається WebComponents. Тож WebComponents – це набір різних технологій, які дозволяють створювати елементи для багаторазового використання з інкапсульованою функціональністю, відокремленою від коду і використовувати їх у своїх веб-додатках. Яку проблему прийшли вирішувати WebComponents? Уявіть, що у вас є дизайн-система, і у цій дизайн-системі є, скажімо, кнопки, і ви хочете, щоб ці кнопки виглядали однаково протягом всієї вашої дизайн-системи. Якщо ви використовуєте, наприклад, мікрофронтенд і ваш мікрофронтенд написаний на різних фреймворках, але ви хочете, щоб кнопка працювала однаково скрізь, ви не хочете її переписувати. Тому WebComponents дають вам таку можливість, оскільки вони працюють скрізь. Тож, як я сказав, WebComponents – це набір технологій. Ми сьогодні поговоримо про три основні технології, які є у WebComponents. Це кастомні елементи, Shadow DOM і слоти.

Розпочнемо ми з кастомних елементів. Так от, кастомні елементи – це спосіб створення своїх власних HTML-елементів. Коли я дізнався про це, вау, це просто ламає голову, тому що створити свої HTML-елементи - хто не хотів би цього робити? Тож створити це дуже просто. Ви пишете клас, який називаєте як завгодно. Він повинен екстендувати HTML-елемент. У цьому класі є три основні колбеки, як у старому React, Lifecycle. Ми знаємо, коли компонента замаунтувалася на сторінку, ми знаємо, коли компонента покинула сторінку, і ми знаємо, коли у компоненті відбулись зміни, коли один із атрибутів компоненти або багато з атрибутів компоненти змінилися. Потім ми можемо використовувати Window Custom Element, щоб задефайнити новий елемент, надавши йому ім'я тегу і пов'язавши його з класом, який ми щойно створили. Потім у HTML ви можете його використовувати просто, написавши Hello World, назву нашого компоненту, тобто назву нашого HTML-тегу, і це покаже вам Hello World з H1 на вашій сторінці.

Поговоримо трошки про Shadow DOM. Shadow DOM – це набір API для прикріплення інкапсульованого тіньового дерева DOM до елемента, який відображається окремо від DOM основного документу і має повністю свою інкапсуляцію. Таким чином ви можете зберегти повністю інкапсульований функціонал елемента, тож він не може ніяк впливати на основний DOM, і основний DOM не може ніяк впливати на нього. Shadow DOM допомагає уникнути такої ситуації, яку називають DOM Pollution. Уявіть, що ви написали якийсь клас, дали йому назву DebitCard і задали йому ширину, висоту і фоновий колір синій. Кльово, у вас є квадратик, і у цьому квадратику є фоновий колір. Що робити, якщо приходить якийсь зовнішній LCSS? І він також використовує той самий DebitCard і його фон тепер інший. Усі ми, звісно, знаємо, що буде відбуватися на сторінці, залежить від того, де ми розташували нашу бібліотеку, чи буде вона знизу, чи буде збоку, чи буде зверху. Але чи хочемо ми, щоб зовнішня бібліотека змінила колір? Може так, може ні, ми не знаємо.

Остання частина - це слоти. Slоти - це спосіб взаємодії між батьківським та дочірнім елементами веб-компонента. Тобто, вони дозволяють передавати вміст від батьківського елемента до дочірнього, надаючи можливість гнучкого використання компонентів та їхнього вмісту. Загалом, WebComponents вирішують проблеми повторного використання, інкапсуляції та інтеракції між компонентами, забезпечуючи єдиний інтерфейс для створення власних елементів, які працюють в усіх сучасних браузерах.

Є різні вирішення цієї ситуації. У моїй ситуації це змінило колір мого діву. Можна використовувати PEM, різні методи назви дівів, але ніхто не хоче з цим заморочуватись. Ми хочемо, щоб просто ми писали класи, вони були повністю інкапсульовані, і Shadow DOM допомагає нам вирішувати це питання. Поговоримо трохи про слоти, це третя key fighter. Слоти – це звичайні компоненти, але є з ними кльова штука, яку можна робити. Тож, як я вже сказав, Shadow DOM – він доступний з основного дому, але що робити, якщо ми динамічно хочемо змінити якийсь контент у Shadow DOM?

Отож, слот виступає як плейсхолдер. Ви можете користуватися ним, ви можете надати спену, який, наприклад, живе окремо від Shadow DOM, слот, надати йому ім'я, підключити його з компонентою слот, який у вас живе у вашому Shadow DOM, і коли щось зарендериться у цей спенд, воно автоматично перейде у цей слот. Це ваш спосіб комунікації з Shadow DOM, з основного дому. Окей, давайте розберемося, чому ми будемо використовувати веб-компоненти. Вони мають фреймворк-агностичність, вони працюють у всіх фреймворках, вони працюють у всіх браузерах, вони декларативні, що ми любимо, інкапсуляція, і вони фейлсейф.

Якщо ви викликаєте якийсь HTML-елемент, який не існує на сторінці, він не викликає ніяких помилок, просто не зарендерився і все. Круто. Окей, давайте поговоримо про фреймворки, всі сьогодні пишуться фреймворками. Я особисто не фанат фреймворків, я думаю, що багато чого можна зробити просто з JS, але не хочемо ми створювати велосипед кожного разу. Тож у вебкомпонентах є свої фреймворки, це літа-стенсії, вони кльові, ми перевірили їх, робили тести. Проблема з ними – це ком'юніті. Як ви бачите, ком'юніті не досить великі порівняно з React'ом, який ми всі любимо, React' просто топчик у порівнянні з ними. І добре використовувати React у вебкомпонентах.

Тож React і вебкомпоненти – це з офіційної документації React'а, створені для вирішення різних проблем. Вебкомпоненти забезпечують надійну інкапсуляцію, повторне використання компонентів, тоді як React' надає декларативну бібліотеку, яка підтримує синхронізацію DOM з вашими даними. Дві цілі доповнюють одна одну. Як розробник ви можете використовувати React у своїх вебкомпонентах або використовувати вебкомпоненти в React. Давайте подивимось, як можна рендерити React у вебкомпонентах. Тож ми маємо клас, з яким ми реально сьогодні працюємо, називаємо його UnitElementsCard, цей клас отримує два філди, IDCard – кастомер токін, токін для того, щоб згодом комунікувати з API, і у час, коли ми маємо connected callback, ми отримуємо атрибути з нашого тегу, ми створюємо mountPoint і ми прикріплюємо Shadow DOM до mountPoint. Згодом, використовуючи API React'18, ми створюємо React.Root і рендеримо React у наших вебкомпонентах. Згодом ми визначаємо, якщо воно не було визначено до цього, і ми отримуємо вебкомпоненти, які рендерять React всередині себе. Отож, у нас є якась архітектура, яку ви бачите зліва, ми бачимо вебкомпоненти, всередині вебкомпонента є застосунок React, і React каже, що UI – User Interface – це функція від нашого стану.

Круто, але у реальному житті ми не хочемо працювати лише з однією компонентою. Ми хочемо, щоб компоненти якось комунікували одна з одною, а також з основною аплікацією. Як це зробити? Ми для цього використовували кастомні івенти. Отож API браузера надає вам можливість створювати власні івенти, і вони будуть працювати точно, як працює OnClick, OnMouseMove, або будь-який інший. API для цього дуже простий. Ви створюєте новий кастомний івент, надаєте йому назву івенту, і також можете використовувати details, де передаєте об'єкт у цьому івенті. Отож, ви бачите на своїх екранах приклад того, як ми використовуємо, наприклад, івент, для того, щоб сказати нашій компоненті, що щось там змінилося, і давай ти перерендериш себе і зробиш API-реквест заново. Ми можемо створювати івенти, бо всі хочуть знати, коли компоненти зарендерились на сторінку, і ми диспетчеризуємо івент, що компонент вже на сторінці.

Як приклад, у details ми передаємо promise, який має payload нашого API, нашої карти. Ми можемо мати івент-лісенери на якісь асинхронні дії. Наприклад, якщо користувач захоче, не знаю, у картки є властивість "freeze", тобто заморозити, і ми хочемо, щоб сніг пішов на нашу сторінку, ми можемо це зробити за допомогою івенту. Коли ми отримуємо promise з результатом, ми можемо вивести його через console.log.data і також змінити сніг на своїй сторінці. Тож досить мене. Тут прийшов розробник, який хоче використовувати, і каже: "Я хочу побачити демо, я хочу побачити, як це працює, давайте подивимось." Окей, я відкриваю сторінку аплікації, видуману, звісно ж таки, аплікацію одного з наших клієнтів. Отож, те, що ми бачимо на цій сторінці з сайдбаром і заголовком, це те, що побудував клієнт. Те, що ми бачимо стосовно фінансів тут, тобто рахунок, активність і картки, це те, що юніт надав, це наші вебкомпоненти, які усередині зарендерили React. Тобто, що ми можемо робити? Наприклад, ми можемо подивитися деталі цієї картки.

Так, я не сказав, усе це, звісно ж таки, підключено до реальних API. У нашому sandbox це не продаж, тому це не реальна картка. Ви не можете зараз купити дані і придбати щось на Amazon. Але ви можете побачити, що це працює. Ми можемо зробити якусь менюшку, ми можемо заморозити картку, і ви бачите, що її стан змінився, ми можемо її розморозити, і ви бачите, що стан змінився. Ми також можемо змінювати аккаунти і динамічно бачити, що компонент "Activity" також змінився. Давайте спробуємо передати гроші з одного аккаунту в інший і побачимо, що компонент "передачі грошей" також оновлює компонент "Activity". Давайте спробуємо передати 100 доларів з одного аккаунту в інший аккаунт, і ми побачили, що щойно сталася зміна.

Джулія Вількерсон відправила 100 доларів з одного свого аккаунту в інший свій аккаунт. Я хочу трошки показати вам кастомізацію, тому що ми говорили, що дизайнери повинні бути задоволені. Ми працюємо з Storybook. Storybook – це фреймворк, який ми розробляємо, і це також фреймворк, з яким ми можемо взаємодіяти з дизайнерами, і вони можуть рев'ювати нас, бачити, які зміни ми вносимо, а також робити кастомізації. Це також фреймворк, який використовується нашими клієнтами для зміни вигляду наших компонентів. Ми, звісно, працюємо в майбутньому над тим, щоб зробити нормальний UI, але наразі ми використовуємо Storybook. Тож давайте відкриємо який-небудь компонент, наприклад, аккаунт, який виглядає ось так, от сумно, і спробуємо змінити йому декілька кольорів.

Отож, ви бачите, що якщо я зміню тут колір, давайте змінимо декілька якихось кольорів, я думаю, що цього буде достатньо. Ми побачимо, що і тут кольори змінилися, є у нас "Account Details", і є "Account Statement". Як це працює? Отож, ми маємо об'єкт "Team", який можна побачити тут у форматі JSON, і коли ви завершуєте кастомізацію теми під вашу компоненту, під ваш бренд, ви просто передаєте його нам через API, воно конектиться, і воно працює. Про те, як ми зробили Team, цікаво, але я розповім про це трошки пізніше. Тож давайте повернемося до презентації і порозмовляємо трошки про кастомізацію. Отож, як ви бачили, картка відкриває меню і флоу. Меню вона відкриває у поп-апі, а флоу вона відкриває у модалі. Але що, якщо наш дизайнер каже: "Я не хочу, щоб воно було у модалі? Я хочу, щоб воно відкривалося у правій стороні мого екрану." Чи можна це зробити?

Можна. І це дуже просто. Ми бачимо, як ми працюємо з нашою компонентою. Отож, ми викликаємо Unit Elements Card. Перед цим нам потрібно завантажити наш скрипт, який завантажується синхронно. У Unit Elements Card ми надаємо Flow Placeholder. Flow Placeholder – це ID елемента, до якого ми хочемо, щоб зарендерився наш флоу. У нас є така ж можливість для меню і для всього іншого, що рендериться у компонентах. Ми надаємо Customer Token, і це дозволяє нам побачити Placeholder у такому вигляді. Що ще ми можемо зробити? Можливо, система, коли ми хочемо, щоб кнопки були не в меню. Ми не хочемо бачити меню, ми хочемо, щоб кнопки були повністю зовнішні, щоб вони краще працювали для мобільних пристроїв. Чи можемо зробити це?

Можемо. І це досить просто. Отож, ми створюємо кнопку, яку ми називаємо Freeze Button і надаємо їй ID. Ми слухаємо клік цієї кнопки. У момент кліку ми можемо вибрати нашу картку за допомогою квері-селектора. Квері-селектор працює так само, як і звичайний HTML елемент. Ми диспетчеризуємо Custom Event у нашу картку, якому ми говоримо: "Картка, будь ласка, виклич у себе Rendering Action Freeze." І це все відбувається. Картка відразу викликає Rendering Freeze, і ви бачите на екранах, що модель працює.

Account Component, який я вам показував, досить цікавий, оскільки в ньому є функціональність, яку багато з наших клієнтів хочуть отримати. Ви викликаєте Unit Elements Account, даєте йому ID аккаунту і Customer Token, і воно працює. Але в Unit Elements Account є цікавий компонент всередині, який називається Account Statement. Це такий календарик, який дає змогу дізнатися, з якого проміжку часу ваш аккаунт існує, з якого проміжку часу він був створений. Ви можете завантажити Statement, який містить усі транзакції, що відбулися з аккаунтом протягом цього місяця. Але що, якщо я хочу Account Statement без компонента Account? Просто я хочу це. Бо в мене немає сили створювати календар, немає сили дізнаватися, коли аккаунт був створений і гратися з API. Чи можу я це зробити? Можу, і це дуже просто. Я викликаю компонент Unit Elements – Account, даю йому також ID аккаунту і Customer Token, і воно працює.

Отже, я хочу сказати вам річ, яку ми використовували у своїй архітектурі. Кожен View, кожен раз, коли ми відкриваємо щось нове, новий поп-ап, новий екран – це новий React-компонент, новий веб-компонент, який рендерить React-компонент. Кожен View – це компонент. Тобто бібліотека стала абсолютно модульною. Ви можете використовувати все, або ви можете використовувати лише частину. І інтерфейси дуже прості. Ви надаєте йому ID аккаунту і Customer Token, і воно працює. Воно знає, як взаємодіяти з API, і воно робить це швидко. Про це ми також поговоримо трошки пізніше. Як це працює, як ми вирішили проблему комунікації? Тож ми створили EventBus. EventBus – це під-паттерн патерна sub-publish. Щоб бути впевненим, що React-компонент, оскільки у нас є багато React-компонентів, якщо ми будемо просто слухати івенти, які до нас приходять, ми завжди мусимо всередині дізнаватися, чи івент, який до мене прийшов, стосується картки або це стосується аккаунту. Ми не хотіли писати таких if-else конструкцій. Тобто, щоб дізнатися, що івент, який до мене прийшов, завжди був мій івент, ми використовуємо EventBus. Отож, коли веб-компонент отримує який-небудь івент, коли ми диспетчеризуємо веб-компонент, він робить публікацію EventBus.

І компонент React підписується на цей івент і завжди всередині знає, що те, що до мене прийшло, це саме моє, це саме мій івент, і я повинен зараз його обробляти, і я повинен зараз з ним працювати. Таким чином, у EventBus є дві функції – це Publish і Subscribe. Publish отримує дані і публікує подію. А Subscribe відслідковує її. Усередині проєкту ми не використовуємо новий власний івент; ми використовуємо лише EventBus. Нам заборонено робити це, і ми завжди працюємо з API EventBus. Добре, тепер найцікавіше. Чи можемо щось зробити для мобільних пристроїв? З самого початку ми знали, що те, що ми хочемо будувати, повинно бути круто для роботи на вебі, але також повинно працювати на мобільних пристроях. Під мобільними я маю на увазі мобільні нативні застосунки, написані на React Native, Flutter, для iOS, Android, Kotlin, або будь-що інше. Добре, давайте говорити про доступи до мобільних пристроїв.

Отже, ми знаємо, що мобільні пристрої можуть використовувати WebView. Не плутайте це з веб-браузером. WebView - це можливість рендерити щось з вебу, HTML, у вигляді, як якщо це нативне, як якщо це побудовано в нативі. Круто. Які нативні речі ми хочемо використовувати? Ми хочемо використовувати нативний Bottom Sheet, хочемо, щоб це були нативні анімації, і, крім того, на мобільних пристроях, я не знаю, чи ви це бачили, але зазвичай, замість того, щоб завантажувати щось, ми хочемо розповсюджувати це. Ми хочемо використовувати цей попап, який може розповсюджувати речі. Чи можемо ми це зробити?

Отже, ми можемо взяти нашу компоненту і рендерити її в WebView. Давайте подивимося, як це буде виглядати. У нас є додаток. У додатку є деякі компоненти, є якась наша картка, яка знаходиться всередині. І наша картка, як ви бачили, призводить до відкриття Bottom Sheet у WebView на мобільному. Щоб це відбулося, коли ми натискатимемо, ми просто викликаємо певну подію. Наша нативна аплікація отримає цю подію, рендеритиме і викличе Bottom Sheet. У цьому Bottom Sheet вона рендерить інший WebView, і коли подія приходить у цей WebView, він рендерить щось. Виглядає круто, виглядає так, як це неможливо, або що за несемітницю ти говориш зараз. Давайте подивимося, чи я можу спробувати це. У мене є невеличке відео, яке я буду зараз коментувати, і в якому я буду намагатися це випробувати. Коли ми клікаємо кнопку тут, ми бачимо, що я просто логую всі події, які відбуваються. Ми бачимо, що відбулася подія під назвою "Unit Request Rendering".

У цьому івенті є пейлот, який зараз я копіюю, і відкриваю інший браузер, який називається Firefox. Тут я створюю дату за допомогою VAR - це пейлот івенту, який я скопіював. Зараз я створюю новий івент, і це новий кастом івент. Ви можете побачити з API, як це створюється. У цьому івенті я надаю йому ім'я, яке я там отримав - "Unit Request Rendering", і я додаю пейлот, який я отримав, і який я скопіював щойно. Окей, пейлот - це дата. Я натискую Enter, і одразу ж роблю window.dispatchEvent, і я диспетчую цей івент. І що ми бачимо зараз? Ми бачимо меню, яке зарендерилося у веб. Отож, подумайте про те, що UI ми пишемо одноразово, і ми пишемо його тільки для вебу. Не тільки для вебу, а для усіх, для всіх, для всіх наших платформ. Задача нативних платформ - ми пишемо три такі бібліотеки: є бібліотека для React Native, є бібліотека для iOS, і бібліотека для Android. Задача цих платформ - це просто скопіювати івент, який прийшов з однієї WebView, і диспетчувати його на іншу WebView. Ми тут у івенті кажемо, який Native Place ми хочемо зарендерити, тобто вони дивляться, що зараз це повинно бути меню, це короткий bottom sheet, якщо це повинен бути великий bottom sheet, то це великий bottom sheet. Якщо ми хочемо викликати якийсь share, ми кажемо request share, і це викликає меню share, і ми кажемо у пейлоті, яку дату потрібно зашерити.

І я хочу зазначити, що так ми працюємо, в принципі, з усім, навіть у вебі, якщо ми працюємо, ми не рендеримо все, ми робимо request rendering і просто рендеримо. У нас немає if-else в коді, які кажуть, що якщо зараз це мобільний, то рендер так, якщо веб – то так. Вони просто знають, як комунікувати самостійно. Тож давайте поговоримо про те, як ми працюємо. Ми використовуємо Atomic Design Methodology, коли ми будуємо наші компоненти. Якщо ви дивитеся нашу структуру, це нагадує якусь біологію, у нас є атоми, молекули, організми, темплейти і сторінки, отже ми розділяємо наші компоненти.

Як ми використовуємо Team? Тож, як я вже зазначив, Team - це JSON-об'єкт, який до нас прийшов. У нас є три рівні тімінгу. У нас є Default Team - це якщо нічого немає, і це тім, який ми надаємо. Є глобальні сеттинги, тобто ви можете зробити якийсь глобальний сеттинг для усіх компонентів одразу. Є Component Setting, тобто ви можете переписати налаштування якоїсь компоненти на її рівні. Як це працює? Ми використовуємо CSS-леєри для того. Ми отримуємо JavaScript-об'єкт, ми парсимо його до CSS variables. Коли ми його запарсили, ми розподіляємо його на леєри, і у леєрів є ієрархія, і відповідно до того, які variables у нас є, і рахуються релеєри, і так ми показуємо наші тіми. Як ми виконуємо перформанс? Тож, як ви вже бачили, у нас є багато компонентів, які самостійні, які роблять API-реквести. Ми побудували дві функції – одна GET, одна POST.

Коли ми робимо GET-реквест, ми генеруємо кеш для кію. У кію ми просто будуємо його за допомогою URL і заголовків, які ми отримуємо. Коли ми робимо POST, ми інвалідуємо наш кеш. Ми могли б використовувати React-query, звісно, для цього, але проблема з React-query полягає в тому, що вона може працювати лише на рівні однієї React-аплікації, а не на рівні декількох React-аплікацій, як у нашій системі. Загальний - про те, як ми працюємо. Отже, Storybook для розробки, Storybook для спілкування з дизайнером. Я зауважу, що коли ви будуєте бібліотеку компонентів, це досить складно комунікувати з дизайнерами, оскільки дизайнери люблять будувати повну картину. Коли потрібно будувати лише компоненти, це може бути дещо складним для них, тому нам довелося трошки навчати дизайнерів.

Ми використовуємо семантичну версію. Кожна версія - це новий файл. Тобто, якщо ви хочете працювати з новою версією, то потрібно просто підключити новий файл. Ми, як я вже зазначив, залишаємо можливість робити які-небудь hotfixes з допомогою cherry-pick до конкретної версії. Ми використовуємо Cypress для UI-тестів. Ми використовуємо Chromatic. Зараз ми хочемо повністю перейти на Chromatic для того, щоб робити скріншот-тести. Кожному PR-у у нас порівнюється скріншот, що змінилося, і дизайнерам легко побачити, чи відбулися які-небудь зміни. У нас є процес забезпечення безпеки UCI, оскільки ми є банківською установою, ми проходимо тестування на проникнення щоразу. І у нас, звісно ж, є deploy-preview для кожного PR-у. Тобто кожен pull-request можна перевірити і побачити, що змінилося, а що ні. Ми використовуємо S3 як наш хостинг для файлів. CloudFront використовується як CDN для комунікації. Немає кешу між CloudFront і браузером.

Ми просто знаємо, коли щось змінилося. Коли він повертає той самий файл. S3 і CloudFront зберігають кеш один від одного назавжди. Scala використовується, оскільки юніт побудований у Scala, і ми повинні використовувати весь наш бекенд на Scala. Scala використовується для створення API для тімів, ленгвіджів і сторонніх інтеграцій, які ми маємо. Так що, суті моєї доповіді. Коли ви будуєте клієнтську бібліотеку, думайте про те, що ви джуніор. Завжди використовуйте як найпростіші інтерфейси. Будьте якнайбільше нативними у своїх інтерфейсах. І важливо зауважити, що React - це не фреймворк для SPA. Це всього лише бібліотека, така сама, як і jQuery колись. Ви можете використовувати її, як вам завгодно. І все можливо. Потрібно багато працювати. Просто любіть те, що ви робите, і завжди думайте про найкращу архітектуру для проєктів. І дякую всім. І, в заключенні, я хочу сказати слова слави Україні і Am Yisrael Chai. Дякую. І тепер, я готовий відповісти на питання.

Sign in
Or by mail
Sign in
Or by mail
Register with email
Register with email
Forgot password?