从 chrome 扩展注册自定义元素

Registering a custom element from a chrome extension

我曾尝试通过本机 javascript 和聚合物从 chrome 扩展中注册自定义元素,但没有成功。 The issue is documented here.

Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'polymer-element'. Elements cannot be registered from extensions.

我正在寻找有关在扩展中使用 Web 组件的建议 - 有人这样做了吗?我的直觉是暂时在阴影 DOM 上使用标准 html 标记(div,等等...)注册这些元素,直到它被支持为止。有什么建议吗?

确实可以。但是,有点老套。

原答案

步骤如下:

  • 本机 Web 组件(无 Polymer)
    注意:这需要使用 webcomponentsjs polyfill
    Chrome 将阻止原生 registerElement 在 chrome 扩展中执行。为了克服它,你需要阻止使用原生的 registerElement 来支持模拟的(polyfill)。

webcomponents-lite.js 中注释掉以下代码(如果您愿意,可以使其更优雅:

scope.hasNative = false; //Boolean(document.registerElement);

瞧! nativeregisterElement 现在已被 polyfill 取代 - chrome 不会阻止在扩展中使用。

  • 聚合物网络组件
    您将需要执行上述步骤中列出的代码,此外,您还需要通过以下代码加载聚合物

      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 在动态加载时无法在扩展中工作。因此,上述修改是必要的。一个更简单的替代方法是 将聚合物加载到内容脚本中的头部 中,如下所示:

  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 
    });

您必须chrome.extension.getURL 加载的 url 添加到清单的 web_accessible_resources 部分。

以上是必要的,因为 polymer.html 必须通过 html 资源加载。阅读 Eric Bidelman's reply here

请注意如果您的组件已经加载它们,您可能不需要在此处加载它们。

2017 年 7 月遇到这个问题。我找到的直接解决方案是加载最新的 webcomponents polyfill for custom elements 作为额外的内容脚本。 polyfill 文件中无需更改代码(可能改进了功能检测)。

清单摘录:

"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["webcomponents-sd-ce.js", "contentscript.js"]
    }
]

对我来说,在 content.js 中使用 @webcomponents/custom-elements 包就足够了。 另外 webcomponents-sd-ce.js 重量大约 80kb 而 custom-elements.min.js 只有 16kb。

只需将其作为依赖项安装并导入到 content.js 中,让您的包管理器完成剩下的工作。

npm i @webcomponents/custom-elements
import '@webcomponents/custom-elements'

这就是我在我的项目中使用它的方式popup-tab-switcher


我认为所有这些解决方法都不是必需的,自定义元素必须适用于没有 polyfill 的扩展。请投票给 the issue in Chrome bugs 以提请注意此缺陷。