You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Manifest V3 Chrome扩展脚本注入报错:无法加载文件求助

Manifest V3 Chrome扩展脚本注入问题排查与解决

问题描述

我正在开发Manifest V3版本的Chrome扩展,因禁止加载外部资源,已将html2canvas.min.js复制到本地libs文件夹中。需在内容脚本get-div-image.js中使用该库访问DOM,通过popup.js调用chrome.scripting.executeScript注入html2canvas.js和get-div-image.js时,触发以下错误:

Unchecked runtime.lastError: Could not load file: 'html2canvas.js'.
Unchecked runtime.lastError: Could not load file: 'get-div-image.js'.

修改文件路径为['libs/html2canvas.js']和['contents/get-div-image.js']后错误消失,但脚本似乎未注入成功,且该路径写法与content_scripts中的路径写法不一致,想知道问题出在哪里。

我的manifest.json配置:

{
    "manifest_version": 3,
    "name": "Images Grabber v2",
    "version": "1.0",
    "description": "Monitors the screen and takes screenshots.",
    "permissions": ["activeTab", "storage", "tabs", "background", "scripting"],
    "content_security_policy": {
        "extension_pages": "script-src 'self'; object-src 'self';"
    },
    "background": {
      "service_worker": "background.js"
    },
    "action": {
      "default_popup": "popup.html"
    },
    "host_permissions": ["<all_urls>"],
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["contents/get-data-urls.js", "libs/html2canvas.js", "contents/get-div-image.js"]
        }
    ],
    "icons": {
      "128": "icons/icon.png"
    }
  }

文件夹结构:

extension/
│
├── manifest.json
│
├── contents/
│   ├── get-data-urls.js
│   └── get-div-image.js
│
└── libs/
    └── html2canvas.js
...

问题原因与解决方法

1. 路径写法差异的本质

content_scripts中的路径本身就是相对于扩展根目录的完整路径,而chrome.scripting.executeScript的files参数要求必须传入这种完整相对路径——你修改后的写法才是正确的。之前的错误是因为只写了文件名(比如html2canvas.js),Chrome会默认在当前执行上下文的目录中查找,而非扩展根目录,所以找不到文件。

2. 脚本看似未注入的核心原因

(1) 重复注入的冲突

你的manifest.json已经在content_scripts里声明了get-div-image.js和html2canvas.js,它们会自动注入到所有匹配的页面中。此时再通过executeScript注入同名脚本,会导致重复执行,出现逻辑覆盖或无响应的情况,看起来像没注入成功。

解决方式:

  • 如果是需要按需触发脚本逻辑,建议移除content_scripts中的这两个脚本,只保留必要的常驻脚本;
  • 或者在get-div-image.js中添加触发判断,比如监听来自popup的消息,而非脚本加载后自动执行。

(2) 注入时机与上下文错误

确保popup.js中的注入代码逻辑正确,必须先获取当前活跃标签页的ID,且标签页处于可注入状态(排除chrome://等限制页面)。示例正确写法:

// popup.js 中的注入代码
document.getElementById('trigger-btn').addEventListener('click', async () => {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  try {
    await chrome.scripting.executeScript({
      target: { tabId: tab.id },
      files: ['libs/html2canvas.js', 'contents/get-div-image.js']
    });
    console.log('脚本注入成功');
  } catch (err) {
    console.error('注入失败:', err);
  }
});

(3) 第三方库的CSP兼容性问题

部分版本的html2canvas依赖eval执行代码,而网页自身的CSP或扩展的CSP可能限制了unsafe-eval,导致库无法正常运行,看起来像脚本未生效。

解决方式:

  • 尝试替换为不需要eval的html2canvas版本;
  • 若必须保留,可在扩展的CSP配置中添加'unsafe-eval'(仅必要时使用):
"content_security_policy": {
    "extension_pages": "script-src 'self' 'unsafe-eval'; object-src 'self';"
}

3. 最佳实践建议

  • 按需注入:不要同时在content_scripts和executeScript中注入相同脚本,避免逻辑冲突。常驻逻辑用content_scripts,按需触发的逻辑用executeScript注入单独的触发脚本;
  • 通信规范:如果get-div-image.js需要和popup交互,使用chrome.runtime.sendMessage和chrome.runtime.onMessage进行消息传递,不依赖注入时机耦合逻辑。

内容的提问来源于stack exchange,提问作者Edoardo Balducci

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:15:06