#javascript #google-chrome-extension #google-chrome-devtools #custom-controls #polyfills
#google-chrome-extension #polymer #веб-компонент
Вопрос:
Я пытался зарегистрировать пользовательские элементы через собственный javascript и polymer из расширения chrome, но безуспешно. Проблема задокументирована здесь .
Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'polymer-element'. Elements cannot be registered from extensions.
Я ищу предложения по использованию веб-компонентов в расширении — кто-нибудь делал это? Мой инстинкт заключается в том, чтобы зарегистрировать эти элементы, используя стандартные html-теги (div и т.д.) в shadow DOM на время, пока это не будет поддерживаться. Есть предложения?
Ответ №1:
Для меня было достаточно использовать @webcomponents/custom-elements
package в моем content.js
. Также webcomponents-sd-ce.js
весит около 80 КБ и custom-elements.min.js
только 16 КБ.
Просто установите его как зависимость и импортируйте в content.js
, а остальное пусть ваш менеджер пакетов сделает сам.
npm i @webcomponents/custom-elements
import '@webcomponents/custom-elements'
Вот как я использую его в своем проекте с переключателем всплывающих вкладок.
Я считаю, что все эти обходные пути не являются необходимыми, и пользовательские элементы должны работать для расширений без полизаполнений. Пожалуйста, проголосуйте за проблему в Chrome bugs, чтобы привлечь внимание к этому недостатку.
Комментарии:
1. Я собирался написать этот ответ, но понял, что кто-то уже нашел это. В качестве альтернативы вы могли бы просто скопировать / вставить
./node_modules/@webcomponents/custom-elements/custom-elements.js
в корневую папку вашего расширения и зарегистрировать его как скрипт содержимого в вашемmanifest.json
2. Это отлично работало с моим расширением Chrome! Это было очень просто, просто установите npm и импортируйте polyfill в верхней части класса MyCustomElement, после чего все, что связано с моим пользовательским элементом, работало в моем скрипте содержимого!!
3. Если вы не используете npm в своем расширении, вы также можете загрузить файл polyfill с unpkg , а исходный код доступен на Github .
Ответ №2:
Это действительно возможно. Но, немного халтурно.
Оригинальный ответ
Вот шаги:
- ПРИМЕЧАНИЕ
Собственные веб-компоненты (без Polymer): для этого требуется использование полизаполнителя webcomponentsjs
Chrome предотвратит выполнение собственногоregisterElement
элемента в расширении Chrome. Чтобы преодолеть это, вам нужно запретить использование собственногоregisterElement
в пользу имитируемого (полизаполнение).
В webcomponents-lite.js
Закомментируйте следующий код (и сделайте его более элегантным, если хотите:
scope.hasNative = false; //Boolean(document.registerElement);
И вуаля! собственный элемент registerElement
теперь заменен на polyfill, который chrome не запрещает использовать в расширении.
-
Веб-компоненты Polymer
Вам нужно будет выполнить код, указанный на шаге выше, и, кроме того, вам нужно будет загрузить polymer с помощью следующего кодаvar link = document.createElement('link'); link.setAttribute('rel', 'import'); link.setAttribute('href', "link_to_your_polymer.html"); link.onload = function() { // Execute polymer dependent code here }
ОБНОВЛЕНИЕ # 1 — Улучшенное решение
После дальнейшего изучения я узнал, что Polymer не будет работать в расширении при динамической загрузке. В результате вышеуказанные изменения необходимы. Более простой альтернативой этому является загрузка polymer в head вашего скрипта содержимого следующим образом:
function loadRes(res) {
return new Promise(
function(resolve, reject) {
var link = document.createElement('link');
link.setAttribute('rel', 'import');
link.setAttribute('href', res);
link.onload = function() {
resolve(res);
};
document.head.appendChild(link);
});
}
loadRes( chrome.extension.getURL("path_to_your_webcomponents-lite.js") ) // You may/may not need webcomponents.js here
.then( loadRes( chrome.extension.getURL("path_to_your_polymer.html") ) )
.then( loadRes( chrome.extension.getURL("path_to_your_custome_component") ) )
.then(function(){
// code that depends on web components
});
ВЫ ДОЛЖНЫ добавить URL-адреса, загруженные chrome.extension.getURL
в web_accessible_resources
часть вашего манифеста.
Вышесказанное необходимо, поскольку polymer.html должен быть загружен через ресурс html. Прочитайте ответ Эрика Бидельмана здесь
Пожалуйста, обратите внимание, что вам может не понадобиться загруженное здесь полизаполнение webcomponents, если ваш компонент уже загружает их.
Комментарии:
1. Действительно ли необходимо полизаполнение, поскольку вы вводите все на главную страницу?
2. Возможно, это не требуется. Изначально я использовал полизаполнение, потому что
registerElement
было запрещено выполнение из расширения Chrome, когда я загружал polymer через скрипт содержимого. Теперь, когда я загружаю эти ресурсы в<HEAD>
, я полагаю, вы можете отказаться от полизаполнения.3. Я не могу заставить его работать с этим кодом. Можете ли вы показать мне, как должен выглядеть мой манифест? Выполняется мой content_scripts (пробовал с <all_urls>), но в моем popup.html итак, я думаю, что этот файл не введен
4. Я получаю следующую ошибку: не удается прочитать свойство ‘appendChild’, имеющее значение null
5. Вам нужно убедиться, что каждый URL указан в доступных веб-ресурсах. Если нет, то chrome.extension.getURL вернет null, что приведет к вашей ошибке
Ответ №3:
Столкнулся с этой проблемой в июле 2017 года. Простое решение, которое я нашел, — загрузить последнюю версию полизаполнения web components для пользовательских элементов в качестве дополнительного скрипта содержимого. В файле polyfill не требуется вносить изменения в код (возможно, было улучшено обнаружение функций).
Извлечение из манифеста:
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["webcomponents-sd-ce.js", "contentscript.js"]
}
]
Комментарии:
1. Ссылка кажется мертвой
2.Вы можете найти
webcomponents-sd-ce.js
здесь.3. На самом деле вы можете создать его самостоятельно. Клонируйте проект webcomponentsjs . Из корня проекта запустите,
npm install
а затемnpm run build
. Это создаст папку с именемbundles
. Там вы найдете свой файл. @Treycos