Webpack3升级至Webpack5后exclude配置失效如何解决
webpack3升级webpack5后node_modules依赖解析报错修复
问题描述
将webpack从3版本升级到5版本后,执行npm run webpack命令时出现大量旧版本未出现的报错,所有报错都指向node_modules文件夹下的依赖包,报错示例如下:
ERROR in ./node_modules/@material-ui/core/esm/ButtonBase/TouchRipple.js 6:0-57 Module not found: Error: Can't resolve 'react-transition-group' in 'G:\GamerRepo\ClientPortal\node_modules\@material-ui\core\esm\ButtonBase' @ ./node_modules/@material-ui/core/esm/ButtonBase/ButtonBase.js 13:0-40 322:22-33
项目文件夹结构如下:
/GamerRepo /wwwroot /dist /ClientPortal /static /node_modules
原配置在webpack3版本中可正常运行,用户粘贴的配置存在结构错位,修正语法错误后的原始配置如下:
const webpack = require('webpack'); const path = require('path'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const nodeExternals = require('webpack-node-externals'); let config = { mode: 'development', resolve: { modules: [ path.resolve(__dirname, 'ClientPortal'), path.resolve(__dirname, 'ClientPortal/static'), path.resolve(__dirname, 'node_modules') ], alias: { moment$: 'moment/moment.js' } }, entry: { app: path.resolve(__dirname, 'ClientPortal/entryPoint.js'), }, output: { path: path.resolve(__dirname, 'wwwroot/dist'), publicPath: '/dist/', filename: '[name].js', chunkFilename: '[name].js' }, module: { rules: [ { test: /\.js$/, include: path.resolve(__dirname, "ClientPortal"), exclude: /(ClientPortal\/static|node_modules)/, use: { loader: 'babel-loader', options: { presets: ["@babel/preset-env", '@babel/preset-react'], } } }, { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.(ttf|eot)$/, type: 'asset/resource' }, ] }, plugins: [ new CleanWebpackPlugin([__dirname + '/wwwroot/dist'], { root: process.cwd(), verbose: false }), new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', Popper: ['popper.js', 'default'], }), new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), ] }; module.exports = config;
修复调整步骤
- 先修正配置语法错误:原始粘贴代码顶部存在错位的
module: {字段,需要删除,确保rules数组完全包裹在config对象的module字段下,否则webpack无法正常加载配置。 - 调整模块解析配置:webpack5重写了模块解析逻辑,默认规则和3版本差异较大,修改
resolve配置如下,兼容旧版解析逻辑同时修复依赖查找失败问题:
resolve: { modules: [ 'node_modules', path.resolve(__dirname, 'ClientPortal'), path.resolve(__dirname, 'ClientPortal/static'), path.resolve(__dirname, 'node_modules') ], alias: { moment$: 'moment/moment.js' }, symlinks: false, fullySpecified: false }
其中symlinks: false用于关闭软链接解析避免路径错位,fullySpecified: false用于关闭webpack5默认的文件后缀强校验,兼容旧版不带后缀的导入写法;将'node_modules'放在modules数组最前,让webpack优先按node标准模块查找规则递归解析依赖,避免依赖包查找上层依赖时出现路径错误。
- 替换过时的清理插件:webpack5不兼容旧版
clean-webpack-plugin,先执行npm uninstall clean-webpack-plugin卸载旧版本,再执行npm install clean-webpack-plugin -D安装最新版,同时修改引入和插件配置:
// 顶部引入修改为 const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // plugins数组内的清理插件替换为 new CleanWebpackPlugin({ verbose: false })
新版插件会自动读取output.path配置清理对应目录,不需要手动传入路径参数。
- 修正loader规则:当前配置同时设置了
include和exclude,webpack5下路径正则匹配优先级和3版本不同,多余的node_modules排除规则会干扰路径判断——因为已经配置include只匹配ClientPortal目录,本身就不会编译node_modules下的文件,修改js规则如下:
{ test: /\.js$/, include: path.resolve(__dirname, "ClientPortal"), exclude: /ClientPortal\/static/, use: { loader: 'babel-loader', options: { presets: ["@babel/preset-env", '@babel/preset-react'], } } }
- 安装缺失的peer依赖:webpack3不会强制校验依赖包的peerDependencies,webpack5会做严格校验,报错中提到的
react-transition-group是@material-ui/core的对等依赖,没有提前安装就会报找不到模块的错误,执行npm install react-transition-group -S安装即可。 - 删除无用引入:配置顶部引入的
webpack-node-externals没有被使用,直接删除const nodeExternals = require('webpack-node-externals');这行,避免版本不兼容导致的意外问题。
所有调整完成后重新执行npm run webpack即可正常构建。
内容的提问来源于stack exchange,提问作者SkyeBoniwell
相关产品推荐
相关产品推荐

