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

Chrome扩展:在Fetch加载的HTML中注入内容脚本问题求助

解决方案

问题1:配置Vite输出IIFE/非模块格式内容脚本

修改你的vite.config.js,通过Rollup配置指定输出格式为IIFE,并处理Svelte的动态导入打包:

import { defineConfig } from 'vite';
import { crx } from '@crxjs/vite-plugin';
import svelte from '@sveltejs/vite-plugin-svelte';
import manifest from './manifest.json';

export default defineConfig({
  plugins: [
    svelte(),
    crx({ manifest }),
  ],
  build: {
    rollupOptions: {
      // 指定content script的入口文件
      input: {
        content: './src/content-script.js',
      },
      output: {
        entryFileNames: '[name].js',
        format: 'iife', // 输出IIFE格式
        inlineDynamicImports: true, // 将动态导入打包进单个文件,避免依赖拆分
        // 若有全局依赖需映射,可在此配置globals
        globals: {
          svelte: 'Svelte'
        }
      }
    }
  }
});

配置完成后,执行vite build生成的content.js即为非模块格式,可直接通过chrome.scripting.registerContentScripts注册,无需指定type: 'module'。

问题2:SPA切换时注入/重新初始化脚本

若无法解决模块格式问题,或网站通过Service Worker实现无刷新路由,可采用以下两种方案:

方案A:监听历史状态变化注入脚本

在扩展的Service Worker中注册chrome.webNavigation.onHistoryStateUpdated事件,监听目标网站的路由变化,触发脚本注入:

// 扩展的service-worker.js
chrome.webNavigation.onHistoryStateUpdated.addListener(
  async (details) => {
    // 匹配目标设置页面的URL规则
    if (details.url.match(/^https:\/\/目标网站域名\/settings\//)) {
      try {
        await chrome.scripting.executeScript({
          target: { tabId: details.tabId },
          files: ['./content.js'],
          // 若仍为模块格式,添加 type: 'module'
          // type: 'module'
        });
      } catch (err) {
        console.error('注入内容脚本失败:', err);
      }
    }
  },
  {
    url: [{ hostEquals: '目标网站域名', pathContains: '/settings' }]
  }
);

需在manifest.json中添加对应权限:

{
  "permissions": ["webNavigation", "scripting"],
  "host_permissions": ["https://目标网站域名/*"]
}

方案B:监听DOM变化重新初始化组件

若内容脚本已注入,仅需在SPA切换后重新渲染按钮,可在内容脚本中使用MutationObserver监听DOM更新:

// content-script.js
function initCustomButtons() {
  // 避免重复创建按钮
  if (document.querySelector('.custom-preset-button')) return;

  // 创建并挂载自定义按钮
  const saveBtn = document.createElement('button');
  saveBtn.className = 'custom-preset-button';
  saveBtn.textContent = '保存预设';
  saveBtn.addEventListener('click', () => {
    // 保存预设逻辑
  });

  // 将按钮插入目标容器
  const targetContainer = document.querySelector('.settings-action-bar');
  targetContainer?.appendChild(saveBtn);
}

// 首次初始化
initCustomButtons();

// 监听DOM变化,当目标容器出现时重新初始化
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.addedNodes.length && document.querySelector('.settings-action-bar')) {
      initCustomButtons();
    }
  });
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

注意:无法直接介入网页自身的Service Worker,Chrome扩展的权限模型隔离了网页与扩展的Service Worker,因此不推荐尝试此路径。

内容的提问来源于stack exchange,提问作者Kat Lim Ruiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:12:50