Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Привет! Это снова команда websecret (member of dev.family). Мы продолжаем эксперимент по созданию приложения на React Native, которое будет работать как Telegram Web App.

В предыдущих сериях мы рассказали про:

  • особенности разработки веб-приложения на React Native с использованием react-native-web и моментах, в которых отходили от документации (весь код и детали процесса вы найдете в первой части);
  • причины, по которым бизнес запускает веб-приложения в мессенджерах.

Теперь перейдем к установке самого веб-приложения в Telegram-бот.

Деплой веб-приложения

Мы закончили подготовительные работы и теперь развернем наш сайт.

Для деплоя кликера используем Firebase. Есть два варианта:

  • Первый (и самый простой) – простой деплой с командной строки;
  • Второй (чуть посложнее) – деплой при коммите/мерже/PR через github actions.

Для этой статьи рассмотрим самый быстрый вариант.

Создадим проект в Firebase Console. Переходим по ссылке и нажимаем на кнопку «Create Project».

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Указываем название нашего проекта:

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Далее несколько раз нажимаем «Continue», выбираем в списке аккаунтов Default Firebase Account (если у вас есть другой, можете выбрать его) и нажимаем «Create Project».

Новый проект удачно создан:

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Теперь переходим в проект и нажимаем кнопку «Добавить веб-приложение»:

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Далее вводим название проекта:

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Галочку напротив «Also set up Firebase hosting» можно не ставить. Нажимаем кнопку «Register app», после чего появляется два варианта с инструкцией по установке firebase-tools в проект.

Мы будем использовать вариант не через npm, а через <script> тег, так как для мобильного приложения он нам не нужен. Вы можете выбрать любой удобный вариант.

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

На этом работа с Firebase Console закончена, возвращаемся к приложению.

Не рекомендуем хранить все эти ключи напрямую в html. Лучше создать .env файл и поместить их туда.

.env

VITE_FIREBASE_API_KEY= VITE_FIREBASE_AUTH_DOMAIN= VITE_FIREBASE_PROJECT_ID= VITE_FIREBASE_STORAGE_BUCKET= VITE_FIREBASE_MESSAGING_SENDER_ID= VITE_FIREBASE_APP_ID= VITE_FIREBASE_MEASUREMENT_ID=

Обратите внимание – все наши ключи начинаются со слова Vite. Мы делаем так, потому что используем Vite в качестве сборщика. И, когда получаем доступ к переменным окружения через import.meta.env, он может не распознать их без этого слова.

Дальше немного отредактируем наш index.html с учетом написанного выше.

index.html

<html> <body> ... <script type="module"> import { initializeApp } from "https://www.gstatic.com/firebasejs/10.13.0/firebase-app.js"; import { getAnalytics } from "https://www.gstatic.com/firebasejs/10.13.0/firebase-analytics.js"; const firebaseConfig = { apiKey:import.meta.env.VITE_FIREBASE_API_KEY, authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN, projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET, messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID, appId: import.meta.env.VITE_FIREBASE_APP_ID, measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID, }; const app = initializeApp(firebaseConfig); const analytics = getAnalytics(app); </script> <script src="./index.web.js" type="module"></script> </body> </html>

Открываем терминал, переходим в корень проекта и прописываем команду

firebase login

После мы попадаем в окно браузера и проходим авторизацию через Firebase Console.

firebase init

Выбираем выделенный пункт и нажимаем клавиши space, потом enter.

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Далее решаем ряд вопросов для конфигурации. Добавляем следующее:

  • Please select an option – тут мы выбираем Use an existing project. А из списка ниже – недавно созданный проект;
  • What do you want to use as your public directory? – выбираем dist (тут будет лежать наша сборка);
  • Configure as a single-page app (rewrite all urls to /index.html)? – y;
  • Set up automatic builds and deploys with GitHub? (y/N) – N (на данном этапе нам это не нужно);
  • File dist/index.html already exists. Overwrite? (y/N) – N.

Переходим в firebase.json и немного его модифицируем.

firebase.json

"hosting": { "public": "dist", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**", //past here "**/android/**", "**/ios/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } }

Добавляем в игнор при деплое директории Android и iOS. Поскольку у нас веб-приложение, не нужно отправлять на хостинг все файлы. К тому же, они достаточно много весят, и без определенного типа подписки вы не сможете их загрузить.

Приближаемся к финишу. Осталось прописать еще одну команду:

firebase deploy

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Теперь переходим по ссылке ниже. Вуаля, наше приложение уже хостится!

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Осталось только развернуть приложение в Telegram.

Установка веб-приложения в Telegram-бота

Еще раз посмотрим, что у нас есть на данный момент:

  • Рабочее приложение на iOS;
  • Рабочее приложение на Android;
  • Рабочее веб-приложение, которое уже хостится.

Остался последний рывок, и можно будет добавить приложение вмессенджер. Открываем бота в Telegram под названием BotFather и начинаем диалог. Выбираем команду /newbot

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Даем нашему боту имя. Далее будет создан API Key для взаимодействия с нашим ботом по HTTP.

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Далее пишем команду /mybots и выбираем только что созданного нами красавца. Переходим в bot settings.

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

В настройках бота выбираем пункт Configure Mini App.

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Может появится сообщение, что mini app отключены для нашего Telegram-бота. Ничего страшного – просто нажимаем на кнопку Enable Mini App.

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Теперь мы просто передаем URL, по которому хостится наше веб-приложение

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

Поработаем с кнопкой меню. Для это возвращаемся в настройки бота и выбираем Configure Menu Button. Здесь может появится уведомление, что сейчас кнопка в нерабочем состоянии и предложение включить ее. Соглашаемся и присваиваем кнопке имя.

Момент истины: проверим, как работает наш парниша в полевых условиях. Переходим в бота – @ReactNativeWebClickerBot (можете тоже его оценить, нам будет приятно ❤). Открываем – все работает!

Создаем Telegram WebApp. Часть II: установка Telegram mini-app

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

Заключение

В этом эксперименте мы детально разобрали, как можно:

  • Сделать веб-приложение на основе мобильного приложения, написанного на React Native, с использованием react-native-web;
  • Задеплоить его через Firebase;
  • Использовать его в Telegram mini app;
  • Взаимодействовать в нашей общей кодовой базе с Telegram client.

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

Почему это хорошо:

  • Ваше приложение будет работать в разных каналах и представлено в нескольких магазинах, что позволит охватить больше пользователей;
  • Скорость разработки продукта значительно увеличится – в среднем, время до релиза сокращается на 20%, а значит time-to-market момент наступит быстрее;
  • Большую часть кодовой базы можно использовать повторно, соответственно, любые апдейты и фикс багов также будет вносить проще.

Главное – помните про особенности каждой платформы и учитывайте их в разработке.

Мы специально оставили отдельные части кода недописанными, чтобы вы смогли дополнить их самостоятельно. При желании, добавьте валидацию пользователя Telegram, проверку наличия пользователя в мобильном приложении, а также настройте деплой в Firebase через GitHub Actions. Короче, экспериментируйте, чтобы получить лучший результат.

По традиции, оставляем ссылки на артефакты:

На связи была команда websecret (member of dev.family) 💜💚

1
Начать дискуссию
\n\n\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Открываем терминал, переходим в корень проекта и прописываем команду

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"firebase login","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

После мы попадаем в окно браузера и проходим авторизацию через Firebase Console.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"firebase init","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Выбираем выделенный пункт и нажимаем клавиши space, потом enter.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"ecdaa9e3-444f-51d5-8742-ab5af04eed1b","width":893,"height":366,"size":48494,"type":"png","color":"282a27","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABgj/xAAjEAACAAQGAwEAAAAAAAAAAAABAgADBBEFBhIhMZEVMkTR/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAQFA//EABsRAAMBAAMBAAAAAAAAAAAAAAABAhESEyFx/9oADAMBAAIRAxEAPwCR66mqNDPJy/RszIVOqUARta/PMIRDqs5PPoO5nwL+BxI/Mex+xU6wwW5qJTD5RQ6SZljba+xhCG/BS0uQMLvf3buKqbNcP//Z"}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Далее решаем ряд вопросов для конфигурации. Добавляем следующее:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Please select an option – тут мы выбираем Use an existing project. А из списка ниже – недавно созданный проект;","What do you want to use as your public directory? – выбираем dist (тут будет лежать наша сборка);","Configure as a single-page app (rewrite all urls to /index.html)? – y;","Set up automatic builds and deploys with GitHub? (y/N) – N (на данном этапе нам это не нужно);","File dist/index.html already exists. Overwrite? (y/N) – N."],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Переходим в firebase.json и немного его модифицируем.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

firebase.json

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"\"hosting\": {\n \"public\": \"dist\",\n \"ignore\": [\n \"firebase.json\",\n \"**/.*\",\n \"**/node_modules/**\",\n //past here\n \"**/android/**\",\n \"**/ios/**\"\n ],\n \"rewrites\": [\n {\n \"source\": \"**\",\n \"destination\": \"/index.html\"\n }\n ]\n }\n}","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Добавляем в игнор при деплое директории Android и iOS. Поскольку у нас веб-приложение, не нужно отправлять на хостинг все файлы. К тому же, они достаточно много весят, и без определенного типа подписки вы не сможете их загрузить.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Приближаемся к финишу. Осталось прописать еще одну команду:

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

firebase deploy

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"e3a1adec-8ca4-5759-93ee-24863b68f636","width":796,"height":262,"size":37085,"type":"png","color":"292e28","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABgUI/8QAIxAAAgEDAgcBAAAAAAAAAAAAAQMCABESBAUGExQiI0FUkv/EABYBAQEBAAAAAAAAAAAAAAAAAAQBA//EABoRAAIDAQEAAAAAAAAAAAAAAAABAgMRIWH/2gAMAwEAAhEDEQA/AMg7xPb5aKU07oxjZ4+MMGPq9wBQUknoadmrA2QLntpysWFU/RLxO1i16XlslHJdzibXOUqNbyXDGL2KZB6rU/Q39msyn//Z"}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Теперь переходим по ссылке ниже. Вуаля, наше приложение уже хостится!

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"4fd5cd99-05ef-53b7-94d3-a903da338795","width":1504,"height":1628,"size":116520,"type":"png","color":"f3f3fb","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQYJ/8QAIhAAAQMEAgIDAAAAAAAAAAAAAQMEBQACBhEIEhQxBxMh/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAIDBP/EAB4RAAICAgIDAAAAAAAAAAAAAAABAgMEEUFREiEi/9oADAMBAAIRAxEAPwC55d5NfG88PiWKObZDGLLWwPhxjMEs3pvlFbV/vOx10mBr8O/VTdPIjkVquKcHvye/a60uSoRqdUnJ/XC7NBK7TAHksSxWWl2s5K4zEvJJn18Z44ZJqLo9btjopcDdbokkaPugGKA//9k="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Осталось только развернуть приложение в Telegram.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Установка веб-приложения в Telegram-бота"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Еще раз посмотрим, что у нас есть на данный момент:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Рабочее приложение на iOS;","Рабочее приложение на Android;","Рабочее веб-приложение, которое уже хостится."],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Остался последний рывок, и можно будет добавить приложение вмессенджер. Открываем бота в Telegram под названием BotFather и начинаем диалог. Выбираем команду /newbot

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"589f473a-a4e5-5fac-9d6f-0347e3c63190","width":909,"height":811,"size":80967,"type":"png","color":"f1f1f9","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABgn/xAAiEAAABgICAgMAAAAAAAAAAAABAgMFBhEABAcSCBMhUXH/xAAXAQEBAQEAAAAAAAAAAAAAAAABAwIE/8QAHREAAgIBBQAAAAAAAAAAAAAAAAECEQMSIjFxkf/aAAwDAQACEQMRAD8ARc4c7cvx7zmbIGz8gvGpG1ZA0ap21JakDJqenuUS/Ruw3+5SS38m45pRhppV0r9qyjeXOcIOUBgrhJySHfhbDsupVU1S7yzcifYA5a6mBQS9rCgob+KwpC2xfiB//9k="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Даем нашему боту имя. Далее будет создан API Key для взаимодействия с нашим ботом по HTTP.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"de87ed6c-75b6-5b09-8898-2cc7673192ee","width":854,"height":761,"size":274264,"type":"png","color":"373737","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABAcI/8QAIxAAAAUDBAMBAAAAAAAAAAAAAQIDBAUABxEGCBIhExQxUf/EABcBAQEBAQAAAAAAAAAAAAAAAAAEAgP/xAAbEQACAgMBAAAAAAAAAAAAAAAAAQIDERJBIf/aAAwDAQACEQMRAD8Aq1y9xtwdP7u0bZs9XyqMKabYNjMUkCiQxFCpiJeQlHADy77/AHutzlPdJPw6VupQe6y+G56oJgSkLDKvPfViWR3OQHzGQIKmQ+DyxmnBkbQH/9k="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Далее пишем команду /mybots и выбираем только что созданного нами красавца. Переходим в bot settings.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"a88ea178-abbc-5371-a461-2f934e4f7a4e","width":854,"height":603,"size":216308,"type":"png","color":"464646","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAwQHCP/EACUQAAICAQIFBQEAAAAAAAAAAAECAwQFAAYHERIxUQgTIXGBkf/EABcBAQEBAQAAAAAAAAAAAAAAAAABAwT/xAAaEQADAAMBAAAAAAAAAAAAAAAAAQIREjFx/9oADAMBAAIRAxEAPwCl8afVVxP2Rx2zOz6+9lq4KhfWMV4scrSIvtgheoqxbmT4H2O+rV3s54ixrOKaz6bh2/dsZHA43IWl6ZrVSGaRfDMgJH9OulGLCzYnFTzmxNjKkkp7u0Klj+kc9UDgAUBVAAHwANAf/9k="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В настройках бота выбираем пункт Configure Mini App.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"7dae4708-ced4-5b1c-9bde-9520104f5e7b","width":788,"height":531,"size":145459,"type":"png","color":"454545","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAwQGCP/EACQQAAEDAgYCAwAAAAAAAAAAAAECAwQABQYHCBESEzFBQlGB/8QAFwEBAAMAAAAAAAAAAAAAAAAAAAIDBP/EABoRAQEAAgMAAAAAAAAAAAAAAAACAQQRITH/2gAMAwEAAhEDEQA/ALvMLUBqEt+dV2w5acbSoVli4kENtsw4/WI3eElHNSCQOPy9VCtyJvM8mI68b/ZUVsoWTuVJB3/K3KgHLbbnXC47b4y1E7kqaSST9+KBrxQf/9k="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Может появится сообщение, что mini app отключены для нашего Telegram-бота. Ничего страшного – просто нажимаем на кнопку Enable Mini App.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"4d7d1482-2858-556e-a857-bb137897597b","width":854,"height":333,"size":99645,"type":"png","color":"414141","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAUHCP/EACMQAAIBAwMEAwAAAAAAAAAAAAECBAADCAYHEhExUpEFIXH/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQMC/8QAGhEBAQACAwAAAAAAAAAAAAAAAAISUQERQf/aAAwDAQACEQMRAD8AoNzLLNFYtySNpI6FOyvp6cWb8ANVzvRcTPplGy5yaMe0ZW3UlbxRTcC6O+QKhun2AeXbrRnei6luniviPVWYHFfEeqA//9k="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Теперь мы просто передаем URL, по которому хостится наше веб-приложение

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"02552f04-8c07-5d9e-8d65-a73069230444","width":854,"height":453,"size":66006,"type":"png","color":"3a3a3a","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAYHCP/EACIQAAEDBAICAwAAAAAAAAAAAAECAwQABQYRCCETIjJBUf/EABcBAAMBAAAAAAAAAAAAAAAAAAABBAL/xAAaEQEAAwEBAQAAAAAAAAAAAAABAAIDESFx/9oADAMBAAIRAxEAPwBrmcsOXUK/KjJtT0phqVtTLeIydrZC/iFePrY639U3TUfKyimGFqjbQH4zZGK5Rn1xxez3C7sIbnSoEd6UgRVJCXVNpKxogEexPVUj06ySwCgylaH4KczCiE//2Q=="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Поработаем с кнопкой меню. Для это возвращаемся в настройки бота и выбираем Configure Menu Button. Здесь может появится уведомление, что сейчас кнопка в нерабочем состоянии и предложение включить ее. Соглашаемся и присваиваем кнопке имя.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Момент истины: проверим, как работает наш парниша в полевых условиях. Переходим в бота – @ReactNativeWebClickerBot (можете тоже его оценить, нам будет приятно ❤). Открываем – все работает!

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"cf43e6d6-d758-5adf-89ed-23281dcb2bfb","width":1032,"height":888,"size":76854,"type":"png","color":"262626","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQcI/8QAIxAAAAUDBAMBAAAAAAAAAAAAAQIDBAUABhEHCBIhEyJCkf/EABgBAAMBAQAAAAAAAAAAAAAAAAABAwQF/8QAHxEAAQQCAgMAAAAAAAAAAAAAAAECAxEEMRIhQVHx/9oADAMBAAIRAxEAPwCoboNZL9tLddC2jD6uTMCwOECKMG2R5ISAruxIuBz/AB6fuMVLInyGZMccbLYt8lvXrrzZWKKN0TnuXtNJW/hu2ugZQiRtG05aTSmJS2Il4/R4+N04ZJKLE4jkuDmKJgwPYd9UgtRemB//2Q=="}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

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

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Заключение"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В этом эксперименте мы детально разобрали, как можно:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Сделать веб-приложение на основе мобильного приложения, написанного на React Native, с использованием react-native-web;","Задеплоить его через Firebase;","Использовать его в Telegram mini app;","Взаимодействовать в нашей общей кодовой базе с Telegram client."],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

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

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Почему это хорошо:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Ваше приложение будет работать в разных каналах и представлено в нескольких магазинах, что позволит охватить больше пользователей;","Скорость разработки продукта значительно увеличится – в среднем, время до релиза сокращается на 20%, а значит time-to-market момент наступит быстрее;","Большую часть кодовой базы можно использовать повторно, соответственно, любые апдейты и фикс багов также будет вносить проще."],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Главное – помните про особенности каждой платформы и учитывайте их в разработке.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Мы специально оставили отдельные части кода недописанными, чтобы вы смогли дополнить их самостоятельно. При желании, добавьте валидацию пользователя Telegram, проверку наличия пользователя в мобильном приложении, а также настройте деплой в Firebase через GitHub Actions. Короче, экспериментируйте, чтобы получить лучший результат.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

По традиции, оставляем ссылки на артефакты:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Документация React Native Web","Документация Telegram mini-app","Ссылка на Firebase","Весь код в Github","Сам @ReactNativeWebClickerBot"],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

На связи была команда websecret (member of dev.family) 💜💚

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":0,"favorites":0,"reposts":0,"views":930,"hits":1036,"reads":null,"online":0},"dateFavorite":0,"hitsCount":1036,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/dev/1587470-sozdaem-telegram-webapp-chast-ii-ustanovka-telegram-mini-app","author":{"id":166568,"name":"Max Bantsevich","nickname":null,"description":"СЕО студии разработки dev.family – фокусируемся на фудтехе и личных кабинетах для b2b","uri":"","avatar":{"type":"image","data":{"uuid":"cf5e7a50-9a30-534e-960c-ee61efbe8071","width":3268,"height":4896,"size":1136914,"type":"jpg","color":"686a69","hash":"7ff5d997276ba08d","external_service":[]}},"cover":{"cover":{"type":"image","data":{"uuid":"e0510af4-38c7-5926-93b1-7af47d6bd500","width":3607,"height":1104,"size":163693,"type":"png","color":"442c93","hash":"","external_service":[]}},"cover_y":0},"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":5255453,"userId":166568,"count":0,"shareImage":"https://api.vc.ru/achievements/share/5255453"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1631366,"userId":166568,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1631366"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":404658,"userId":166568,"count":0,"shareImage":"https://api.vc.ru/achievements/share/404658"}],"lastModificationDate":1764963396,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":true,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":235819,"name":"Разработка","description":"Сообщество разработчиков: публикации о личном опыте, выдающиеся приёмы при решении рутинных задач, полезные материалы для профессионального роста.","uri":"/dev","avatar":{"type":"image","data":{"uuid":"fef5b5fb-e488-5b7f-8445-e3a26a910b44","width":1200,"height":1200,"size":7757,"type":"png","color":"343434","hash":"04042b2b1c1000","external_service":[]}},"cover":{"type":"image","data":{"uuid":"2a214cc5-35cc-58ca-bc07-fc1c892d2101","width":960,"height":280,"size":177,"type":"png","color":"343434","hash":"","external_service":[]}},"lastModificationDate":1642411346,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"dev","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":1}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null,"keywords":[],"media":{"type":"image","data":{"uuid":"4cae2506-0141-5c72-9da5-15e1a89bcc9c","width":1272,"height":699,"size":59451,"type":"png","color":"1c2c44","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABQj/xAAdEAACAgMAAwAAAAAAAAAAAAABAgMFAAQhEVFx/8QAGAEAAgMAAAAAAAAAAAAAAAAAAgMBBQb/xAAaEQADAQADAAAAAAAAAAAAAAAAAQIRAxIx/9oADAMBAAIRAxEAPwCJ9+sMDKYAXDAvxwx8fFHM1bhoo9QfgEiFVaWddLPJX2O1rPKhWRoZmQuPRIPRjOO6nerwFyq9D8WEf//Z"}},"customCover":null,"robotsTag":"noindex","categories":[10],"isAnonymized":true}};