24

我正在尝试将我的 chrome 扩展从清单版本 2 迁移到 3。现在后台脚本已被清单 v3 中的服务人员替换,我不能再使用 html 文件并js在脚本标签中引用文件。

有什么方法可以将我的单个脚本文件导入service_worker.js文件中?

我在互联网上搜索了几乎所有内容,但找不到任何解决方案。甚至这里的官方文档注册后台脚本也没有太大帮助。任何帮助,将不胜感激。

4

1 回答 1

38

首先,重要的警告:

  • 警告!由于架构限制,如果在其编译期间发生未处理的异常(如未闭合括号之类的语法错误)或初始化(例如访问未定义的变量),则无法注册服务工作者,因此我们将代码包装在try/catch. 请注意,在 Chrome 93 之前,该错误并未显示在任何地方(这是一个错误),现在它显示在 chrome://extensions 页面的扩展卡上的错误列表中。

  • 警告!工作文件必须位于 Chrome 版本早于 93的根路径中。

  • 警告!不要导入像jQuery这样的基于 DOM 的库,因为 service worker 没有 DOM,所以没有document,XMLHttpRequest等等。

1.导入脚本

这个内置函数同步获取并运行脚本,以便它们的全局变量和函数立即可用。

清单.json:

"background": { "service_worker": "bg-loader.js" },

bg-loader.js 只是单独文件中实际代码的 try/catch 包装器:

try {
  importScripts('/path/file.js', '/path2/file2.js' /*, and so on */);
} catch (e) {
  console.error(e);
}

如果某个文件抛出错误,则不会导入后续文件。如果您想忽略此类错误并继续导入,请在其自己的 try-catch 块中单独导入此文件。

不要忘记指定文件扩展名,通常是.js.mjs.

1b。侦听器中的 importScripts

根据规范,我们必须使用服务工作者的install事件并导入我们希望稍后能够在异步事件中导入的所有脚本(从技术上讲,是 JS 事件循环初始任务之外的任何内容。此处理程序仅在安装或更新扩展或重新加载未打包的扩展时调用(因为它等于更新)。

这在 MV3 中很复杂,因为服务工作者是为 Web 设计的,远程脚本可能无法离线使用。希望它会在crbug/1198822中得到简化。

另请参阅:WebPack 的 webpack-target-webextension插件。

self.oninstall = () => {
  tryImport('/js/some-complex-script.js');
};

function tryImport(...fileNames) {
  try {
    importScripts(...fileNames);
    return true;
  } catch (e) {
    console.error(e);
  }
}

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.action === 'somethingComplex') {
    if (tryImport('/js/some-complex-script.js')) {
      // calling a global function from some-complex-script.js
      someComplexScriptAsyncHandler(msg, sender, sendResponse);
      return true;
    }
  }
});

2. Chrome 92 及更新版本中的 ES 模块

通过添加到manifest.json"type": "module"中的声明启用。background

  • import可以使用静态语句。
  • 动态import()尚未实现 ( crbug/1198822 )。

清单.json:

"background": { "service_worker": "bg.js", "type": "module" },
"minimum_chrome_version": 92,

bg.js:

模块名称必须以路径开头并以 .js 或 .mjs 之类的扩展名结尾

import {foo} from '/path/file.js';
import './file2.js';

// each imported module should also use try/catch for their own init
try { init(); } catch (e) { console.error(e); }
function init() {
  // .........
}
于 2021-02-28T11:06:30.153 回答