vue2项目从webpack3升级至webpack5线上环境报错,如何解决?

公司项目从webapck3升级到webpack5, 打包上线以后白屏,报这个错误,请问该如何解决,似乎只要引入如ECHART,axios之类的依赖,就会报出这个错误,不引入就是正常的,该如何对webpack进行配置,以下是报错截图和我的webpack配置,还请各位教教,框架地址https://github.com/1443290403/fronted_frame.git

img

img

// build.js
'use strict'
require('./check-versions')()
 
process.env.NODE_ENV = 'production'
 
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
 
const spinner = ora('building for production...')
spinner.start()
 
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
  if (err) throw err
  webpack(webpackConfig, (err, stats) => {
    spinner.stop()
    if (err) throw err
    process.stdout.write(stats.toString({
      colors: true,
      modules: false,
      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
      chunks: false,
      chunkModules: false
    }) + '\n\n')
 
    if (stats.hasErrors()) {
      console.log(chalk.red('  Build failed with errors.\n'))
      process.exit(1)
    }
 
    console.log(chalk.cyan('  Build complete.\n'))
    console.log(chalk.yellow(
      '  Tip: built files are meant to be served over an HTTP server.\n' +
      '  Opening index.html over file:// won\'t work.\n'
    ))
  })
})
// util.js
'use strict'
const path = require('path')
const config = require('../config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const packageConfig = require('../package.json')

exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function (options) {
  options = options || {}

  const cssLoader = {
    loader: 'css-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  const postcssLoader = {
    loader: 'postcss-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  // generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return [{loader: MiniCssExtractPlugin.loader}].concat(loaders)
    } else {
      return [{loader: 'vue-style-loader'}].concat(loaders)
    }
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
  const output = []
  const loaders = exports.cssLoaders(options)

  for (const extension in loaders) {
    const loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }

  return output
}

exports.createNotifierCallback = () => {
  const notifier = require('node-notifier')

  return (severity, errors) => {
    if (severity !== 'error') return

    const error = errors[0]
    const filename = error.file && error.file.split('!').pop()

    notifier.notify({
      title: packageConfig.name,
      message: severity + ': ' + error.name,
      subtitle: filename || '',
      icon: path.join(__dirname, 'logo.png')
    })
  }
}

// vue-loader.conf.js

'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
  ? config.build.productionSourceMap
  : config.dev.cssSourceMap

module.exports = {
  loaders: utils.cssLoaders({
    sourceMap: sourceMapEnabled,
    extract: isProduction
  }),
  cssSourceMap: sourceMapEnabled,
  cacheBusting: config.dev.cacheBusting,
  transformToRequire: {
    video: ['src', 'poster'],
    source: 'src',
    img: 'src',
    image: 'xlink:href'
  }
}
//webpack.base.conf.js

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

const createLintingRule = () => ({
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [resolve('src'), resolve('test')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: ["@babel/polyfill", "./src/main.ts"]
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  externals: {
    'vue': 'Vue',
    'vue-router': 'VueRouter',
    'vuex': 'Vuex',
    'axios': 'axios'
  },
  resolve: {
    extensions: ['.js', '.vue', '.json', '.ts'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    },
    fallback: {
      setImmediate: false,
      // prevent webpack from injecting mocks to Node native modules
      // that does not make sense for the client
      dgram: false,
      fs: false,
      net: false,
      tls: false,
      child_process: false,
      path: require.resolve("path-browserify")
    }
  },
  module: {
    rules: [
      //...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        use: {
          loader: 'vue-loader',
          options: vueLoaderConfig
        },
      },
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader'
        },
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.tsx?$/,
        use: {
          loader: 'ts-loader',
          options: {
            appendTsSuffixTo: [/\.vue$/],
            transpileOnly: true,
            happyPackMode: true
          }
        },
        exclude: /node_modules/,
      },
      {
        test: /\.svg$/,
        use: {
          loader: 'svg-sprite-loader',
          options: {
            symbolId: 'icon-[name]'
          }
        },
        include: [resolve('src/assets/icons')],
        
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024
          }
        },
        generator: {
          filename: utils.assetsPath('img/[name].[hash:7].[ext]')
        },
        exclude: [resolve('src/assets/icons')]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024
          }
        },
        generator: {
          filename: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf|TTF)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024
          }
        },
        generator: {
          filename: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.sass$/,
        use: ['style', 'css', 'sass']
      },
      // {
      //   test: /\.ts$/,
      //   exclude: /node_modules/,
      //   enforce: 'pre',
      //   use: {
      //     loader: 'tslint-loader'
      //   }
      // },

    ]
  },
  plugins: [
    new VueLoaderPlugin()
    // new ForkTsCheckerWebpackPlugin({
    //   async: false,
    //   vue: true
    // })
  ],
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).

  }
}
//webpack.prod.conf.js
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const { merge } = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')

const env = require('../config/prod.env')

const webpackConfig = merge(baseWebpackConfig, {
  mode: "production",
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
    clean: true
  },
  optimization: {
    minimize: true,
    minimizer: [
      new TerserWebpackPlugin({
        parallel: true,
        extractComments: false,
        terserOptions: {
          compress: {
            drop_console: true,
            drop_debugger: true,
            warnings: false,
            pure_funcs: ['console.log']
          },
          sourceMap: config.build.productionSourceMap,
          format: {
            comments: false
          }
        }
      }), // Webpack5自带了开箱即用的代码压缩插件,官方推荐
      new CssMinimizerWebpackPlugin(), // 压缩css代码
    ],
    runtimeChunk: { name: 'runtime' },
    concatenateModules: true,
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          type: "css/mini-extract",
          chunks: "all",
          enforce: true
        },
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          chunks: 'all',
          priority: -10
        },
        'async-vendors': {
          test: /[\\/]node_modules[\\/]/,
          minChunks: 2,
          chunks: 'async',
          name: 'async-vendors'
        },
        manifest: {
          name: 'manifest',
          minChunks: Infinity
        }
      }
    },
    moduleIds: 'deterministic'
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    // extract css into its own file
    new MiniCssExtractPlugin({
      ignoreOrder: true,
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      chunkFilename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'auto'
    }),
    // keep module.id stable when vendor modules does not change
    new webpack.ids.HashedModuleIdsPlugin(),
    // enable scope hoisting
    new webpack.optimize.ModuleConcatenationPlugin(),

    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ]),
    // new CopyWebpackPlugin({
    //   patterns: [
    //     {
    //       from: path.resolve(__dirname, '../static'),
    //       to: config.build.assetsSubDirectory,
    //       globOptions: {
    //         dot: true,
    //         gitignore: false,
    //         ignore: ['.*','/**']
    //       }
    //     }
    //   ]
    // }),
    new webpack.ProvidePlugin({
      $lodash: 'lodash'
    })
  ]
})

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      filename: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8,
      deleteOriginalAssets: true
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

// config/index.js
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.

const path = require('path')
module.exports = {
  lintOnSave:false,
  chainWebpack: config => {
    config
        .entry('index')
        .add('@babel/polyfill')
    config.module
        .rule('svg')
        .exclude.add(resolve('src/assets/icons'))
        .end()
    config.module
        .rule('icons')
        .test(/\.svg$/)
        .include.add(resolve('src/assets/icons'))
        .end()
        .use('svg-sprite-loader')
        .loader('svg-sprite-loader')
        .options({
          symbolId: 'icon-[name]'
        })
        .end()
        
  },
  dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},

    // Various Dev Server settings
    host: '0.0.0.0', // can be overwritten by process.env.HOST
    port: 9093, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: false,
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-

    // Use Eslint Loader?
    // If true, your code will be linted during bundling and
    // linting errors and warnings will be shown in the console.
    useEslint: true,
    // If true, eslint errors and warnings will also be shown in the error overlay
    // in the browser.
    showEslintErrorsInOverlay: false,

    /**
     * Source Maps
     */

    // https://webpack.js.org/configuration/devtool/#development
    devtool: 'eval-cheap-module-source-map',

    // If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
    cacheBusting: true,

    cssSourceMap: true
  },
  transpileDependencies: [
    // /[/\\]node_modules[/\\]element-ui[/\\]/,[@\\]
    /[/\\]node_modules[/\\]element-ui[/\\]src[/\\]utils[/\\]/,
    /[/\\]node_modules[/\\]vue-awesome[/\\]/
  ],
  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',

    /**
     * Source Maps
     */

    productionSourceMap: true,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: 'source-map',

    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],

    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

// pacgage.json

{
  "name": "front",
  "version": "1.0.0",
  "description": "",
  "author": "",
  "private": true,
  "scripts": {
    "dev": "npx webpack serve --config build/webpack.dev.conf.js --color --progress",
    "start": "npm run dev",
    "lint": "eslint --fix --ext .js,.vue src",
    "build": "node --max-old-space-size=8192 build/build.js"
  },
  "dependencies": {
    "@babel/polyfill": "^7.0.0",
    "@babel/runtime": "^7.15.3",
    "@babel/runtime-corejs2": "^7.15.3",
    "@ckeditor/ckeditor5-build-classic": "^20.0.0",
    "@ckeditor/ckeditor5-vue": "^1.0.3",
    "@fortawesome/fontawesome-free": "^5.15.3",
    "@fullcalendar/core": "^5.10.1",
    "@fullcalendar/daygrid": "^5.10.1",
    "@fullcalendar/interaction": "^5.10.1",
    "@fullcalendar/timegrid": "^5.10.1",
    "@fullcalendar/vue": "^5.10.1",
    "@packy-tang/vue-tinymce": "^1.1.0",
    "@riophae/vue-treeselect": "^0.4.0",
    "codemirror": "^5.62.2",
    "crypto-js": "^4.0.0",
    "echarts-liquidfill": "^3.1.0",
    "echarts-wordcloud": "^2.0.0",
    "el-table-draggable": "^1.4.12",
    "element-ui": "^2.15.5",
    "es6-promise": "^4.2.8",
    "file-saver": "^2.0.5",
    "fork-ts-checker-webpack-plugin": "^6.2.12",
    "html2canvas": "^1.3.2",
    "js-base64": "^2.5.1",
    "js-cookie": "^2.2.1",
    "js-md5": "^0.7.3",
    "jsplumb": "^2.15.5",
    "kindeditor": "^4.1.10",
    "moment": "^2.24.0",
    "nanoid": "^1.0.2",
    "nprogress": "^0.2.0",
    "qs": "^6.9.1",
    "shelljs": "^0.8.4",
    "snowflake-id": "^1.1.0",
    "sockjs-client": "^1.3.0",
    "spark-md5": "^3.0.2",
    "stompjs": "^2.3.3",
    "tinymce": "^5.5.1",
    "vue-amap": "^0.5.10",
    "vue-baidu-map": "^0.21.22",
    "vue-codemirror": "^4.0.6",
    "vue-gpickr": "^0.4.2",
    "vue-marquee-tips": "^1.0.8",
    "vue-print-nb": "^1.7.5",
    "vue-property-decorator": "^7.2.0",
    "vue-qr": "^3.2.2",
    "vue-seamless-scroll": "^1.1.23",
    "vuedraggable": "^2.24.3",
    "vuex-router-sync": "^5.0.0",
    "xlsx": "^0.17.2"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-proposal-decorators": "^7.0.0",
    "@babel/plugin-proposal-export-namespace-from": "^7.0.0",
    "@babel/plugin-proposal-function-sent": "^7.0.0",
    "@babel/plugin-proposal-json-strings": "^7.0.0",
    "@babel/plugin-proposal-numeric-separator": "^7.0.0",
    "@babel/plugin-proposal-throw-expressions": "^7.0.0",
    "@babel/plugin-syntax-dynamic-import": "^7.0.0",
    "@babel/plugin-syntax-import-meta": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.0.0",
    "@babel/preset-env": "^7.20.2",
    "autoprefixer": "^7.1.2",
    "babel-eslint": "^9.0.0",
    "babel-helper-vue-jsx-merge-props": "^2.0.3",
    "babel-loader": "^8.0.0",
    "babel-plugin-dynamic-import-node": "^2.3.3",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "chalk": "^2.0.1",
    "compression-webpack-plugin": "^1.1.12",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^7.0.2",
    "css-loader": "^0.28.0",
    "css-minimizer-webpack-plugin": "^5.0.0",
    "echarts": "^5.2.1",
    "eslint": "^4.15.0",
    "eslint-config-standard": "^10.2.1",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-node": "^5.2.0",
    "eslint-plugin-promise": "^3.4.0",
    "eslint-plugin-standard": "^3.0.1",
    "eslint-plugin-vue": "^4.0.0",
    "file-loader": "^1.1.4",
    "fork-ts-checker-webpack-plugin": "^6.2.12",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "html-webpack-plugin": "^5.5.0",
    "jquery": "^3.5.1",
    "js-base64": "^2.5.1",
    "js-cookie": "^2.2.1",
    "js-md5": "^0.7.3",
    "localforage": "^1.10.0",
    "mini-css-extract-plugin": "^2.7.5",
    "node-notifier": "^5.1.2",
    "node-sass": "^4.14.1",
    "optimize-css-assets-webpack-plugin": "^3.2.0",
    "ora": "^1.2.0",
    "path-browserify": "^1.0.1",
    "portfinder": "^1.0.13",
    "postcss-import": "^11.0.0",
    "postcss-loader": "^2.0.8",
    "postcss-url": "^7.2.1",
    "rimraf": "^2.6.0",
    "sass-loader": "^7.1.0",
    "script-loader": "^0.7.2",
    "semver": "^5.3.0",
    "svg-sprite-loader": "^5.0.0",
    "ts-loader": "^9.4.2",
    "tslint": "^5.11.0",
    "tslint-config-standard": "^8.0.1",
    "tslint-loader": "^3.5.4",
    "typescript": "^3.1.4",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "url-loader": "^0.5.8",
    "vue-class-component": "^7.2.6",
    "vue-loader": "^15.10.1",
    "vue-style-loader": "^3.0.1",
    "vue-template-compiler": "^2.5.2",
    "vuex": "^3.6.2",
    "webpack": "^5.77.0",
    "webpack-bundle-analyzer": "^2.13.1",
    "webpack-cli": "^4.9.0",
    "webpack-dev-server": "^3.11.3",
    "webpack-merge": "^5.8.0",
    "webpackbar": "^5.0.0-3"
  },
  "engines": {
    "node": ">= 10.13.0",
    "npm": ">= 6.0.0",
    "cnpm": "latest"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}


你可以看看这个大佬的记录是不是可以解决你的问题

img


你把依赖排除啦

报错截图:

webpack5-error

根据报错信息,是因为在webpack5中引入了新特性chunk loading using JSONP,导致了跨域问题。解决办法有两种:

  1. 在webpack配置中添加crossOriginLoading选项,将其设置为"anonymous",表示允许跨域加载资源:
module.exports = {
  // ...
  output: {
    // ...
    crossOriginLoading: 'anonymous'
  }
  // ...
}
  1. 在html文件中手动添加crossorigin属性,也是为了解决跨域问题:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webpack App</title>
    <script src="dist/main.js" crossorigin="anonymous"></script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

其中,crossorigin属性值为anonymous表示允许跨域加载资源。

参考文档: