webpack reack 老项目升级输出报错?

webpack1.0 直接升到 webpack5.0 各种依赖冲突,已经根据报错提示一个一个慢慢升级完了。在1.0的时候虽然很慢,但是能运行起来的,所以业务逻辑代码肯定是没问题么也动过。
现在升级完依赖,改完webpack配置 npm run start 项目启动报错如下:
image.png

根据chatGPT 和 文心一言的就解答就是“多个 chunk 尝试输出到相同的文件名” 造成的。如图:

image.png
image.png
在webpack配置文件中根据提示来回改,主要是改的 :entry,output,optimization 三个配置项,但这个错误始终存在,区别就是下面的输出信息有时候长,有时候短,但开头都是这个错误

[webpack-dev-middleware] Error: Conflict: Multiple chunks emit assets to the same filename antdStyle.css (chunks 86171 and 70775)

附:
wenpack 配置如下:

/**
 * 开发模式下的webpack配置
 * 在整个项目开发过程中,几乎99%的时间都是在这个模式下进行的
 * 注意。两种模式的配置有较大差异!!
 */

const path = require('path');
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

export default {
  devtool: 'eval-source-map',
  devServer: {//代理配置
      //其实很简单的,只要配置这个参数就可以了
      // proxy: {
      //     '/cosmo': {
      //         target: 'http://localhost:8887',
      //         secure: false
      //     }
      // }
    // headers:{
    //   'Access-Control-Allow-Origin': '*',
    // },
    quiet:false,
    noInfo: false,
  },
  // entry: [
  //   './src/webpack-public-path',  // 服务器静态资源路径配置,保证首先载入
  //   'react-hot-loader/patch',
  //   'webpack-hot-middleware/client?reload=true',
  //   path.resolve(__dirname, 'src/js/index.js')
  // ],
  entry: {
    main: [
      './src/webpack-public-path',
      'react-hot-loader/patch',
      'webpack-hot-middleware/client?reload=true',
      path.resolve(__dirname, 'src/js/index.js')
    ]
  },
  target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
  // output: {
  //   path: `${__dirname}/src`, // Note: Physical files are only output by the production build task `npm run build`.
  //   publicPath: '/',
  //   filename: 'bundle.js',
  //   chunkFilename: '[name].bundle.js', // 使用[name]占位符为每个chunk指定独一无二的文件名
  //   library: `hce-[name]`,
  //   libraryTarget: 'umd',
  //   globalObject:'window'
  // },
  // output: {
  //   path: `${__dirname}/dist`, // 通常输出目录是 dist 而不是 src
  //   publicPath: '/',
  //   filename: (info) => {
  //     return `${info.chunk.id}-${info.chunk.name || 'main'}-[contenthash].bundle.js`;
  //   },
  //   chunkFilename: (info) => {
  //     return `${info.chunk.id}-${info.chunk.name || 'chunk'}-[contenthash].bundle.js`;
  //   },
  //   library: `hce-[name]`,
  //   libraryTarget: 'umd',
  //   globalObject: 'window'
  //
  // },
  // output: {
  //   path: `${__dirname}/dist`,
  //   publicPath: '/',
  //   filename: 'bundle.js',
  //   chunkFilename: 'chunk-[id].js',
  //   library: `hce-[name]`,
  //   libraryTarget: 'umd',
  //   globalObject: 'window'
  // },
  output: {
    path: `${__dirname}/dist`,
    publicPath: '/',
    filename: '[name]-[id].bundle.js',
    chunkFilename: '[name]-[id].chunk.js',
    library: `hce-[name]`,
    libraryTarget: 'umd',
    globalObject: 'window'
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      name: 'common',
      minSize: 20000, // 20KB
      maxSize: 70000, // 70KB
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      automaticNameDelimiter: '~',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10, // 优先级,数字越小优先级越高
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('development'),
      __DEV__: true
    }),
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: 'src/index.html',
      chunks: "",
      title: 'MOM-开发模式',
      favicon: './src/favicon.ico',
      minify: {
        removeComments: true,
        collapseWhitespace: true
      },
      hash:true,
      // 这样每次客户端页面就会根据这个hash来判断页面是否有必要刷新
      // 在项目后续过程中,经常需要做些改动更新什么的,一但有改动,客户端页面就会自动更新!
      inject: 'body'
    }),
    new MiniCssExtractPlugin({
      filename: 'antdStyle.css', // 输出文件的名称
      chunkFilename: '[name].css', // 非入口(non-entry) chunk 文件的名称
    }),
  ],
  resolve: {
    modules: ['node_modules', path.join(__dirname, '../node_modules')],
    extensions: ['.web.js', '.js', '.json'],

    // 路径别名, 懒癌福音
    alias:{
      '@':path.resolve(__dirname,'src'),
            app:path.resolve(__dirname,'src/js'),
            // 以前你可能这样引用 import { Nav } from '../../components'
            // 现在你可以这样引用 import { Nav } from 'app/components'

            style:path.resolve(__dirname,'src/styles'),
            // 以前你可能这样引用 import "../../../styles/mixins.scss"
      // 现在你可以这样引用 import "style/mixins.scss"
      
            // 注意:别名只能在.js文件中使用。
    }
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.scss$/,
        include: path.resolve(__dirname, 'src/js'),
        use: [
          'MiniCssExtractPlugin.loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              sourceMap: true,
              importLoaders: 1,
              localIdentName: '[local]___[hash:base64:5]'
            }
          },
          'postcss-loader?parser=postcss-scss'
        ]
      },
      // 组件样式,需要私有化,单独配置

      {
        test: /\.scss$/,
        include: path.resolve(__dirname, 'src/styles'),
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader?parser=postcss-scss'
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
              lessOptions: {
                modifyVars: {
                  "@icon-url": "'/fonts/iconfont'"
                },
                javascriptEnabled: true
              }
            }
          }
        ]
      },
      {
        test: /\.css$/,
        include: path.resolve(__dirname, 'node_modules'),
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  require('precss'),
                  require('autoprefixer'),
                  require('rucksack-css')
                ]
              }
            }
          }
        ]
      },
      {
        test: /\.(otf|eot|svg|ttf|woff|woff2).*$/,
        use: 'url-loader?limit=10000'
      },
      {
        test: /\.(gif|jpe?g|png|ico)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192, // 小于这个大小的文件会被转为DataUrl
              name: 'images/[name].[hash].[ext]', // 输出文件的命名规则
            },
          },
        ],
      },
    ]
  },
};

package.json 如下:

{
  "name": "hce",
  "version": "1.0.0",
  "description": "react-base",
  "main": "index.js",
  "theme": {
    "@icon-url": "'/fonts/iconfont'"
  },
  "scripts": {
    "start": "npm-run-all --parallel open:src",
    "open:src": "babel-node server.js",
    "clean": "rimraf dist",
    "build:webpack": "node --max-old-space-size=102400 ./node_modules/webpack/bin/webpack.js --config webpack-pro-config.js --progress --colors",
    "build": "npm-run-all clean build:webpack"
  },
  "keywords": [
    "react",
    "es6",
    "webpack"
  ],
  "author": "minooo",
  "license": "MIT",
  "dependencies": {
    "@antv/g2": "^3.5.3",
    "antd": "^4.24.16",
    "axios": "^0.19.2",
    "babel-runtime": "^6.20.0",
    "copy-to-clipboard": "^3.1.0",
    "echarts": "^4.9.0",
    "echarts-for-react": "^3.0.2",
    "echarts-gl": "^1.1.2",
    "echarts-wordcloud": "^1.1.3",
    "ezuikit-js": "^0.7.0",
    "fixed-data-table-2": "^0.8.13",
    "handsontable": "^7.0.2",
    "history": "^3.0.0",
    "html2canvas": "^1.4.1",
    "jquery": "^3.4.0",
    "jspdf": "^1.5.3",
    "moment": "^2.24.0",
    "qrcodejs2": "0.0.2",
    "react": "^17.0.2",
    "react-cookie": "^1.0.4",
    "react-dimensions": "^1.3.0",
    "react-dom": "^17.0.2",
    "react-dragula": "^1.1.17",
    "react-free-scrollbar": "^0.3.4",
    "react-handsontable": "^0.3.2",
    "react-image-process": "^0.1.6",
    "react-modal": "^3.3.2",
    "react-piwik": "^1.6.0",
    "react-router": "^3.0.0",
    "react-slick": "^0.29.0",
    "react-to-print": "^2.14.1",
    "react-viewer": "^2.11.1",
    "reflux": "^6.4.1",
    "reqwest": "^2.0.5",
    "slick-carousel": "^1.8.1",
    "swiper": "^6.8.1",
    "wangeditor": "^3.1.1",
    "ztree": "^3.5.24"
  },
  "devDependencies": {
    "@babel/core": "^7.25.7",
    "@babel/node": "^7.25.7",
    "@babel/plugin-transform-runtime": "^7.25.7",
    "@babel/preset-env": "^7.25.7",
    "@babel/preset-react": "^7.25.7",
    "@babel/preset-stage-0": "^7.8.3",
    "autoprefixer": "^6.4.0",
    "babel-loader": "^9.2.1",
    "babel-plugin-import": "^1.1.1",
    "babel-preset-latest": "^6.16.0",
    "babel-preset-react": "^6.11.1",
    "babel-preset-stage-0": "^6.5.0",
    "browser-sync": "^2.14.0",
    "chokidar": "^1.6.1",
    "classnames": "^2.2.5",
    "connect-history-api-fallback": "^1.3.0",
    "cross-env": "^2.0.0",
    "css-loader": "^0.23.1",
    "express": "^4.14.0",
    "file-loader": "^5.1.0",
    "html-webpack-plugin": "^5.6.0",
    "http-proxy-middleware": "^0.17.4",
    "json-loader": "^0.5.4",
    "less": "^4.2.0",
    "less-loader": "^10.2.0",
    "mini-css-extract-plugin": "^2.9.1",
    "npm-run-all": "^2.3.0",
    "postcss-loader": "^4.3.0",
    "postcss-scss": "^0.1.9",
    "precss": "^1.4.0",
    "react-addons-css-transition-group": "^15.3.0",
    "react-addons-perf": "^15.4.2",
    "react-hot-loader": "^3.0.0-beta.6",
    "react-router-dom": "^5.3.0",
    "rimraf": "^2.5.3",
    "rucksack-css": "^0.8.6",
    "style-loader": "^0.13.2",
    "url-loader": "^3.0.0",
    "webpack": "^5.95.0",
    "webpack-dev-middleware": "^5.3.4",
    "webpack-hot-middleware": "^2.26.1"
  }
}
阅读 1k
2 个回答

错误分析

你的 Webpack 配置文件存在多个 chunk 输出到相同的 antdStyle.css 文件导致冲突。主要是 MiniCssExtractPlugin 的配置问题。

解决方案

1. 修改 MiniCssExtractPlugin 的配置
确保每个 CSS 文件有唯一的名称。修改插件配置文件名:

new MiniCssExtractPlugin({
  filename: '[name].[contenthash].css', // 确保唯一的文件名
  chunkFilename: '[name].[contenthash].css', // 确保唯一的文件名
})

2. 修改 output 配置
使用占位符确保文件名唯一:

output: {
  path: `${__dirname}/dist`,
  publicPath: '/',
  filename: '[name].[contenthash].js', // 唯一文件名
  chunkFilename: '[name].[contenthash].chunk.js', // 唯一文件名
  library: `hce-[name]`,
  libraryTarget: 'umd',
  globalObject: 'window',
},

3. 确认 CSS 加载器配置
检查所有 CSS 处理规则,确保使用 MiniCssExtractPlugin

{
  test: /\.css$/,
  use: [
    MiniCssExtractPlugin.loader,
    'css-loader',
    'postcss-loader'
  ],
},
{
  test: /\.scss$/,
  include: path.resolve(__dirname, 'src/js'),
  use: [
    MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        modules: true,
        sourceMap: true,
        importLoaders: 1,
        localIdentName: '[local]___[hash:base64:5]'
      }
    },
    'postcss-loader?parser=postcss-scss'
  ]
},
{
  test: /\.less$/,
  use: [
    MiniCssExtractPlugin.loader,
    'css-loader',
    'postcss-loader',
    {
      loader: 'less-loader',
      options: {
        sourceMap: true,
        lessOptions: {
          modifyVars: {
            "@icon-url": "'/fonts/iconfont'"
          },
          javascriptEnabled: true
        }
      }
    }
  ]
}

新的 Webpack 配置示例:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  devtool: 'eval-source-map',
  devServer: {
    quiet: false,
    noInfo: false,
  },
  entry: {
    main: [
      './src/webpack-public-path',
      'react-hot-loader/patch',
      'webpack-hot-middleware/client?reload=true',
      path.resolve(__dirname, 'src/js/index.js')
    ]
  },
  target: 'web',
  output: {
    path: `${__dirname}/dist`,
    publicPath: '/',
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].chunk.js',
    library: `hce-[name]`,
    libraryTarget: 'umd',
    globalObject: 'window',
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      name: 'common',
      minSize: 20000, // 20KB
      maxSize: 70000, // 70KB
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      automaticNameDelimiter: '~',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('development'),
      __DEV__: true
    }),
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: 'src/index.html',
      title: 'MOM-开发模式',
      favicon: './src/favicon.ico',
      minify: {
        removeComments: true,
        collapseWhitespace: true
      },
      hash: true,
      inject: 'body',
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[name].[contenthash].css',
    }),
  ],
  resolve: {
    modules: ['node_modules', path.join(__dirname, '../node_modules')],
    extensions: ['.web.js', '.js', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      app: path.resolve(__dirname, 'src/js'),
      style: path.resolve(__dirname, 'src/styles'),
    },
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.scss$/,
        include: path.resolve(__dirname, 'src/js'),
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: true,
              sourceMap: true,
              importLoaders: 1,
              localIdentName: '[local]___[hash:base64:5]',
            },
          },
          'postcss-loader?parser=postcss-scss',
        ],
      },
      {
        test: /\.scss$/,
        include: path.resolve(__dirname, 'src/styles'),
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader?parser=postcss-scss',
        ],
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
              lessOptions: {
                modifyVars: {
                  "@icon-url": "'/fonts/iconfont'",
                },
                javascriptEnabled: true,
              },
            },
          },
        ],
      },
      {
        test: /\.css$/,
        include: path.resolve(__dirname, 'node_modules'),
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  require('precss'),
                  require('autoprefixer'),
                  require('rucksack-css'),
                ],
              },
            },
          },
        ],
      },
      {
        test: /\.(otf|eot|svg|ttf|woff|woff2).*$/,
        use: 'url-loader?limit=10000',
      },
      {
        test: /\.(gif|jpe?g|png|ico)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: 'images/[name].[hash].[ext]',
            },
          },
        ],
      },
    ],
  },
};

做了这些更改后,运行 npm run start,看看是否解决了冲突问题。

错误已经给了提示,在antdStyle.css

new MiniCssExtractPlugin({
  filename: 'antdStyle.css', // 输出文件的名称
  chunkFilename: '[name].css', // 非入口(non-entry) chunk 文件的名称
}),

用了代码分割为多个chunk,再把多个chunk的css合并到一个css文件这个有可能会冲突覆盖,把filename删了试试

推荐问题
宣传栏