Опыт разработки виджетов для сторонних сайтов / Хабр

Опыт разработки виджетов для сторонних сайтов / Хабр Гаджет

А как надо делать?

Если вы когда-нибудь устанавливали на сайт какой-нибудь виджет, например, от ВК, то могли заметить, что код виджета разделен на две части: библиотеку (SDK) и инициализацию виджетов:

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

Мы видим, что для вставки любого виджета нужно один раз подключить SDK и добавить один пустой тэг с инициализацией виджета. А дальше все делает javascript: он может делать любые запросы и любое их количество на бэкенд, и разработчики виджета могут в любой момент эту логику изменить без изменения кода виджета на сайте.

А потом поговорим о том, что же у нас получилось и на что стоит обратить внимание.

Код библиотеки
Код вставки

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

Асинхронность

Сразу в глаза бросается атрибут async у тэга script. Он позволит браузеру не ждать загрузки нашего скрипта и продолжить отрисовывать сайт. Это важно: если по каким-то причинам наш скрипт будет недоступен (недоступен сервер, фаервол компании), это не должно влиять на скорость загрузки сайта клиента.

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

Поэтому в месте вызова виджета мы должны обработать оба сценария, когда SDK загрузилось и еще нет.

В первом случае мы просто вызываем функцию init(). Во втором — откладываем выполнение этой функции до момента, когда скрипт загрузится, добавляя замыкание в очередь. А последней строчкой в нашем SDK вызывается метод runInitCallbacks, который как раз и выполнит все отложенные инициализации.

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

Теперь наш код запускается всегда и не блокирует отрисовку страницы!

Библиотека

Не нужно думать, что виджет у вас будет один.

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

Гаджет:  Гаджеты Календари для Windows 7 скачать бесплатно » Страница 2

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

Поэтому сразу проектируем код таким образом, чтобы он позволял вставлять неограниченное число разных виджетов на одну страницу без ограничений. Первое, что приходит в голову: «а давайте просто выведем iframe с нашего сайта?». И сделаем код вида:

Из чего состоит гаджет для windows 7?

Как правило, простейший состоит из 2-х файлов:

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

Изоляция

Название объекта SDK и id контейнеров должны быть уникальными, ведь наш код будет выполняться на совершенно разных сайтах. Ни в коем случае нельзя нарваться на совпадения. ID контейнеров желательно генерировать уникальными, например, через uniqid(). Нельзя надеяться и на сторонние библиотеки, установленные на сайте, и совсем не желательно приносить их с собой. Да, я о jQuery, как вы уже догадались.

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

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

Код, написанный нами выше, позволяет не останавливаться на одном виджете: сейчас у нас есть только myCompanyApi.button(), но ничего не мешает добавить другие виджеты.

Кеширование

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

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

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

Гаджет:  вышивка аппликации на АлиЭкспресс — купить онлайн по выгодной цене

Лишние запросы на бэкенд

Если на сайт будет установлено 5 таких одинаковых виджетов, то на ваш сервер придет 5 одинаковых запросов, хотя по факту нужен был только один. Конечно, можно сделать кеш на nginx и не пропускать запрос дальше, но зачем нам самим себе делать паразитные запросы?

Невозможность расширения

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

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

Про то, какие проблемы есть в работе с iframe и их решении, поговорим попозже.

Немного про iframe

Iframe — по сути, отображение сайта в сайте. Вернемся к нашему кейсу с кнопкой покупки билетов. Если мы хотим при клике открывать попап со страницей выбора места — без iframe нам не обойтись. Какие же там есть нюансы?

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

Общение с  sdk

Часто требуется организовать общение нашего SDK с приложением внутри iframe, например, мы хотим при открытии виджета растянуть размер фрейма под размер контента. Для этого нам нужно сообщить размер контента из iframe в родительское окно. Это можно легко сделать через postMessage.

Спасибо за внимание, надеюсь, вы узнали для себя что-то новое.

Сергей Никитченко, Студия Валерия Комягина

Этап №1

Для начала надо создать директорию, в которой будет находиться . По мнению специалистов Microsoft, очень удобным является директория разделенная точкой. Например: first.gadget. Но на самом деле не имеет значения, как будет называться папка. Главное чтобы было понятно.

Разместить папку можно где угодно, но при создании и тестировании удобней всего размещать в системных папках. Например:

Этап №2

Затем создаем файл манифеста в директории .

«Манифест” – это XML файл, который содержит общую конфигурацию и информацию для ассоциированного . Информация, указанная манифестом, включает мета-информацию, которая передается пользователю в диалоге информации о таких как: иконка для , разработчика гаджета и т.п. Вся эта информация определяется в манифесте. Имя манифеста всегда должно быть.

Пример файла gadget.xml:

Гаджет:  Карта «Тройка»

Элемент <xml> Обязательный.

Декларация XML определяет версию XML и шифрование символов,
используемых в документе. Этот специфический документ соответствует
спецификации XML 1.0 и использует набор символов UTF-8 (unicode).

Свойства:

https://www.youtube.com/watch?v=CrWN8cSk-9s

Version. Обязателен. Значение – 1.0.

Encoding. Обязателен. Значение – UTF-8.

Элемент <gadget> Обязательный.

У элемента <gadget> нет атрибутов, но он включает в себя элементы потомков, которые и определяют сам гаджет.

Обязательные элементы:

Элемент <name> представляет собой имя пользователя, которое
отображается в описании гаджета на странице панели управления Windows
Sidebar и непосредственно на самой боковой панели.

Элемент <version> определяет версию .
Sidebar использует это значение во время установки гаджета. Если уже
был установлен гаджет с таким же именем, то Sidebar прежде всего
сравнивает версии и если версии различаются, то пользователь вынужден
выбрать соответствующую версию.

Действительные строки версии являются формой
major.minor.revision.build. Каждый из этих номеров (или восемь символов)
может содержать от 0 до 4 цифр, между значениями 0 и 9.

Элемент <hosts> является контейнером для одного или более элементов <hosts>.

Элемент потомок:

Обязательный. Элемент <host> идентифицирует приложение, которое принимает . Его элементы потомки определяют поведение гаджета для специфического хостового приложения.

Атрибуты:

Name. Обязательный. Необходимое значение – ‘sidebar’

Элемент <base> обеспечивают Sidebar файлом type и обязательной информацией версии API для управлением гаджета.

Атрибуты:

Type. Обязательный. Необходимое значение – ‘HTML’

Src. Обязательный. Указывает, какой файл должен загружать Sidebar для выполнения приложения.

apiVersion. Обязательный. Необходимое значение – 1.0.0

Необходимое значение – ‘Full’

Элемент <platform> указывает боковой панели минимальную версию Windows, которая может управлять приложением.

Атрибуты:

minPlatformVersion. Обязательный. Необходимое значение – ‘1.0’

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

Атрибуты:

Src. Обязательный. Путь к графическому файлу.

Элемент <namespace> зарезервирован для будущего использования.

Элемент <author> отображает информацию о разработчике гаджета.

Атрибуты:

Name. Обязательный. Имя разработчика гаджета.

Элемент <info> отображает более подробную информацию о разработчике.

Атрибут:

URL. Обязательный. Ссылка на сайт разработчика.

Элемент <logo> определяет графический файл или иконку,
ассоциированную с разработчиком, которая отображается рядом с именем
автора на панели управления гаджетами.

Атрибуты:

Src. Обязательный. Путь к графическому файлу.

Элемент <copyright> отображает лицензионные права, которые
принадлежат разработчику. Может содержать любую строку символов.

Значение элемента <description> отображает для пользователя в Gadget Gallery диалоговое окно.

Элемент <icons> определяет размер и графический файл иконки
гаджета. Графическим файлом может быть любой файл, который
поддерживается GDI 1.0.

Атрибуты:

Height. Опциональный. Целое число, которое указывает высоту, в пикселях, иконки графического файла.

Width. Опциональный. Целое число, которое указывает ширину, в пикселях, иконки графического файла.

. Src. Обязательный. Путь к графическому файлу.

Этап №3

Создадим html файл в директории с гаджетом. Пример файла:

Оцените статью
GadgetManiac
Добавить комментарий