在现代前端工程史上,webpack作为一款流行的模块打包工具,占据了打包编译界的半壁江山。拥有丰富的插件生态和强大的编译能力。正是因为太“强大”,所以在升级的过程中会出现各种兼容性问题,想必体验过升级的人印象深刻!那么今天我们就来说说在升级到webpack5的过程中出现的各种问题以及相关的解决方法。原因是由于公司项目重构和打包优化的需要。同时,基于架构的统一和底层的完善,决定使用webpack5作为打包工具,加快项目的打包编译效率。注意,以下所有配图均为实际开发主题时遇到的错误信息,仅供参考。从上面的截图中提取了未定义错误的'locals'问题。错误消息UncaughtTypeError:Cannotreadproperty'locals'ofundefined是原因。题主粗略分析了一下这个错误的大概意思,猜测可能和loader的版本有关(毕竟这是升级过程中的经典问题之一),然后经过一番猛烈的操作通过题目,发现确实是loader造成的。普遍的问题是同时打包了style-loader和mini-css-extract-plugin这两项使用冲突。解决方案题主参考了相关解决方案后,采用了去除style-loader的方法,贴出示例代码供参考。constMiniCssExtractPlugin=require("mini-css-extract-plugin");constisDev=/*你的逻辑*/true;module.exports={plugins:[newMiniCssExtractPlugin()],module:{rules:[{test:/\.css$/i,use:[//只在开发中使用样式加载器isDev?“样式加载器”:MiniCssExtractPlugin.loader,“css-loader”,]],},}],},};Tips:很多webpackloader(比如:css-loader)在新版本发布后会有breakingchanges,所以遇到问题最好先查看loader的最新文档。以下是在解决问题过程中找到的相关解决方案,供参考。Uncaught-typeerror-cannot-read-property-locals-of-undefinedmini-css-extract-plugin/issuesprocessisnotdefinedReason这个问题基本上只在项目中用到process变量应该会遇到,所以会让人疑惑为什么明明我在webpack4可以用,但是在webpack5会被杀?带着这些疑问,我们去查一下官方文档,看看能不能找到一些注解。果然在MigrationGuide中,官爹对这个breakingchange做了详细的描述,这里贴出topic的主要内容。从圈出的内容可以看出,为了提高web的兼容性,webpack5不再自动导入Node模块相关的polyfill。如果我们需要使用它,我们需要手动导入相应的依赖包,这意味着流程变量是未定义的。原因。解决了那么我们还能不能把process当成全局变量呢?答案当然是肯定的,下面是题主结合其他方案采用的方案。手动将进程依赖项安装到项目中。将全局变量process指向进程的浏览器目录主文件。引入ProvidePlugin插件,指定流程点。//step1yarn添加进程//step2config.resolve.alias.set("process","process/browser");//step3config.plugin("processPolyfill").use(newwebpack.ProvidePlugin({process:"进程/浏览器",}));然后,主题实现完成后,在开发和运行时没有问题,但是在打包构建(稍微解绑)的时候出现了无法读取process.env.API等环境变量的问题。所以最后通过EnvironmentPlugin结合DotPlugin来读取*.env文件来弥补这个缺陷。如果有更好的解决方案,请告诉我。config.plugin("env").use(newwebpack.EnvironmentPlugin(envKeys));if(isProd){config.plugin("DotPlugin").use(require.resolve("dotenv-webpack"),[{路径:envFile,},]);}以下是在解题过程中找到的相关解决方案,供参考。这个错误比较明显,应该是插件排序导致的。直接通过mini-css-extract-plugin配置项ignoreOrder解决。config.optimization.minimizer("css").use(MiniCssExtractPlugin,[{filename:`css/[name].[contenthash:8].css`,chunkFilename:`css/[name].[contenthash:8].chunk.css`,ignoreOrder:true,},]);以下是在解决问题的过程中找到的相关解决方案,供参考。上面报错mini-css-extract-plugin/issueremove-order-warningscore-js中的define-property错误截图提取报错信息webpack5.0.0-beta.30Modulenotfound:Error:Can'tresolve'../../core-js/object/define-property'这个错误的原因乍一看有点迷惑,但是仔细观察可以发现错误来自于core-js,并且猜测可能与.(m)js文件的编译有关。解决方案经过题主的多方努力,找到了一个可行的解决方案,即设置fullySpecified为false,可以参考下面贴出的例子。config.module.rule("esmJs").test(/\.m?js/).resolve.set("fullySpecified",false);以下是题主解决过程中找到的相关解决方案供参考webpack/issuepath-to-regexpexporterror报错信息Attemptedimporterror:'path-to-regexp'doesnotcontainadefaultexport(importedas'pathToRegexp')是从上面的屏幕截图中提取的。查了一下原因,对比package.json版本中的依赖,node_modules依赖版本后,题主发现在重构迁移的过程中,按照老项目安装了两份path-to-regexp。具体依赖包位置如下:项目安装的react-router已安装path-to-regexp库已包含,依赖版本为^1.7.0。项目还单独安装了path-to-regexp依赖,其版本为^6.1.0,解决可能同时存在两个版本API差异的猜测。大师特意查看了不同版本的文档,发现不同版本的导出方式也发生了变化,所以这里我们使用删除单独安装的path-to-regexp的依赖(项目中用到这个库的不多,并且react-router已经包含了这个库,不再重复添加),然后按照低版本引入到项目中。//beforeimport{pathToRegexp}from"path-to-regexp";//afterimportpathToRegexpfrom"path-to-regexp";以下是问题解决过程中找到的相关解决方案供参考attempted-import-error-path-to-regexp-does-not-contain-a-default-export-impo.plugins3报错报错信息摘自以上截屏。plugins[3][1]mustbeanobject,false,orundefined这个问题一般是babel配置文件(.babelrc或babel.config.js)中plugin配置不当造成的,请参考plugins01-must-be-an-object-false-or-undefined来解决它。@pmmmwh/react-refresh-webpack-plugin报错$RefreshReg$题主在本次升级过程中引入了新的刷新库@pmmmwh/react-refresh-webpack-plugin。官方也推荐这个库来替代react-hot-loader的refresh库虽然还没有beta版本,但是大家可以先试试(个人觉得还是稳定的,可以试试)。魔改配置后,没有得到想要的刷新效果,反而得到如下错误信息。$RefreshReg$isnotdefinedwithChildCompilerusage原因是参考配置分析刷新后,题主基本确定这个错误与配置的处理位置有关。解决方案由于题主项目将react等库抽取到CDN,实现方式不同,所以不贴出参考代码。具体解决办法参考react-reisfresh-webpack-plugin/issue。@babel/plugin-transform-typescript不支持export=语法。从上面的截图来看,报错`export=`isnotsupportedby@babel/plugin-transform-typescriptPleaseconsiderusing`export
