React项目使用webpack-obfuscator报错:Cannot find module 'object-assign'
解决Webpack构建中"Cannot find module 'object-assign'"错误(结合webpack-obfuscator使用场景)
我在React项目中尝试用webpack-obfuscator混淆源码(不混淆依赖库),执行npm run dev时出现**webpack Cannot find module 'object-assign'**错误。项目配置文件如下:
package.json
{ "name": "xyz", "version": "1.0.0", "private": true, "homepage": "/apps/", "dependencies": { "@date-io/date-fns": "^1.3.13", "@date-io/moment": "^2.6.0", "@fortawesome/fontawesome-svg-core": "^1.2.28", "@fortawesome/free-solid-svg-icons": "^5.13.0", "@fortawesome/react-fontawesome": "^0.1.9", "@material-ui/core": "^4.8.2", "@material-ui/icons": "^4.5.1", "@material-ui/lab": "^4.0.0-alpha.39", "@material-ui/pickers": "^3.2.10", "apexcharts": "^3.28.1", "babel-preset-es2015": "^6.24.1", "crypto-browserify": "^3.12.0", "crypto-random-string": "^4.0.0", "cypress": "^9.1.1", "date-fns": "^2.14.0", "dayjs": "^1.8.28", "fetch-retry": "^3.1.0", "i18next": "^21.5.4", "i18next-browser-languagedetector": "^6.1.2", "i18next-http-backend": "^1.3.1", "isomorphic-fetch": "^3.0.0", "jwt-decode": "^3.1.2", "moment": "^2.26.0", "mui-datatables": "^2.15.0", "multimatch": "^6.0.0", "npm": "^7.16.0", "process": "^0.11.10", "prop-types": "^15.8.1", "react": "^16.14.0", "react-alert": "^7.0.3", "react-apexcharts": "^1.3.9", "react-async": "^10.0.0", "react-avatar": "^3.9.0", "react-custom-scrollbars": "^4.2.1", "react-dom": "^16.14.0", "react-filter-box": "^3.4.2", "react-grid-layout": "^0.17.1", "react-helmet": "^6.1.0", "react-i18next": "^11.14.3", "react-image-mapper": "0.0.15", "react-lineto": "^3.2.1", "react-native-svg": "^12.1.1", "react-number-format": "^4.4.1", "react-responsive-carousel": "^3.2.18", "react-router-dom": "^5.1.2", "react-scripts": "^4.0.3", "react-split-pane": "^0.1.89", "react-svg-pathline": "^0.5.0", "react-youtube": "^7.11.2", "recharts": "^1.8.5", "stream": "^0.0.2", "typescript": "^3.7.0-dev" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "dev": "webpack serve", "production": "webpack --mode production" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@babel/core": "^7.19.0", "@babel/preset-env": "^7.19.0", "@babel/preset-react": "^7.18.6", "babel-loader": "^8.2.5", "clean-webpack-plugin": "^4.0.0", "css-loader": "^6.7.1", "csv-loader": "^3.0.5", "file-loader": "^6.2.0", "html-loader": "^4.1.0", "html-webpack-plugin": "^5.5.0", "interpolate-html-plugin": "^4.0.0", "javascript-obfuscator": "^4.0.0", "mini-css-extract-plugin": "^2.6.1", "node-sass": "^7.0.1", "object-assign": "^4.1.1", "papaparse": "^5.3.2", "sass-loader": "^13.0.2", "webpack": "^5.74.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.10.1", "webpack-obfuscator": "^3.5.1", "xml-loader": "^1.2.1" } }
.babelrc
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
webpack.config.js
'use strict'; const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const InterpolateHtmlPlugin = require("interpolate-html-plugin"); const WebpackObfuscator = require('webpack-obfuscator'); const webpack = require('webpack'); //const multimatch = require('multimatch'); const publicUrl = process.env.PUBLIC_URL; module.exports = { mode: "development", entry: { app: "./src/index.js" }, devtool: 'source-map', //'eval', devServer: { static: { directory: path.join(__dirname, 'public'), staticOptions: { index: false } }, liveReload: false, compress: true, port: 80, open: true, hot: false, client: false, historyApiFallback: false }, output: { filename: '[name].js', path: path.resolve(__dirname, 'dist'), publicPath: "/" }, resolve: { extensions: [".wasm", ".mjs", ".js", ".jsx", ".ts", ".tsx", ".json"], // ['*', '.js', '.jsx'], alias: { '@': path.resolve(__dirname, 'src') // shortcut to reference src folder from anywhere }, fallback: { crypto: require.resolve('crypto-browserify'), assert: require.resolve('assert'), console: require.resolve('console-browserify'), constants: require.resolve('constants-browserify'), domain: require.resolve('domain-browser'), events: require.resolve('events'), http: require.resolve('stream-http'), https: require.resolve('https-browserify'), os: require.resolve('os-browserify/browser'), path: require.resolve('path-browserify'), punycode: require.resolve('punycode'), process: require.resolve('process/browser'), querystring: require.resolve('querystring-es3'), stream: require.resolve('stream-browserify'), string_decoder: require.resolve('string_decoder'), sys: require.resolve('util'), timers: require.resolve('timers-browserify'), tty: require.resolve('tty-browserify'), url: require.resolve('url'), vm: require.resolve('vm-browserify'), zlib: require.resolve('browserify-zlib'), isomorphic: require.resolve('isomorphic-fetch'), log: false, object_assign: require.resolve('object-assign'), scheduler: require.resolve('scheduler') } }, module: { rules: [ { // config for es6 jsx test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader" } }, { // config for sass compilation test: /\.scss$/, use: [ { loader: MiniCssExtractPlugin.loader }, 'css-loader', { loader: "sass-loader" } ] }, { test: /\.css$/, use: [ // [style-loader](/loaders/style-loader) { loader: 'style-loader' }, // [css-loader](/loaders/css-loader) { loader: 'css-loader', options: { modules: true } }, // [sass-loader](/loaders/sass-loader) { loader: 'sass-loader' } ] }, { // config for images test: /\.(png|svg|jpg|jpeg|gif)$/, type: 'asset/resource', exclude: /node_modules/, use: ['file-loader?name=[name].[ext]'] }, { // config for fonts test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ { loader: 'file-loader', options: { outputPath: 'fonts', } } ], }, { test: /\.html$/i, loader: "html-loader", }, { test: /\.js$/, exclude: [ //path.resolve(__dirname, 'content.js') path.resolve(__dirname, 'node_modules/react/index.js') ], enforce: 'post', //exclude: /node_modules/, use: { loader: WebpackObfuscator.loader, options: { rotateStringArray: true } } } ], noParse: [require.resolve('typescript/lib/typescript.js')] }, plugins: [ new WebpackObfuscator ({ rotateStringArray: true }), new webpack.ProvidePlugin({ process: 'process/browser', }), new HtmlWebpackPlugin({ // plugin for inserting scripts into html template: path.resolve(__dirname, "public/index.html"), inject: true, PUBLIC_URL: publicUrl }), new MiniCssExtractPlugin({ // plugin for controlling how compiled css will be outputted and named filename: "css/[name].css", chunkFilename: "css/[id].css" }), new InterpolateHtmlPlugin({ PUBLIC_URL: '' }) ] };
问题原因与修复方案
核心原因
- resolve.fallback配置错误:配置中写的
object_assign(下划线)与实际模块名object-assign(连字符)不匹配,Webpack无法正确解析模块。 - webpack-obfuscator重复配置:同时在
plugins和module.rules中配置了混淆插件,导致代码重复处理,触发对依赖库的不必要扫描。 - 混淆范围控制不当:仅排除了
react/index.js,未排除整个node_modules目录,混淆逻辑侵入依赖库,引发额外模块解析问题。
具体修复步骤
1. 修正resolve.fallback中的模块名称
修改webpack.config.js的resolve.fallback部分,将object_assign改为object-assign:
fallback: { // ...其他配置项 "object-assign": require.resolve('object-assign'), // ...其他配置项 }
2. 移除重复的WebpackObfuscator插件配置
删除plugins数组中的new WebpackObfuscator(...),仅保留module.rules里的后置loader配置,避免重复处理代码。
3. 精准控制混淆范围
确保仅混淆项目源码,排除所有依赖库:
{ test: /\.js$/, exclude: /node_modules/, // 排除所有node_modules下的文件 enforce: 'post', use: { loader: WebpackObfuscator.loader, options: { rotateStringArray: true } } }
或者更精准地只包含src目录:
{ test: /\.js$/, include: path.resolve(__dirname, 'src'), // 仅处理src目录下的js文件 enforce: 'post', use: { loader: WebpackObfuscator.loader, options: { rotateStringArray: true } } }
4. 可选:清理缓存并重装依赖
rm -rf node_modules package-lock.json npm install
修复后的webpack.config.js关键片段
resolve: { // ...其他配置 fallback: { // ...其他配置 "object-assign": require.resolve('object-assign'), // ...其他配置 } }, module: { rules: [ // ...其他rules { test: /\.js$/, exclude: /node_modules/, enforce: 'post', use: { loader: WebpackObfuscator.loader, options: { rotateStringArray: true } } } ] }, plugins: [ // 移除new WebpackObfuscator(...) new webpack.ProvidePlugin({ process: 'process/browser', }), // ...其他plugins ]
内容的提问来源于stack exchange,提问作者Matteo Simone
相关产品推荐
相关产品推荐

