我正在尝试将我的 chrome 扩展从清单版本 2 迁移到 3。现在,后台脚本已被清单 v3 中的服务工作人员替换,我无法再使用 html 文件并引用脚本标签中的
js
文件。
有什么方法可以将我的个人脚本文件导入到
service_worker.js
文件中吗?
我在互联网上搜索了几乎所有内容,但找不到任何解决方案。即使这里的官方文档注册后台脚本也没有那么有帮助。任何帮助将不胜感激。
首先,重要警告:
警告:Chrome 92 或更早版本不显示服务工作线程中发生的错误 - 这是一个 bug,已在较新的 Chrome 中修复,现在在
chrome://extensions
页面中显示错误。如果在编译(未闭括号等语法错误)或初始化(例如访问未定义的变量)期间发生未处理的异常,这些旧版本的 Chrome 无法注册后台脚本,因此如果您仍然支持旧 Chrome,您可能需要将代码包装在 try/catch
中。
警告:Chrome 92 或更早版本 要求工作文件位于根路径中(bug)。
警告! 不要导入基于 DOM 的库,如 jQuery 或 axios,因为 Service Worker 没有 DOM,所以没有
document
、XMLHttpRequest
等。直接使用 fetch
或查找/编写一个基于 fetch
并且不使用 window
或 document
的库。
使用像 webpack 这样的打包器。
通过将
"type": "module"
添加到 manifest.json 中 background
的声明中来启用。
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。
此内置函数同步获取并运行脚本,以便它们的全局变量和函数立即可用。
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
。
根据规范,我们必须使用 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;
}
}
});
chrome-extension-cli
包通过安装和预配置webpack解决了这个问题。这使您可以轻松导入包或模块
立即开始
您不需要安装或配置Webpack。
Webpack 已预先配置,以便您可以专注于代码。只需创建一个项目,就可以开始了。