Регистрация пользовательского элемента из расширения chrome

#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