短发控 2024-01-30 11:35 采纳率: 33.3%
浏览 79
已结题

求解如何在谷歌插件v3 内容脚本中导入模块

如何在谷歌插件v3 内容脚本中导入模块

现有文件结构:
scripts

  • content
  • background
  • utils

其中content用来存放内容脚本,utils用来存放一些共有的功能,我想使用import功能使background和content能够调用utils中的方法
background可以通过type:module解决

但是content的限制更多,无法原生使用import

import {myfunction} from './xxx.js'
//会报错异常 提示无法引入额外的模块

尝试寻找方法通过对网页新建脚本元素可以使用import但是chrome.runtime等api就无法使用,请求指导解决方法。

console.log(chrome.runtime)
//被引入的脚本,会输出undefined
  • 写回答

19条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-01-30 11:36
    关注
    获得7.50元问题酬金

    引自免费微信小程序:皆我百晓生

    在谷歌插件v3中,内容脚本(content scripts)并不直接支持ES6模块导入。不过,你可以通过以下几种方式来实现模块化功能的调用:

    方法1:使用Chrome Extension Reloader (CER) 或 Manifest V2 的 crossorigin 属性

    如果你仍在使用 Manifest V2 并且可以接受一些限制,可以通过设置 "crossorigin": "use-credentials" 来启用CORS,然后在内容脚本中尝试使用动态脚本加载和import()函数。但请注意,这仅适用于部分场景,并不推荐,因为Manifest V3已不再支持此属性。

    方法2:使用workaround - 事件消息传递与注入脚本

    由于Chrome扩展内容脚本运行在页面上下文,它们不能直接访问chrome.runtime API或其他外部脚本。一种常见的做法是利用消息传递机制,在background script中加载并执行模块,然后通过消息传递将结果发送回内容脚本。

    步骤如下:

    1. background.js中允许消息通信,并加载并执行模块:
    // background.js
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
      if (request.action === 'runModuleFunction') {
        import('./scripts/utils.js').then((module) => {
          const result = module.myfunction(request.data);
          sendResponse({ result });
        });
        return true; // 表示异步响应
      }
    });
    
    1. content.js中发送请求至background script,并接收结果:
    // content.js
    chrome.runtime.sendMessage({ action: 'runModuleFunction', data: someData }, (response) => {
      if (chrome.runtime.lastError) {
        console.error('Error:', chrome.runtime.lastError.message);
      } else {
        console.log('Module function result:', response.result);
        // 使用从utils.js获取的结果
      }
    });
    
    1. utils.js 文件保持模块化结构:
    // scripts/utils.js
    export function myfunction(data) {
      // 实现你的公共功能
      return processedData;
    }
    

    方法3:构建工具整合(如Rollup或Webpack)

    使用构建工具将模块打包成一个单一的内容脚本文件,这样你可以在内容脚本中直接引用模块化的代码,而无需运行时动态加载。

    例如,配置Rollup或Webpack将所有模块合并到一个bundle中,然后在manifest.json中的content_scripts字段指定这个bundle作为内容脚本。

    完整实践这个方法可能需要对构建工具有一定了解,并且需要额外的开发环境配置,但它能提供更好的模块化体验,并确保内容脚本可以直接访问模块中的函数。

    由于篇幅原因,这里未给出具体构建配置,请参考对应构建工具的文档进行设置。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 2月7日
  • 创建了问题 1月30日