Webpack 4 + Create React App环境下如何移除打包代码中的new Function以符合严格CSP要求
解决Webpack 4 + Create React App中CSP违反的new Function生成问题
我完全懂你的痛点——严格CSP下new Function确实是个棘手的坎,还不能用unsafe-eval绕过,必须从Webpack的生成逻辑根源入手解决。下面是几个经过验证的方案,按优先级排序:
1. 确保globalObject配置彻底生效
你已经设置了globalObject: 'window',但在Create React App(CRA)中,默认Webpack配置被封装,直接修改可能没完全覆盖。得通过自定义配置工具确保这个设置落地:
- 安装
react-app-rewired和customize-cra作为开发依赖 - 在项目根目录创建
config-overrides.js,添加以下代码:
const { override, adjustWebpackConfig } = require('customize-cra'); module.exports = override( adjustWebpackConfig((webpackConfig) => { // 强制全局对象为window,消除Webpack的全局对象 fallback 逻辑 webpackConfig.output.globalObject = 'window'; // 加强node环境模拟的禁用 webpackConfig.node = { ...webpackConfig.node, global: false, __dirname: false, __filename: false, }; return webpackConfig; }) );
- 修改
package.json中的启动/打包脚本,把react-scripts替换为react-app-rewired:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" }
这个配置直接告诉Webpack:我们的运行环境是浏览器,全局对象就是window,不需要再生成那段带new Function的兼容代码。
2. 直接替换Webpack运行时的不安全逻辑
如果上面的配置还没完全解决,可以通过自定义Webpack插件,直接替换生成的运行时代码里的问题片段:
在config-overrides.js中添加自定义插件:
const { override, addWebpackPlugin, adjustWebpackConfig } = require('customize-cra'); class ReplaceUnsafeRuntimePlugin { apply(compiler) { compiler.hooks.compilation.tap('ReplaceUnsafeRuntimePlugin', (compilation) => { compilation.hooks.runtimeModule.tap('ReplaceUnsafeRuntimePlugin', (module) => { // 定位包含new Function的runtime模块 if (module.source().includes("new Function(\"return this\")")) { // 替换为直接指向window的安全代码 const newSource = module.source().replace( /try { n = n || new Function\("return this"\)\(\); } catch \(e\) { "object" == typeof window && \(n = window\); }/, "n = window;" ); module._source = { source: () => newSource, size: () => newSource.length, }; } }); }); } } module.exports = override( addWebpackPlugin(new ReplaceUnsafeRuntimePlugin()), adjustWebpackConfig((webpackConfig) => { webpackConfig.output.globalObject = 'window'; webpackConfig.node.global = false; return webpackConfig; }) );
这个插件会在Webpack生成运行时代码时,把那段不安全的fallback逻辑直接替换成n = window;,彻底消除new Function的使用。
3. 排查第三方依赖的潜在问题
有时候第三方依赖也会生成new Function或eval代码(比如某些国际化库、动态样式库),可以这样排查:
- 打包后搜索生成的chunk文件,定位
new Function的来源 - 用
webpack-bundle-analyzer分析bundle,找到包含该代码的依赖包 - 替换为符合CSP规范的替代库,或者联系依赖作者修复问题
关于polyfill的思路
你提到的polyfill思路其实和上面的方案一致:这段代码原本是为了兼容不同环境的全局对象获取,我们直接给Webpack提供一个确定的、安全的全局对象实现(即window),这相当于用浏览器环境的“专属实现”替代了Webpack的通用fallback逻辑,完全符合你的需求。
内容的提问来源于stack exchange,提问作者dagda1
相关产品推荐
相关产品推荐

