首先,重要警告:
0. NPM 包
使用像 webpack 这样的捆绑器。
1. Chrome 92 及更高版本中的静态 ES 模块
在 manifest.json 中 "type": "module"
声明来 background
启用
-
名称必须以路径开头并以扩展名结尾:
./foo.js
, /foo/bar.mjs
-
可以使用
import
静态
-
动态
import()
尚未实现( crbug/1198822 )。
清单.json:
"background": { "service_worker": "bg.js", "type": "module" },
"minimum_chrome_version": "92",
背景.js:
// files must start with a path and end with an extension!
import {foo} from '/path/file.js';
import './file2.js';
try {
chrome.runtime.onMessage.addListener(...........);
doSomething();
// .................
} catch (err) { console.error(err); }
每个导入的模块也应该在内部使用 try/catch。如果仍然无法捕获错误,请使用 --enable-logging=stderr --v=1 2>log.txt
命令行重新启动 chrome,并在 log.txt 中查找带有扩展程序 ID 的消息。
此内置函数同步获取并运行脚本,因此其全局变量和函数可立即使用。它比 import
Chrome 中的静态函数慢得多,这在导入大量脚本时会变得明显。
清单.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. importScripts
监听器内部的
根据规范,我们必须使用服务工作线程的 install
事件并导入我们希望稍后能够在异步事件中导入的所有脚本(从技术上讲,是 JS 事件循环 的 任务 )。 仅在安装或更新扩展程序或重新加载解压的扩展程序时(因为它等同于更新)才会调用此处理程序。
在 MV3 中,这个问题很复杂,因为服务工作线程是为 Web 设计的,远程脚本可能无法离线使用。希望在 crbug/1198822 .
另请参阅: webpack-target-webextension 插件。
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;
}
}
});