Ограничения и проблемы Shadow DOM
Тред из третьего дня моей недели в @jsunderhood.
Тред про ограничения Shadow DOM и связанные с ними проблемы.
— jsunderhood (@jsunderhood) November 11, 2020
Как и кастомные элементы, Shadow DOM имеет ряд ограничений, наиболее важные из которых обусловлены самим устройством API, реализованного в браузерах. В том числе, природой изоляции.
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 1: та же, что и для кастомных элементов — Shadow DOM не работает с выключенным JS. Этот факт делает невозможными некоторые сценарии использования, прежде всего SSR.
— jsunderhood (@jsunderhood) November 11, 2020
Кроме того, это также означает проблемы с SEO. В качестве решения в Google советуют Rendertron на базе Puppeteer, который умеет отдавать роботам статику. Мои коллеги в Vaadin его используют.https://t.co/smcwXiBtwt
— jsunderhood (@jsunderhood) November 11, 2020
Существует черновик API декларативного Shadow DOM, над которым работает Mason Freed из Google. Реализация есть в Chrome за флагом, недавно о ней вышла статья на https://t.co/O4bOplajxu.https://t.co/f4iTvUKXAE
— jsunderhood (@jsunderhood) November 11, 2020
Видео с примером использования декларативного Shadow DOM для изоляции стилей недавно опубликовал Вадим Макеев.https://t.co/z81jsVNtaa
— jsunderhood (@jsunderhood) November 11, 2020
К стабильной версии декларативный Shadow DOM еще не готов. Идет обсуждение рисков, связанных с XSS и санитайзерами. Также пока неясно, что будет с декларативными кастомными элементами.https://t.co/DjUeTISwyz
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 2: изоляция Shadow DOM создает преграду для связей по ID. В итоге ARIA-атрибуты вроде aria-labelledby не работают для элементов, находящихся по разные стороны shadow root.
— jsunderhood (@jsunderhood) November 11, 2020
О том, как эта проблема проявляется на практике, написал Devon Govett из Adobe. Он поделился выводами из своего эксперимента на тему использования хуков React Aria внутри веб-компонентов.https://t.co/irmMFNQZZG
— jsunderhood (@jsunderhood) November 11, 2020
Решением может стать Accessibility Object Model (AOM). Это целый набор экспериментальных API, которые пока находятся в разработке. Подробнее можно почитать в статье Léonie Watson.https://t.co/oRCvUFjDUs
— jsunderhood (@jsunderhood) November 11, 2020
Одна из идей в рамках AOM — атрибут, позволяющий явно указывать ID элементов, к которым необходим доступ извне. Что-то вроде атрибута exportparts, который доступен для CSS Shadow Parts.https://t.co/4YmRuyeSdf
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 3: изоляция затрагивает также и элемент <form>. Если кнопка в форме находится внутри shadow root, отправлять форму она не сможет. Пример приводит в своей статье Poul H. Hansen.https://t.co/1Nfyr7E4AU
— jsunderhood (@jsunderhood) November 11, 2020
Справедлива эта проблема и для элементов <input> внутри Shadow DOM. В прошлом Polymer предлагал компонент для сериализации форм с рекурсивным обходом вложенных shadow root.https://t.co/6VXm9laNuy
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 4: отсутствие API для работы с выделенным текстом внутри Shadow DOM при использовании window.getSelection(). Это актуально для WYSIWYG-редакторов вроде CKEditor, Quill и Trix.https://t.co/x90qPWWmst
— jsunderhood (@jsunderhood) November 11, 2020
В Chrome этот метод реализован на shadow root, в Firefox работает глобальный метод. Но в Safari действует изоляция, и getSelection() не возвращает данные об элементах внутри Shadow DOM.https://t.co/FOsVYk4kec
— jsunderhood (@jsunderhood) November 11, 2020
Sam Thorogood из Google написал экспериментальный полифилл, позволяющий обойти это ограничение в Safari. Для одного из компонентов Vaadin я интегрировал этот полифилл в форк Quill.https://t.co/po2Zfvfzkb
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 5: проблемы с автозаполнением форм. В баг-трекере Chromium есть issue на эту тему, и ему уже больше трех лет. В общем, с формами у Shadow DOM как-то совсем не задалось.https://t.co/s9kl9XT1wA
— jsunderhood (@jsunderhood) November 11, 2020
Затрагивает эта проблема и браузерные расширения, прежде всего менеджеры паролей. Каждому из них потребуется соответствующий фикс. Например, в 1Password он уже реализован.https://t.co/RXgoKpkNvq
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 6: изоляция стилей не работает в случае с font-face и keyframes. Решение этой проблемы требует стандартизации. На данный момент font-face в Shadow DOM использовать нельзя.https://t.co/7VH7BT69Ht
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 7: сторонние скрипты. Google Tag Manager, A/B тесты, аналитика и все, что так любят добавлять на сайт маркетологи, очень плохо дружит с Shadow DOM. Об этом тоже важно помнить.
— jsunderhood (@jsunderhood) November 11, 2020
Проблема № 8: тестирование. На сегодняшний день Shadow DOM уже поддерживается в Cypress, TestCafe, WebdriverIO и Playwright. В Selenium поддержка пока не реализована.https://t.co/es2F7vfXOs
— jsunderhood (@jsunderhood) November 11, 2020
Насчет WebdriverIO: поддержка Shadow DOM появилась в версии 5.5.0 и реализация у них своя (поскольку в протоколе WebDriver нет стандартизированного API).https://t.co/Yg7UJoyosOhttps://t.co/oZ57v3ef1z
— jsunderhood (@jsunderhood) November 11, 2020
Есть issue на эту тему, где в том числе поделился опытом Diego Ferreiro Val из Salesforce. Согласиться на добавление API, которое бы нарушало изоляцию, разработчики браузеров не готовы.https://t.co/7494Gm0xDx
— jsunderhood (@jsunderhood) November 11, 2020
Вроде бы, все основные проблемы перечислил. Есть и другие — например, в Chrome в Shadow DOM не работает перевод страницы.https://t.co/IxyIqDlHCa
— jsunderhood (@jsunderhood) November 11, 2020
Еще есть баг на iOS, связанный с кнопками быстрого перехода между полями формы в Shadow DOM. Он был исправлен совсем недавно.https://t.co/PF5SCBzcZn
— jsunderhood (@jsunderhood) November 11, 2020
В качестве заключения: проблем у Shadow DOM по-прежнему много, и о них желательно знать заранее (или придется городить костыли). Неспроста YouTube использует полифилл даже в Chrome.
— jsunderhood (@jsunderhood) November 11, 2020
Да, чуть не забыл: реклама же! Мне однажды тоже довелось встретить div с shadow root в рекламном баннере Яндекс-почты. Для блокировщиков это проблема.https://t.co/H0oToP9mUf
— jsunderhood (@jsunderhood) November 11, 2020
Так или иначе, статистика показов страниц в Chrome Platform Status говорит сама за себя: по сравнению с кастомными элементами, у которых около 10%, Shadow DOM почти вдвое менее популярен.https://t.co/PiS96eSZW4
— jsunderhood (@jsunderhood) November 11, 2020