Сделать приложение в браузере
Работающий стартап, это тот, который построенный на принципах стратегии MVP (Minimum Viable Product). Такой подход позволяет вам проверить ваш продукт перед запуском его в широкие массы.
После запуска MVP изучаете реакцию вашей аудитории и рынка на него, меряете покупательских спрос. Как результат, вы получаете первые плоды от продаж, первый пользовательский опыт, первый отзыв о продукте / сервисе. У вас вырисовывается полное представление о проекте, и о том, что с ним дальше делать: в каком направлении развиваться и развиваться ли вообще.
Ниже мы детально рассмотрим как механизм MVP может помочь в сборе информации и превращении ее в ценностное предложение. И помните, что как стратегический предприниматель, лучше выбирать такой способ разработки продукта, который покажет результаты в первые дни работы. Пссс… правильный ответ — веб-приложение;)
Запуская технический продукт, который не имеет никакой взаимосвязи с камерой или микрофоном смартфона, подумайте о том, чтобы начать все-таки с веб-приложения. Функционально браузеры быстрее развиваются чем мобильные приложения, и соответственно количество пользователей у них больше. При создании приложения лучше задействовать принципы MVP. Также не забывайте, что оно должно запускаться в Chrome или Safari.
Приложения подобные Uber или Instagram напрямую зависят от функциональности девайса (геолокация), но есть много других продуктов, которые не нуждаются в взаимодействии с API устройства. А благодаря адаптивному веб-дизайну такие приложения получают межплатформенную доступность и корректно отображаются на экранах разного разрешения.
Существует десятки технических методов разработки мобильных приложений. Различия между ними сводятся к скорости написания приложения, стоимости, и к качеству конечного продукта. Понимание различий между ними, пожалуй, сложная задача.
Итак, давайте рассмотрим четыре популярные технологии создания мобильных приложений, а также их основные различия. Это поможет определить практичный способ верификации бизнес-идеи и облегчит конструирование будущего продукта. Возможно, веб-приложение (а не нативное мобильное приложение) поможет сократить расстояние между MVP и запуском полноценного проекта.
Эта относительно новая технология, разработанная Google. Она позволяет мобильным устройствам добавлять веб-сайт или веб-приложение на домашний экран смартфона и дальше использовать его в оффлайн-режиме.
Для превращения веб-приложения в прогрессивное веб-приложение, вам нужно добавить в него значок для главного экрана, манифест веб-приложения и рабочие службы — все это позволит сайту загружаться быстрее, работать в оффлайн-режиме и отправлять push-уведомления. Обратите внимание, что при загрузке прогрессивного веб-приложения в браузере телефона устройству предлагается добавить сайт на главный экран.Прогрессивные веб-приложения не полностью поддерживаются на устройствах iOS, но, надеюсь, это изменится в ближайшем будущем.
- Позволяет получать push-уведомления;
- Приложения могут работать в оффлайн-режиме;
- Базовые сайты получают лучшее ранжирование в поисковых системах.
- Эта технология — это просто оболочка браузера, а не полнофункциональное приложение, поэтому технически это все еще веб-сайт;
- Пользователи не получат опыт работы с нативным приложением (анимация, производительность), поскольку пользовательский интерфейс — это просто полноэкранное окно браузера без строки URL, которая может работать в автономном режиме;
- Плохая совместимость (по-прежнему недоступна на iPhone и iPad).
Washington Post одна из первых медиакомпаний, использующих прогрессивное веб-приложение для увеличения охвата веб-сайта.
Прогрессивные веб-приложения — отличный способ дополнить веб-сайт или веб-приложение, расширяя его охват. Они могут улучшить глобальный пользовательский опыт с устройствами, которые их поддерживают; однако, поскольку эта технология не распространена, ее следует рассматривать как дополнительное средство увеличение охвата веб-сайта, а не как способ трансформации веб-сайта в мобильное приложение.
Apache Cordova — это платформа для создания мобильных приложений с использованием HTML, CSS и Javascript.
Приложения, созданные с использованием Apache Cordova, работают во встроенной среде браузера (WebView) на мобильных платформах Android, iOS и загружаются из App Store или Google Play Store. Приложение запускается с помощью ярлыка, который расположен на главном экране, и взаимодействует с API-интерфейсами смартфонов, функциями девайса (геолокация, камера и т. д.).
Пользовательский интерфейс приложения, созданного с помощью этой инфраструктуры, не будет таким гладким, как в родном (native) приложении. Внешний вид интерфейса аналогичен интерфейсу веб-сайта (задержка нажатия на 300 мс, фантомные клики при прокрутке и так далее). Конечно, есть модули и фреймворки, которые предлагают компоненты пользовательского интерфейса. Модули разработанные так, чтобы быть похожими на собственные приложения, но они все еще не дотягивают до опыта взаимодействия с родным приложением.
Помимо Cordova, есть и другие популярные платформы — Ionic и PhoneGap. Для примера того, как такое приложение выглядит и работает, можно скачать приложение для Национального музея афроамериканской истории и культуры.
Это приложение было создано с использованием Ionic framework и предлагает следующие возможности:
- Поиск / исследование конкретных объектов в музее;
- Видео дополненной реальности;
- Обмен через социальные сети;
Недавним примером гибридного приложения, которое мы создали в Ezetech для Tickfinity — TicketNetwork POS для мобильных устройств (видео).
- Высокая скорость разработки;
- Написаны с помощью HTML, CSS, Javascript, что обеспечивают кросс-совместимое iOS, Android и веб-программное обеспечение (требуется только один веб-разработчик);
- Доступны фреймворки, которые эмулируют пользовательские элементы UI (например, кнопки, меню и так далее);
- UX близок к нативному опыту с использованием элементов UI, которые имитируют поведение обычного приложения;
- Доступ к API-интерфейсу смартфона ( камера, push-уведомления, геолокация и другие).
- UX не так хорош, как в родных приложениях (задержки на клики 300 мс, фантомные клики при прокрутке);
- Чем сложнее приложение, тем медленнее оно работает из-за использования различных оболочек и библиотек;
- Не работает в офлайн режиме;
- Анимации трудно реализовать в UI.
Этот вариант подходит для MVP простых веб или мобильных приложений. Если у вас уже есть веб-приложение, построенное с помощью Javascript, вы можете использовать существующий код. Проще говоря Apache Cordova хорош для быстрого создания недорогих мобильных приложений со стандартными функциями.
React — отличный выбор, если ваше веб-приложение построено с помощью React.js. Это относительно новая технология в мире гибридных приложений, и миграция из существующего веб-приложения в мобильное может пройти довольно быстро. В результате вы получаете мобильное приложение, которое использует собственные компоненты ОС вашего смартфона (кнопки, входы и другие функции устройства). Производительность хорошая, потому что исходный код конвертируется в собственное мобильное приложение, а не работает во встроенном окне браузера.
Некоторые примеры приложений, использующих React Native:
- Высокая скорость разработки для веб-приложений на основе React;
- Веб-приложение, созданное с помощью React.js, может быть легко преобразовано в мобильное приложение React Native, а некоторые исходные коды можно повторно использовать;
- Собственный пользовательский опыт;
- Приложение выглядит и воспринимается как родное мобильное приложение для конкретной платформы;
- Низкие затраты на разработку;
- Эксперты в React Native обычно могут создавать приложения для Android и iOS.
- Относительно новая технология (ограниченные решения с открытым исходным кодом);
- Ограничено в отношении визуального дизайна;
- Не подходит для сложных проектов, таких как мобильные игры или приложения, требующие высокой нагрузки (значительные вычисления).
React Native — самая популярная технология для разработки гибридных мобильных приложений. Она используется крупнейшими цифровыми корпорациями и имеет много преимуществ. Это хороший вариант, если вашему приложению не требуется поддерживать несколько соединений с сервером в реальном времени или выполнять сложные вычисления. Технология по прежнему новая, и не так много библиотек и модулей с открытым исходным кодом, как для собственных технологий разработки мобильных приложений, но она быстро развивается.
Создание родных (native) приложений для каждой платформы — лучший выбор с точки зрения производительности и качества продукции, но это также и самый дорогой подход. Если у вас уже есть веб-приложение, вам нужно будет только создать мобильные клиенты для мобильного приложения Android и iOS, которые будут подключены к тому же бэкенду, что и ваш веб-клиент. Незначительные изменения могут быть все еще необходимы на бэкенде, но это не займет много времени.
Обычно вам нужно как минимум 2 разработчика — разработчик iOS, который работает над iPhone-приложением с использованием Objective-C или Swift, и разработчика Android, который будет использовать Java или Kotlin. Поэтому стоимость разработки будет выше, чем в любом из вышеперечисленных подходов.
В то же время гибкость такого подхода заключается в том, что вы сначала можете разработать начальную версию только для одной платформы, и позже добавить другую. Первую платформу, можно определить исследуя целевую аудиторию с помощью Mapbox.
Несколько примеров нативных мобильных приложений:
Coinbase: одно из самых популярных приложений для торговли криптовалютами.
Uber: самое популярное приложение для транспортировки.
- Многие модули и библиотеки доступны для решения общих задач разработки;
- Хорошая производительность и отличный пользовательский интерфейс на всех мобильных платформах;
- Позволяет приложению получать доступ ко всем устройствам разрешенным производителем;
- Может работать в офлайн режиме и хранить данные на устройстве.
- Более высокие затраты по сравнению с разработкой гибридных приложений;
- Различные стеки технологий для разных платформ (требуется больше разработчиков).
- Обратите внимание, что лучше всего создавать нативное приложение c нуля, только если у вас есть на это ресурсы. Технологии для создания таких приложений уже давно существуют, что дает множество модульных решений, а также сообществ с открытым исходным кодом, доступных разработчикам для эффективного решения проблем.
Есть два основных варианта, которые хорошо подойдут для перехода из веб-приложения в мобильное — разработка гибридного приложения и запуск с нуля (разработка нативного приложения).Если функциональность вашего продукта не слишком сложна, и вы просто хотите предложить мобильным пользователям лучший опыт, вы должны использовать React Native (если сайт на реакте) или Apache Cordova для разработки вашего гибридного приложения. Это оптимальный вариант, если у вас ограничен бюджет и вам нужна поддержка на Android и iOS.
Для сложных приложений, которые должны выполнять сложные вычисления, поддерживать соединение в реальном времени с сервером и предлагать пользователям уникальные функции, которые требуют постоянного взаимодействия с другими приложениями, лучше использовать нативную разработку. В этом случае вы сможете создать приложение с наиболее важным функционалом и улучшать его по мере роста вашего бизнеса.
Что касается разработки прогрессивного веб-приложения, то это достаточно новая технологическая парадигма. Такое приложение хорошо подойдет для расширения охвата вашего ресурса, но до полноценного мобильного приложения ему еще далеко.
В отличие от распространенной "клиент-серверной" архитектуры, для децентрализованных приложений характерно:
- Отсутствие необходимости хранить базу данных с логинами и паролями пользователя. Информация для доступа хранится исключительно у самих пользователей, а подтверждение их достоверности происходит на уровне протокола.
- Отсутствие необходимости использовать сервер. Логика приложения может выполняться в блокчейн-сети, где возможно и хранение необходимого количества данных.
Существует 2 относительно безопасных хранилища для ключей пользователей — хардверные кошельки и браузерные расширения. Хардверные кошельки в большинстве своем максимально безопасны, однако сложны в использовании и далеко не бесплатны, а вот браузерные расширения являются идеальным сочетанием безопасности и простоты в использовании, а еще могут быть совершенно бесплатны для конечных пользователей.
Учитывая все это, мы захотели сделать максимально безопасное расширение, которое упрощает разработку децентрализованных приложений, предоставляя простой API для работы с транзакциями и подписями.
Об этом опыте мы вам и расскажем ниже.
В статье будет пошаговая инструкция как написать браузерное расширение, с примерами кода и скриншотами. Весь код вы можете найти в репозитории. Каждый коммит логически соответствует разделу данной статьи.
Краткая история браузерных расширений
Браузерные расширения существуют достаточно давно. В Internet Explorer они появились еще в 1999-м году, в Firefox — в 2004-м. Тем не менее, очень долго не было единого стандарта для расширений.
Можно сказать, что он появился вместе с расширениями в четвертой версии Google Chrome. Конечно, никакой спецификации тогда не было, но именно API Chrome стал ее основой: завоевав большую часть рынка браузеров и имея встроенный магазин приложений, Chrome фактически задал стандарт для браузерных расширений.
У Mozilla был свой стандарт, но, видя популярность расширений для Chrome, компания решила сделать совместимый API. В 2015 году по инициативе Mozilla в рамках World Wide Web Consortium (W3C) была создана специальная группа для работы над спецификациями кроссбраузерных расширений.
За основу был взят уже существующий API расширений для Сhrome. Работа велась при поддержке Microsoft (Google в разработке стандарта участвовать отказался), и в результате появился черновик спецификации.
Формально спецификацию поддерживают Edge, Firefox и Opera (заметьте, что в этом списке отсутствует Chrome). Но на самом деле стандарт во многом совместим и с Chrome, так как фактически написан на основе его расширений. Подробнее о WebExtensions API можно прочитать здесь.
Структура расширения
Единственный файл, который обязательно нужен для расширения — манифест (manifest.json). Он же является “точкой входа” в расширение.
Манифест
По спецификации файл манифеста является валидным JSON файлом. Полное описание ключей манифеста с информацией о том, какие ключи в поддерживается в каком браузере, можно посмотреть здесь.
Ключи, которых нет в спецификации, “могут” быть проигнорированы (и Chrome, и Firefox пишут об ошибках, но расширения продолжают работать).
А я бы хотел обратить внимание на некоторые моменты.
- background — объект, который включает в себя следующие поля:
- scripts — массив скриптов, которые будут выполнены в background-контексте (поговорим об этом чуть позже);
- page — вместо скриптов, которые будут выполнятся в пустой странице, можно задать html с контентом. В этом случае поле script будет проигнорировано, а скрипты нужно будет вставить в страницу с контентом;
- persistent — бинарный флаг, eсли не указан, то браузер будет "убивать" background-процесс, когда посчитает, что он ничего не делает, и перезапускать при необходимости. В противном случае страница будет выгружена только при закрытии браузера. Не поддерживается в Firefox.
- matches — паттерн url, по которому определяется, будет включаться конкретный content script или нет.
- js — список скриптов которые будут загружены в данный матч;
- exclude_matches — исключает из поля match URL, которые удовлетворяют этому полю.
- default_popup — путь до HTML файла с popup-интерфейсом, может содержать CSS и JS.
Контекст выполнения
У расширения есть три контекста исполнения кода, то есть, приложение состоит из трех частей с разным уровнем доступа к API браузера.
Extension context
Здесь доступна большая часть API. В этом контексте "живут":
- Background page — “backend” часть расширения. Файл указывается в манифесте по ключу “background”.
- Popup page — popup страница, которая появляется при нажатии на иконку расширения. В манифесте browser_action -> default_popup .
- Custom page — страница расширения, "живущая" в отдельной вкладке вида chrome-extension:///customPage.html .
Этот контекст существует независимо от окон и вкладок браузера. Background page существует в единственном экземпляре и работает всегда (исключение — event page, когда background-скрипт запускается по событию и "умирает" после его выполнения). Popup page существует, когда открыто окно popup, а Custom page — пока открыта вкладка с ней. Доступа к другим вкладкам и их содержимому из этого контекста нет.
Content script context
Файл контент-скрипта запускается вместе с каждой вкладкой браузера. У него есть доступ к части API расширения и к DOM-дереву веб-страницы. Именно контент-скрипты отвечают за взаимодействие со страницей. Расширения, манипулирующие DOM-деревом, делают это в контент-скриптах – например, блокировщики рекламы или переводчики. Также контент-скрипт может общаться со страницей через стандартный postMessage .
Web page context
Это собственно сама веб-страница. К расширению она не имеет никакого отношения и доступа туда не имеет, кроме случаев, когда в манифесте явно не указан домен этой страницы (об этом — ниже).
Сервер или background:
Также есть событие onDisconnect и метод disconnect .
Схема приложения
Давайте сделаем браузерное расширение, которое хранит приватные ключи, предоставляет доступ к публичной информации (адрес, публичный ключ общается со страницей и позволяет сторонним приложениям запросить подпись транзакций.
Разработка приложения
Наше приложение должно как взаимодействовать с пользователем, так и предоставлять странице API для вызова методов (например, для подписи транзакций). Обойтись одним лишь contentscript не получится, так как у него есть доступ только к DOM, но не к JS страницы. Подключаться через runtime.connect мы не можем, потому что API нужен на всех доменах, а в манифесте можно указывать только конкретные. В итоге схема будет выглядеть так:
Будет еще один скрипт — inpage , который мы будем инжектить в страницу. Он будет выполняться в ее контексте и предоставлять API для работы с расширением.
Начало
Весь код браузерного расширения доступен на GitHub. В процессе описания будут ссылки на коммиты.
Начнем с манифеста:
Создаем пустые background.js, popup.js, inpage.js и contentscript.js. Добавляем popup.html — и наше приложение уже можно загрузить в Google Chrome и убедиться, что оно работает.
Чтобы убедиться в этом, можно взять код отсюда. Кроме того, что мы сделали, по ссылке настроена сборка проекта с помощью webpack. Чтобы добавить приложение в браузер, в chrome://extensions нужно выбрать load unpacked и папку с соответствующим расширением — в нашем случае dist.
Теперь наше расширение установлено и работает. Запуститьинструменты для разработчиков для разных контекстов можно следующим образом:
Доступ к консоли контент-скрипта осуществляется через консоль самой страницы, на которой он запущен.
Это браузерное расширение для работы с сетью Ethereum. В нем разные части приложения общаются через RPC при помощи библиотеки dnode. Она позволяет достаточно быстро и удобно организовать обмен, если в качестве транспорта ей предоставить nodejs stream (имеется в виду объект, реализующий тот же интерфейс):
Теперь мы создадим класс приложения. Оно будет создавать объекты API для popup и веб-страницы, а также создавать dnode для них:
Создадим инстанс приложения в background скрипте:
Так как dnode работает со стримами, а мы получаем порт, то необходим класс-адаптер. Он сделан при помощи библиотеки readable-stream, которая реализует nodejs-стримы в браузере:
Теперь создаем подключение в UI:
Затем мы создаем подключение в content script:
Так как API нам нужен не в контент-скрипте, а непосредственно на странице, мы делаем две вещи:
- Создаем два стрима. Один — в сторону страницы, поверх postMessage. Для этого мы используем вот этот пакет от создателей metamask. Второй стрим — к background поверх порта, полученного от runtime.connect . Пайпим их. Теперь у страницы будет стрим до бэкграунда.
- Инжектим скрипт в DOM. Выкачиваем скрипт (доступ к нему был разрешен в манифесте) и создаем тег script с его содержимым внутри:
Теперь создаем объект api в inpage и заводим его global:
У нас готов Remote Procedure Call (RPC) с отдельным API для страницы и UI. При подключении новой страницы к background мы можем это увидеть:
Пустой API и origin. На стороне страницы мы можем вызвать функцию hello вот так:
Работать с callback-функциями в современном JS — моветон, поэтому напишем небольшой хелпер для создания dnode, который позволяет передавать в объект API в utils.
Объекты API теперь будут выглядеть вот так:
Получение объекта от remote следующим образом:
А вызов функций возвращает промис:
Версия с асинхронными функциями доступна здесь.
В целом, подход с RPC и стримами кажется достаточно гибким: мы можем использовать steam multiplexing и создавать несколько разных API для разных задач. В принципе, dnode можно использовать где угодно, главное — обернуть транспорт в виде nodejs стрима.
Внутренний стейт и localStorage
Нам понадобится хранить внутренний стейт приложения — как минимум, ключи для подписи. Мы можем достаточно легко добавить стейт приложению и методы для его изменения в popup API:
В background обернем все в функцию и запишем объект приложения в window, чтобы можно было с ним работать из консоли:
Добавим из консоли UI несколько ключей и посмотрим, что получилось со стейтом:
Стейт нужно сделать персистентным, чтобы при перезапуске ключи не терялись.
Хранить будем в localStorage, перезаписывая при каждом изменении. Впоследствии доступ к нему также будет необходим для UI, и хочется также подписываться на изменения. Исходя из этого удобно будет сделать наблюдаемое хранилище (observable storage) и подписываться на его изменения.
Добавим инициализацию начального стейта и сделаем store observable:
"Под капотом" mobx заменил все поля store на proxy и перехватывает все обращения к ним. На эти обращения можно будет подписываться.
Далее я буду часто использовать термин “при изменении”, хотя это не совсем корректно. Mobx отслеживает именно доступ к полям. Используются геттеры и сеттеры прокси-объектов, которые создает библиотека.
Декораторы action служат двум целям:
- В строгом режиме с флагом enforceActions mobx запрещает менять стейт напрямую. Хорошим тоном считается работа именно в строгом режиме.
- Даже если функция меняет стейт несколько раз – например, мы меняем несколько полей в несколько строк кода, — обсерверы оповещаются только по ее завершении. Это особенно важно для фронтенда, где лишние обновления стейта приводят к ненужному рендеру элементов. В нашем случае ни первое, ни второе особо не актуально, однако мы будем следовать лучшим практикам. Декораторы принято вешать на все функции, которые меняют стейт наблюдаемых полей.
В background добавим инициализацию и сохранение стейта в localStorage:
Интересна здесь функция reaction. У нее два аргумента:
- Селектор данных.
- Обработчик, который будет вызван с этими данными каждый раз, когда они изменяются.
В отличие от redux, где мы явно получаем стейт в качестве аргумента, mobx запоминает к каким именно observable мы обращаемся внутри селектора, и только при их изменении вызывает обработчик.
Важно понимать, как именно mobx решает, на какие observable мы подписываемся. Если бы в коде я написал селектор вот так () => app.store , то reaction не будет вызван никогда, так как сам по себе хранилище не является наблюдаемым, таковыми являются только его поля.
Если бы я написал вот так () => app.store.keys , то опять ничего не произошло бы, так как при добавлении/удалении элементов массива ссылка на него меняться не будет.
Mobx в первый раз выполняет функцию селектора и следит только за теми observable, к которым мы получали доступ. Сделано это через геттеры прокси. Поэтому здесь использована встроенная функция toJS . Она возвращает новый объект, в котором все прокси заменены на оригинальные поля. В процессе выполнения она читает все поля объекта – следовательно, срабатывают геттеры.
В консоли popup снова добавим несколько ключей. На этот раз они попали еще и в localStorage:
При перезагрузке background-страницы информация остается на месте.
Весь код приложения до этого момента можно посмотреть здесь.
Безопасное хранение приватных ключей
Хранить приватные ключи в открытом виде небезопасно: всегда есть вероятность того, что вас взломают, получат доступ к вашему компьютеру и так далее. Поэтому в localStorage мы будем хранить ключи в зашифрованном паролем виде.
Для большей безопасности добавим приложению стейт locked, в котором доступа к ключам не будет совсем. Мы будем автоматически переводить расширение в стейт locked по таймауту.
Mobx позволяет хранить только минимальный набор данных, а остальное автоматически рассчитывать на их основе. Это — так называемые computed properties. Их можно сравнить с view в базах данных:
Теперь мы храним только шифрованные ключи и пароль. Все остальное вычисляется. Перевод в стейт locked мы делаем с помощью удаления пароля из стейта. В публичном API появился метод для инициализации хранилища.
У браузера есть idle API, через который можно подписаться на событие — изменения стейта. Стейт, соответственно, может быть idle , active и locked . Для idle можно настроить таймаут, а locked устанавливается, когда блокируется сама ОС. Также мы поменяем селектор для сохранения в localStorage:
Код до этого шага находится здесь.
Транзакции
Итак, мы подошли к самому главному: созданию и подписи транзакций в блокчейне. Мы будем использовать блокчейн WAVES и библиотеку waves-transactions.
Если не сделать observable вручную, то mobx сделает это сам при добавлении в массив messages. Однако он создаст новый объект, на который у нас не будет ссылки, а она понадобится для следующего шага.
Approve и reject мы выносим в API UI, newMessage — в API страницы:
Теперь попробуем подписать транзакцию расширением:
В целом все готово, осталось добавить простой UI.
Интерфейсу нужен доступ к стейту приложения. На стороне UI мы сделаем observable стейт и добавим в API функцию, которая будет этот стейт менять. Добавим observable в объект API, полученный от background:
В конце мы запускаем рендер интерфейса приложения. Это react-приложение. Background-объект просто передается при помощи props. Правильно, конечно, сделать отдельный сервис для методов и store для стейта, но в рамках данной статьи этого достаточно:
С помощью mobx очень просто запускать рендер при изменении данных. Мы просто вешаем декоратор observer из пакета mobx-react на компонент, и рендер будет автоматически вызываться при изменении любых observable, на которые ссылается компонент. Не нужно никаких mapStateToProps или connect, как в redux. Все работает сразу "из коробки":
Остальные компоненты можно посмотреть в коде в папке UI.
Теперь в классе приложения необходимо сделать селектор стейта для UI и при его изменении оповещать UI. Для этого добавим метод getState и reaction , вызывающий remote.updateState :
При получении объекта remote создается reaction на изменение стейта, который вызывает функцию на стороне UI.
Итак, приложение готово. Веб-страницы могут запрашивать подпись транзакций:
Код доступен по этой ссылке.
Заключение
Если вы дочитали статью до конца, но у вас остались вопросы, вы можете задать их в репозитории с расширением. Там же вы найдете коммиты под каждый обозначенный шаг.
А если вам интересно посмотреть код настоящего расширения, то вы сможете найти это здесь.
В конце 2020 года мы делали проект со снежинками — писали специальный скрипт, который запускал падающий снег на сайтах. Если бы мы хотели сделать такой снег на любом своём сайте, это не составило бы труда: добавляешь скрипт в код страницы, и готово.
А вот на чужих сайтах была проблема. Скрипт нужно было вставлять через консоль. А если на сайте была настроена политика безопасности, которая запрещает запуск внешних скриптов, то магия не срабатывала.
Сегодня мы это исправим — сделаем расширение для браузера, которое может запускать любой скрипт на любой странице. Мы охватим принцип, на основе которого вы сможете сделать собственные расширения, в том числе намного более сложные.
👉 Что такое расширение
Расширение для Chrome — это небольшая программа, которая выполняется внутри браузера и помогает расширить возможности сайтов. Сила расширения в том, что оно может выполняться прямо из меню браузера и не зависит от политик безопасности.
Примеры того, что может сделать расширение:
- Сохранить ваши пароли и другие личные данные,
- Выдрать из страницы скрытые данные (например, ссылку на скачивание музыки).
- Менять что-то на странице, например, отключать рекламу, переводить текст, удалять ненужное.
- Собирать статистику вашей работы в интернете.
- Подключаться к другим сервисам (почте, чатам, файлообменникам) и взаимодействовать с ними из браузера.
В этой статье
Мы сделаем самое простое расширение для браузера Chrome, которое позволит запускать скрипт со снежинками на любом сайте, независимо от настроенной политики безопасности. Для этого воспользуемся официальным руководством Google по созданию расширений.
Манифест
В каждом расширении для браузера должен быть манифест — документ, в котором написано:
- как называется расширение;
- к чему расширение может получить доступ;
- какие скрипты будут работать в фоне;
- как должна выглядеть иконка расширения;
- что показать или что выполнить, когда пользователь нажмёт на иконку расширения.
Манифест задаёт общие правила для всего расширения, поэтому манифест — единственный обязательный компонент. Можно обойтись без иконок и скриптов, но манифест обязательно должен быть.Каждый манифест хранится в файле manifest.json — создадим пустой файл с таким именем и напишем внутри такое:
«name»: «Запускаем снежинки на любом сайте»,
«description»: «Проект журнала Код»,
«version»: «1.0»,
«manifest_version»: 3
>Первые две строчки — это название и подробное описание расширения. Третья отвечает за номер версии расширения, а последняя говорит браузеру, какая версия манифеста используется в описании. На момент выхода статьи в феврале 2021 года используется третья версия.
Сохраняем файл и всё, расширение готово. Оно ничего не умеет, ничего не делает, зато мы уже можем добавить его в браузер. Для этого запускаем Хром и в адресной строке пишем:
Мы попадаем на страницу, которая нам покажет все установленные расширения:
Чтобы добавить своё расширение, в правом верхнем углу включаем режим разработчика, а затем нажимаем «Загрузить распакованное расширение»:
Теперь выбираем папку, в которой лежит наш манифест:
Отлично, мы только что добавили в браузер новое расширение:
Теперь мы можем обновлять наш манифест, класть в ту же папку дополнительные файлы, а для обновления в браузере достаточно будет нажать на круглую стрелку на карточке расширения.
Чтобы было проще работать и тестировать расширение, закрепим его на панели браузера:
Иконки
У расширения есть две иконки, которыми мы можем управлять:
- Картинка в карточке расширения на странице настроек.
- Иконка на панели браузера.
Чтобы не рисовать всё с нуля, скачаем папку с иконками из того же руководства Google и положим её в ту же папку, что и манифест:
Теперь добавим иконки в манифест. За картинку в карточке отвечает блок icon, а за иконку на панели — блок action. Разные размеры картинки нужны для того, чтобы на разных мониторах с любой плотностью пикселей иконки выглядели хорошо:
Сохраняем манифест, обновляем расширение на странице настроек и смотрим результат:
Настраиваем разрешения
Разрешения — это то, что браузер позволяет делать расширению со страницами и с их содержимым. Для запуска снежинок нам нужно сделать две вещи:
- Понять, какая вкладка сейчас активная, чтобы запустить снежинки именно на ней.
- Запустить наш скрипт со снежинками.
Чтобы получить доступ к активной вкладке и к запуску скриптов, добавим в манифест такую строку:
"permissions": ["activeTab", "scripting"],
Показываем меню
Если мы сейчас нажмём на иконку расширения на панели браузера, то ничего не призойдёт, потому что мы ничего не запрограммировали. Исправим это — сделаем так, чтобы при нажатии расширение показывало кнопку запуска. Когда расширение будет уметь больше, вместо одной кнопки можно будет показать целое меню.
Чтобы сделать всплывающее меню, добавим в манифест в раздел action такую строку:
Она означает, что при нажатии на иконку мы увидим рядом с ней мини-страничку, на которой что-то будет.Создадим в той же папке расширения файл popup.html и добавим в него такой код:
Чтобы браузер не ругался, что у нас нет файла popup.js , создадим пустой файл с таким названием и положим его в ту же папку:
Сохраняем манифест, обновляем его на странице настроек и видим, что у нашего расширения появилось меню с кнопкой:
Запускаем снежинки
Вся магия будет происходить в файле popup.js — откроем его и добавим такой код:
Последнее, что нам осталось сделать, — положить в функцию snowFall() полный код скрипта из проекта со снежинками и сохранить файл.
Проверка
В прошлый раз мы не смогли запустить скрипт на любой странице Яндекса — мешала политика безопасности. Теперь всё работает:
В этой инструкции я покажу, как создать расширение для браузера Google Chrome и при желании опубликовать его в открытом доступе.
Расширение или плагин для Chrome – это приложение, которое добавляет новые возможности браузеру. В магазине Chrome порядка 200 тысяч расширений для разработчиков, маркетологов, дизайнеров и других пользователей браузера.
SimilarWeb показывает 1,141 млрд посещений главной страницы за август. Если хотя бы 10% из них приходится на десктопный браузер и целевое действие, то это 141 млн открытых вкладок в месяц. На возврат и закрытие вкладки уходит не меньше секунды. Получается, мы собираемся сэкономить 31,5 тысячи человеко-часов в месяц.
Приготовим минимальный стартовый набор.
1. Создайте папку проекта. Назовите ее именем вашего расширения.
2. Создайте javascript-файл, в котором будет реализована логика приложения. Я назвал его app.js.
3. Добавьте в созданный файл команду для тестирования: вывод строки в консоль или в диалоговое окно браузера.
4. Создайте manifest.json – служебный файл, который должен быть в каждом расширении.
Обязательные параметры, должны быть в каждом manifest.json:
manifest_version – целое число, обозначает версию формата манифеста. Для современных версий браузера значение равно 2;
name – название расширения, до 45 символов. К названию стоит подойти ответственно – оно отображается в магазине, при установке и на странице управления расширениями (chrome://extensions);
description – простой текст, до 132 символов. Отображается в магазине и на странице управления расширениями;
icons – список из иконок расширения;
5. Подготовьте иконку в формате png размером 128х128 пикселей и положите ее в папку проекта. Эта версия отображается при установке и в магазине расширений. Рекомендуют также добавить иконку размером 48х48 пикселей – она отображается на странице управления расширениями. И можно добавить версию 16х16 пикселей, которая будет использоваться как фавикон.
К этому моменту в нашем проекте есть иконка расширения, manifest.json со служебной информацией и app.js, в котором позже появится код приложения.
Примечание: расширение может состоять из нескольких JS-файлов, HTML-верстки и CSS-стилей.
Теперь можно проверить, что мы выполнили минимальные требования к расширению.
1. Войдите в свой аккаунт в браузере Chrome.
2. Перейдете на страницу chrome://extensions.
3. В правом верхнем углу включите Режим разработчика.
4. Нажмите Загрузить распакованное расширение и выберите папку проекта. В результате вы увидите похожую картинку:
5. В новой вкладке браузера откройте любую веб-страницу. Отлично, работает!
Теперь мы готовы добавить полезное действие.
Получается, с помощью javascript нам нужно выбрать две ссылки и удалить этот атрибут.
1. В app.js сохраните ссылки в переменные:
Здесь мы выбираем элементы по их идентификатору (id).
2. Если такие ссылки найдены, удалите у них атрибут target.
Похоже, этого кода достаточно для решения проблемы.
Заодно давайте пропишем в manifest.json правило, по которому расширение будет запускать наш скрипт только на целевой странице. Для этого в параметре content_scripts в ключе matches пропишем конкретный URL:
Кстати, после обновления расширения стоит обновить версию и в manifest.json:
После внесения правок важно обновить расширение в браузере. Для этого нажмите на стрелку на странице управления расширениями (chrome://extensions/).
Готово! Проверим расширение в боевых условиях.
Этот шаг необязательный. Во-первых, возможно, вы не хотите делать доступным для всех свое расширение. А во-вторых, возможно, не захотите платить за это $5. Такой регистрационный сбор должен оплатить разработчик Chrome Web Store.
Это всё. Остается ждать результат проверки, которая может занять несколько недель.
Я отправил расширение на проверку параллельно с публикацией статьи. Как только получу ответ, добавлю комментарий со ссылкой на опубликованное расширение.
Надеюсь, эта инструкция была вам полезной. Буду рад обсудить детали в комментариях.
И всё это ради 5 (3) строк кода?
Всё это ради решения проблемы. В данном случае получилось решить её с помощью нескольких строк кода.
один раз установить расширение Tampermonkey
Вы правы, это можно делать и так. Или можно было просто написать сниппет и сохранить его в браузере. Подозреваю, что есть еще несколько вариантов. Но мне хотелось самому написать расширение для браузера и показать в инструкции, как это сделать. Писать под эту задачу сложное приложение, кажется, излишне.
Вот это уже другой вопрос. Поэтому я сознательно опустил тему непосредственно написания расширений, а комментарий относился именно к самой идеи/мотивации (читать: проблеме) и описал максимально быстрый и эффективный способ решения таких проблем (создание правок для сайтов).
Да, понимаю.
Кстати, если бы вы описывали пошагово создание расширения, какую задачу выбрали бы для иллюстрации?У меня было несколько идей, в итоге победила та, что связана с реальной «болью» и не требует долгих объяснений, чтобы не раздувать инструкцию.
Скорее всего я бы выбрал вариант автономного приложения с использованием сетевого API бесплатных сервисов (чтобы это смог повторить каждый), либо просто парсинга, с информативной иконкой с числовым показателем и уведомлениями (Notifications API).
Идеальным вариантом для демонстрации, как мне кажется, было бы расширение для мониторинга конкретной информации (входящие e-mail, доступные билеты, баланс на счёте, начало трансляций и так далее) с информативными image/text-уведомлениями.
Это не требует много кода, но функционал используемых API очень показателен и информативен, который в последствии можно универсально применить под свои нужды.
Ага, примерно так я первое расширение для Pyrus написал в 2013 году )))
UPD. Расширение опубликовано в Chrome Web Store. На почту никакое уведомление не приходило, поэтому сложно сказать, сколько времени заняла проверка.
Компания Microsoft 15 января 2020 года выпустила браузер Microsoft Edge для Windows, MacOS и для мобильных операционных систем. А в октябре 2020 года, разрабатываемую версию Microsoft Edge Dev для Linux, которая обновляется каждую неделю.
«В основе нового браузера Microsoft Edge используется платформа Chromium. Он совместим со всеми поддерживаемыми версиями Windows и macOS. Благодаря повышенной скорости работы и производительности, лучшей в своем классе совместимости с веб-сайтами и расширениями, а также встроенным функциям обеспечения конфиденциальности и защиты этот браузер может заменить все остальные».
Я не фанат Google Chrome и других браузеров основанных на платформе Chromium. Предпочитаю Palemoon, форк Firefox, но потребляющий намного меньше ресурсов компьютера, чем его старший брат.
Браузер шустрый, быстрее Google Chrome, легко настраиваемый за счёт расширений Chrome и потребляет меньше ресурсов.
Но меня заинтересовала одна фишка в Настройках Microsoft Edge, а именно предложение создать из любой веб-страницы веб-приложение в два клика.
Созданное приложение встраивается в систему, его значок запуска автоматически отображается на рабочем столе и системном Меню и открывается, как любое приложение в новом окне. А также значок запуска может быть добавлен на панель быстрого запуска
Примечание. Хотелось бы отметить, что значки запуска созданных приложений автоматически создаются из фавикона (favicon) веб-сайта, который отображается на каждой вкладке:
3. После чего откроется окно подтверждения - Установить приложение, где пользователь может изменить название данного приложения на своё усмотрение и нажать Установить.
Вот и всё. Приложение создано. Запустить его можно как из системного Меню приложений, так и с рабочего стола, а также добавить на панель быстрого запуска.
Я сделал небольшой эксперимент. Открыл канал YouTube в браузере и одновременно приложение YouTube, чтобы посмотреть на потребление ресурсов в Системном мониторе. И вот что показывает сисмонитор.
1. Если вы решили удалить созданное приложение, откройте Настройки браузера - Приложения - Управление приложениями.
2. Откройте веб-приложение, перейдите в Настройки - Удалить.
Читайте также: