Firefox扩展出现‘import声明仅能在模块顶层’错误求助
解决Firefox扩展Content Script中ES模块导入报错问题
问题场景
项目目录结构:
app js foo.js content.js manifest.json background.js
各文件代码
foo.js:
function myFunc() { let hello = 'hello from foo.js'; return hello; } export {myFunc};
content.js:
import { myFunc } from './js/foo.js'; browser.runtime.onMessage.addListener((message) => { let result = myFunc(); console.log(result); });
manifest.json(原配置):
{ "manifest_version": 2, "name": "test", "version": "1.0.0", "description": "A notetaking tool for YouTube videos", "icons": { "48": "icons/border-48.png" }, "background": { "scripts": ["background.js"] }, "permissions": [ "tabs" ], "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_start" } ], "web_accessible_resources":[ "icons/my_icon.svg", "js/*" ] }
background.js:
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { browser.tabs.sendMessage(tabId, {message: 'hello from background.js'}); });
报错信息
import declarations may only appear at the top level of a module
错误原因
Manifest V2 中的 Content Script 默认以普通脚本而非ES模块的方式加载,即使import语句在文件顶部,浏览器也无法识别模块语法,因此抛出错误。
解决方案
方案1:升级到 Manifest V3(推荐)
Manifest V3 原生支持将 Content Script 作为模块加载,修改步骤如下:
- 更新
manifest.json:- 将
manifest_version改为3 - 在
content_scripts配置中添加"type": "module" - 调整
background配置为service_worker(V3强制要求)
- 将
修改后的manifest.json:
{ "manifest_version": 3, "name": "test", "version": "1.0.0", "description": "A notetaking tool for YouTube videos", "icons": { "48": "icons/border-48.png" }, "background": { "service_worker": "background.js" }, "permissions": [ "tabs" ], "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_start", "type": "module" } ], "web_accessible_resources": [ { "resources": ["icons/my_icon.svg", "js/*"], "matches": ["<all_urls>"] } ] }
- 保持
content.js和foo.js代码不变,此时浏览器会将content.js作为模块加载,import语法可正常工作。
方案2:Manifest V2 下动态注入模块脚本
如果暂时无法升级到V3,可通过Background Script动态注入模块形式的Content Script:
- 修改
manifest.json:- 移除原有的
content_scripts配置 - 在
web_accessible_resources中添加content.js
- 移除原有的
修改后的manifest.json片段:
{ "manifest_version": 2, // 其他原有配置保持不变 "web_accessible_resources":[ "icons/my_icon.svg", "js/*", "content.js" ] }
- 更新
background.js,使用executeScript注入模块脚本:
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { // 确保页面加载完成后执行注入 if (changeInfo.status === 'complete') { browser.tabs.executeScript(tabId, { file: 'content.js', runAt: 'document_start', type: 'module' }).catch(err => console.error('注入脚本失败:', err)); } });
- 保持
content.js和foo.js代码不变,注入后的脚本会以模块形式执行,import语法生效。
注意:该方案要求Firefox版本在89及以上,因为Manifest V2下的
executeScript支持type: 'module'是从该版本开始的。
内容的提问来源于stack exchange,提问作者Diehardwalnut
相关产品推荐
相关产品推荐

