如何使用 Chrome 扩展清单版本 3 将脚本导入到 Service Worker 中?

问题描述 投票:0回答:2

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

js
文件。

有什么方法可以将我的个人脚本文件导入到

service_worker.js
文件中吗?

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

google-chrome google-chrome-extension google-chrome-app browser-extension chrome-extension-manifest-v3
2个回答
97
投票

首先,重要警告:

  • 警告:Chrome 92 或更早版本不显示服务工作线程中发生的错误 - 这是一个 bug,已在较新的 Chrome 中修复,现在在

    chrome://extensions
    页面中显示错误。如果在编译(未闭括号等语法错误)或初始化(例如访问未定义的变量)期间发生未处理的异常,这些旧版本的 Chrome 无法注册后台脚本,因此如果您仍然支持旧 Chrome,您可能需要将代码包装在
    try/catch
    中。

  • 警告:Chrome 92 或更早版本 要求工作文件位于根路径中(bug)。

  • 警告! 不要导入基于 DOM 的库,如 jQueryaxios,因为 Service Worker 没有 DOM,所以没有

    document
    XMLHttpRequest
    等。直接使用
    fetch
    或查找/编写一个基于
    fetch
    并且不使用
    window
    document
    的库。

0。 NPM 包

使用像 webpack 这样的打包器。

1. Chrome 92 及更高版本中的 ES 模块

通过将

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

  • 名称必须以路径开头并以 .js 或 .mjs 等扩展名结尾
  • 可以使用Static
    import
    语句。
  • 动态
    import()
    尚未实现 (crbug/1198822)。

manifest.json:

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

bg.js:

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

如本答案开头所述,如果您仍然以 Chrome 92 或更早版本为目标,在注册期间不会显示错误,则每个导入的模块还应该在可能出现异常的地方使用 try/catch。

2. 导入脚本

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

manifest.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

2b。侦听器内的导入脚本

根据规范,我们必须使用 Service Worker 的

install
事件,并导入我们希望稍后能够在异步事件中导入的所有脚本(从技术上讲,除了 JS 事件的初始 task 之外的任何脚本)循环)。仅当安装或更新扩展或重新加载解压的扩展时才会调用此处理程序(因为它相当于更新)。

MV3 中的情况很复杂,因为 Service Worker 是为 Web 设计的,远程脚本可能无法离线使用。希望它会在 crbug/1198822 中得到简化。

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

const importedScripts = [];

function tryImport(...fileNames) {
  try {
    const toRun = new Set(fileNames.filter(f => !importedScripts.includes(f)));
    if (toRun.size) {
      importedScripts.push(...toRun);
      importScripts(...toRun);
    }
    return true;
  } catch (e) {
    console.error(e);
  }
}

self.oninstall = () => {
  // The imported script shouldn't do anything, but only declare a global function
  // (someComplexScriptAsyncHandler) or use an analog of require() to register a module
  tryImport('/js/some-complex-script.js');
};

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

0
投票

使用 chrome-extension-cli

chrome-extension-cli
包通过安装和预配置webpack解决了这个问题。这使您可以轻松导入包或模块

立即开始

不需要安装或配置Webpack。
Webpack 已预先配置,以便您可以专注于代码。

只需创建一个项目,就可以开始了。

了解更多:https://github.com/dutiyesh/chrome-extension-cli

© www.soinside.com 2019 - 2024. All rights reserved.