[Из песочницы] Проблемы и нюансы при разработке под SmartTV с использованием React.js

Хочу поделиться опытом разработки приложения с просмотром видео контента для SmartTV (Tizen и WebOS) и с какими проблемами мы столкнулись.

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

Так как это браузер, то ничего нам не мешало использовать React.js для разработки, что повлияло на некоторые проблемы с производительностью.

Я не буду рассказывать о том, как именно нужно делать с примерами кода, я расскажу о нюансах и решениях, которые были приняты.
Пройдемся по основным моментам:

  1. Ограниченные ресурсы
  2. Навигация
  3. Производительность стилей и рендеринга
  4. Видео плееры
  5. Backend


Ограниченные ресурсы


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

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

Решение этой проблемы react-window
Он не хранит все элементы вне окна в DOM.

Навигация


Если на компьютере мы привыкли, что мы кликаем мышкой по элементам на сайте, то на телевизорах мы пользуемся пультом, который бывает и с возможностью использования как мышь, но в большинстве это кнопки. Отсюда вылазит проблема навигации, что мы должны обрабатывать нажатия кнопок пульта и навигировать по всему приложению без курсора, но, в то же время нам необходимо и обрабатывать нажатия на элементы с помощью «клика».
Некоторые коды кнопок на пультах LG и Samsung отличаются, как и отличаются от клавиатуры обычной, поэтому для каждой платформы у нас были захардкожены коды кнопок, которые мы обрабатываем.

Пример Tizen
Tizen

export default {
  KEY_0: 48,
  KEY_1: 49,
  KEY_2: 50,
  KEY_3: 51,
  KEY_4: 52,
  KEY_5: 53,
  KEY_6: 54,
  KEY_7: 55,
  KEY_8: 56,
  KEY_9: 57,
  KEY_UP: 38,
  KEY_DOWN: 40,
  KEY_LEFT: 37,
  KEY_RIGHT: 39,
  KEY_OK: 13,
  KEY_BACK: 10009,
  KEY_CHANNEL_UP: 427,
  KEY_CHANNEL_DOWN: 428,
  KEY_MEDIA_FAST_FORWARD: 417,
  KEY_MEDIA_PAUSE: 19,
  KEY_MEDIA_PLAY: 415,
  KEY_MEDIA_PLAY_PAUSE: 10252,
  KEY_MEDIA_REWIND: 412,
  KEY_MEDIA_STOP: 413,
  KEY_DEBUG_TOGGLE_CONSOLE: 403,
  KEY_DEBUG_TOGGLE_QUICK_EDIT: 404,
  KEY_DEBUG_SET_FAVOURITES: 405,
  KEY_DEBUG_CLEAR_FAVOURITES: 406,
  KEY_SHOW_REMOTE_POINTER: 7777777, // not applicable
  KEY_HIDE_REMOTE_POINTER: 7777777, // not applicable
};


WebOS

export default {
  KEY_0: 48,
  KEY_1: 49,
  KEY_2: 50,
  KEY_3: 51,
  KEY_4: 52,
  KEY_5: 53,
  KEY_6: 54,
  KEY_7: 55,
  KEY_8: 56,
  KEY_9: 57,
  KEY_UP: 38,
  KEY_DOWN: 40,
  KEY_LEFT: 37,
  KEY_RIGHT: 39,
  KEY_OK: 13,
  KEY_BACK: 461,
  KEY_MEDIA_FAST_FORWARD: 417,
  KEY_MEDIA_PAUSE: 19,
  KEY_MEDIA_PLAY: 415,
  KEY_MEDIA_PLAY_PAUSE: 10252,
  KEY_MEDIA_REWIND: 412,
  KEY_MEDIA_STOP: 413,
  KEY_CHANNEL_UP: 33,
  KEY_CHANNEL_DOWN: 34,
  KEY_DEBUG_SET_EMAIL: 403,
  KEY_DEBUG_TOGGLE_CONSOLE: 404,
  KEY_DEBUG_TOGGLE_QUICK_EDIT: 405,
  KEY_DEBUG_SET_FAVOURITES: 406,
  KEY_DEBUG_CLEAR_FAVOURITES: 407,
  KEY_SHOW_REMOTE_POINTER: 1536,
  KEY_HIDE_REMOTE_POINTER: 1537,
};


Клавиатура

export default {
  KEY_0: 48,
  KEY_1: 49,
  KEY_2: 50,
  KEY_3: 51,
  KEY_4: 52,
  KEY_5: 53,
  KEY_6: 54,
  KEY_7: 55,
  KEY_8: 56,
  KEY_9: 57,
  KEY_UP: 38,
  KEY_DOWN: 40,
  KEY_LEFT: 37,
  KEY_RIGHT: 39,
  KEY_OK: 13,
  KEY_BACK: 8, // backspace
  KEY_MEDIA_FAST_FORWARD: 70, // f
  KEY_MEDIA_PLAY_PAUSE: 80, // p
  KEY_MEDIA_REWIND: 66, // b
  KEY_MEDIA_STOP: 83, // s
  KEY_CHANNEL_UP: 70, // f
  KEY_CHANNEL_DOWN: 71, // g
  KEY_DEBUG_SET_EMAIL: 81, // q
  KEY_DEBUG_TOGGLE_CONSOLE: 87, // w
  KEY_DEBUG_TOGGLE_QUICK_EDIT: 69, // e
  KEY_DEBUG_SET_FAVOURITES: 88, // w
  KEY_DEBUG_CLEAR_FAVOURITES: 82, // r
  KEY_SHOW_REMOTE_POINTER: 7777777, // not applicable
  KEY_HIDE_REMOTE_POINTER: 7777777, // not applicable
};


Как можно заметить, на клавиатуре это кнопки с буквами (в комментариях указаны).

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

Другой особенностью навигации является фокус, на каждом экране должен быть элемент в фокусе, потому что потеряв фокус, мы уже не сможем навигировать по экрану. Каждому элементу прописывались свойства focus и id фокуса. При навигации нужно было всегда это учитывать, но и к тому же, иногда возникает требование при возвращении назад восстанавливать состояние полностью предыдущего экрана, поэтому навигация была написана полностью кастомная.

Производительность стилей и рендера


Анимация на CSS работает медленно на телевизорах, особенно, когда DOM элементов, которые попадают в анимирование много, можно увидеть не плавное изменение, а слайд-шоу. Один из вариантов решение этой проблемы — canvas. Отрисовка на нем, анимация, подсветка при навигировании ускоряют работу в разы, но, если у вас есть автоматизаторы, то им такая реализация может не понравиться, т.к им сложно по картинке проверять контент.

Много перерендереваний на странице — еще одна боль, все начинает тормозить, дергаться. Нужно было максимально контролировать этот процесс, после чего shouldComponentUpdate компонентов выглядит так:

image

В итоге переписали чувствительные части приложения на vanilla js, стало быстрее.

Видео плееры


У LG и Samsung разные нативные видео плееры, что тоже создает дополнительные трудности при разработке. Для них используются разные sdk, с разной функциональностью, нужно учитывать, что не все возможности одинаковы в LG и Samsung и могут отличаться от версии к версии ОС.

Также  были проблемы с нагрузкой при запуске видео — решалось кэшированием, параллелизацией и откладыванием запросов, обработок.

Backend


На скорость работы влияет качество бэкенда, скорость обработки запросов и их количество. На стороне FE должно быть минимальное количество обработки данных. Если нужно подгружать большие объемы даных, можно использовать web workers.

© Habrahabr.ru