将前端工程升级到webpack5

525 阅读2分钟

node环境: >=16

包管理器: pnpm >=7.0.0

  1. 安装核心依赖

原版本:

"webpack": "^4.8.3",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.4",

新版本:

"webpack": "^5.72.1",
"webpack-cli": "^4.9.2",
"webpack-merge": "^4.1.0"

安装的时候显示node-sass编译报错,换成dart-sass,更新sass-loader到最新版。

"sass": "^1.51.0",
"sass-loader": "^12.6.0",

安装通过,但是报了一堆 Unmet peer dependencies 错误,稍后解决这些问题。

  1. 修改启动参数

运行工程:

Error: Unknown option '--inline'

看了一下官方迁移指南,webpack-dev-server插件的--inline这个参数在v4版本被废弃。

再次运行工程:

Invalid configuration object

报错显示配置对象的多个字段设置错误。

node字段,本来是让nodejs的api可以在其他的运行环境当中调用,比如浏览器。webpack5当中删除了这些配置。

optimization.namedModules,webpack4设置成true,webpack5用另一个属性来替换。

moduleIds: 'named'

devServer字段要改的比较多

watchOptions字段删除,contentBase字段被改成directory,因为使用了copy-webpack-plugin,暂时不知道怎么改。和staticOptions有关的配置都被挪到了static:

{
    static: {
      watch: true
    }
}

quiet字段本来是用来关闭日志的,现在被删除了,日志输出由webpack接管。配置为以下格式:

{
  infrastructureLogging: {
    level: 'none',
  }
}

为了显示报错,先把level的值改回info吧。

和webpack-dev-middleware有关的配置都被挪到了devMiddleware

{
  devMiddleware: {
    publicPath: config.dev.assetsPublicPath
  },
}

和clientLogLevel有关的配置都被挪到了client

{
  client: {
    logging: "warn",
    overlay: true
  }
}

hot热更新选项不用手动开启,删除HotModuleReplacementPlugin

optimization.noEmitOnErrors改成optimization.emitOnErrors: true

用感叹号来分割多个loader的语法被移除,只能用use

Exclamation mark separated loader lists has been removed in favor of the 'use' property with arrays

html-webpack-plugin版本太低,升级到5.5.0

 Cannot add property htmlWebpackPluginAlterChunks, object is not extensible

vue-loader版本太低,升级到17.0.0

 Error: Can't resolve 'vue-hot-reload-api'

在plugins字段添加new VueLoaderPlugin()

开始报错

Can't resolve 'vue-style-loader' 

pnpm使用的时候有一个坑,要给shamefully-hoist这个参数设置为true,不然它不会把依赖的依赖安装到node_modules根目录下。

shamefully-hoist=true // .npmrc

同时,因为项目太老,修复了很多v-for报错。

接下来,移除file-loader和url-loader,webpack5自带类似的功能:资源模块(asset module)

 {
  module: {
   rules: [
     {
       test: /.png/,
       type: 'asset/resource'
     }
   ]
 }
}

webpack-merge升级到5.8.0以后要修引入方式

const { merge } = require("webpack-merge");

copy-webpack-plugin更新之后传入的配置格式也变了

new CopyWebpackPlugin({
  patterns: [{
    from: path.resolve(__dirname, '../static'),
    to: config.build.assetsSubDirectory,
  }]
})

最后记录两个问题

  • 两个文件都引入了a,b,c模块但是引入顺序各不相同,会引起mini-css-extract-plugin报错。
  • 在多个文件当中引入同一个资源,有一个文件里面的引用路径没有区分大小写,会报模块重名的错误。