Chrome扩展background.js导入模块触发Uncaught EvalError问题
解决Chrome扩展Manifest V3中Service Worker导入模块触发EvalError的问题
问题分析
你遇到的Uncaught EvalError是因为Webpack默认打包生成的代码中包含eval或类似动态代码执行逻辑,而Chrome扩展Manifest V3的默认内容安全策略(CSP)严格禁止unsafe-eval,即使将background声明为type: module也无法绕过这个限制。
相关配置与代码
manifest.json
{ "name":"Site Analyzer", "description":"Analyze the text content of the site.", "version":"0.1.0", "manifest_version":3, "action":{ "default_popup":"popup.html" }, "background": { "service_worker": "background.js", "type": "module" } }
webpack.config.js(原配置)
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); module.exports = { entry: { popup:"./src/popup.jsx", background: "./src/background.js" }, output: { path: path.resolve(__dirname, "dist"), filename: "[name].js", clean:true }, module:{ rules:[{ test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader" } }] }, plugins:[ new HtmlWebpackPlugin({ template:"./src/popup.html", filename: "popup.html" }), new CopyPlugin({ patterns:[{from:"public"}] }) ] }
package.json
{ "private": true, "scripts": { "build": "webpack --mode production" }, "dependencies": { "arquero": "^5.1.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@babel/core": "^7.20.5", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", "babel-loader": "^9.1.0", "copy-webpack-plugin": "^11.0.0", "html-webpack-plugin": "^5.5.0", "webpack": "^5.75.0", "webpack-cli": "^5.0.1", "webpack-merge": "^5.8.0" } }
background.js
import * as aq from "arquero"; const table1 = aq.table({a:["whatewer","there"],b:["beep","boop"]}); console.log(table1.objects());
已尝试的排查动作
- 构建后的
./dist/background.js在Node环境下执行正常 - 已知多数类似问题出现在
--mode development模式,但当前使用production模式仍复现 - 尝试过修改webpack的不同
devtool选项 - 设置
.env文件添加INLINE_RUNTIME_CHUNK=false - 每次修改后都重新构建、清除扩展错误并刷新扩展,问题依旧
已验证的解决步骤
修改Webpack配置,禁用动态代码生成
安装terser-webpack-plugin(如果未安装),然后更新webpack.config.js,针对background入口设置正确的目标环境,并优化打包逻辑避免生成eval相关代码:const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); const TerserPlugin = require('terser-webpack-plugin'); module.exports = { entry: { popup: "./src/popup.jsx", background: "./src/background.js" }, output: { path: path.resolve(__dirname, "dist"), filename: "[name].js", clean: true }, // 为不同入口设置对应目标环境 target: { popup: "web", background: "webworker" }, module: { rules: [{ test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader" } }] }, optimization: { runtimeChunk: false, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: true, // 禁用可能生成eval的压缩选项 evaluate: false }, format: { comments: false } } }) ] }, plugins: [ new HtmlWebpackPlugin({ template: "./src/popup.html", filename: "popup.html" }), new CopyPlugin({ patterns: [{ from: "public" }] }) ] };确认Manifest配置正确
保持manifest.json中的background配置不变,确保type: module已声明验证打包结果
执行npm run build后,检查dist/background.js文件,确认不存在eval(、new Function(这类动态代码执行语句。此时重新加载扩展,Service Worker即可正常运行
为什么之前的尝试无效?
- 仅修改
devtool无法彻底消除Webpack生成的eval代码,必须通过指定目标环境为webworker来调整打包逻辑 INLINE_RUNTIME_CHUNK=false主要针对Create React App的配置,不适用于自定义Webpack配置场景- Node环境下执行无问题是因为Node没有Chrome扩展的CSP限制
内容的提问来源于stack exchange,提问作者PeterN
相关产品推荐
相关产品推荐

