vue2 webpack3 升级 webpack5 全过程,内附详细配置文件

由于 webpack5 需要 node 版本>= 10.13.0,请先将 node版本 升级, npm版本 用node自带的就可以了。

官方最新的node版本好像不兼容下面的webpack5配置,建议升级成 LTS版本 ,这里我升级的是v14.18.1的LTS版本,可以完美兼容。

配置代码我怕各种不兼容你们拿去不能用,索性全部贴出来,用到什么参考下我的版本,这些版本间的兼容性一言难尽,不要问我为什么不用最新的,不是最新的就是最好(它不兼容啊),但是不够新一定不行。

webpack5 相关的配置就 babel7 和 名字与webpack相关的依赖

主要和webpack3的配置区别就是几个依赖弃用和新的依赖支持

ExtractTextPlugin, OptimizeCSSPlugin, UglifyJsPlugin => MiniCssExtractPlugin, CssMinimizerPlugin ,TerserWebpackPlugin 

merge =>  { merge }
VueLoaderPlugin 的添加

.postcssrc.js => postcss.config.js 

这些后面配置文件里都会贴,找不同改下就好了

package.json

{
  "name": "",
  "version": "",
  "description": "",
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack server --inline --progress --config build/webpack.dev.conf.js",
    "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js",
    "start": "npm run dev",
    "check": "cross-env npm-check"
  },
  "dependencies": {
    "@babel/polyfill": "^7.0.0",
    "@babel/runtime": "^7.15.3",
    "@babel/runtime-corejs2": "^7.15.3",
    "axios": "^0.18.0",
    "diff": "^5.0.0",
    "echarts": "^5.2.1",
    "element-ui": "^2.15.6",
    "jquery": "^3.5.1",
    "js-cookie": "^2.2.1",
    "lodash": "^4.17.15",
    "npm-check": "^5.9.2",
    "qs": "^6.9.4",
    "sortablejs": "^1.13.0",
    "vue": "^2.6.10",
    "vue-i18n": "^8.18.2",
    "vue-meta": "^1.5.8",
    "vue-router": "^3.0.1",
    "vue-virtual-scroll-list": "^2.3.2",
    "vuex": "^3.0.1",
    "wangeditor": "^4.6.16"
  },
  "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-syntax-jsx": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "acorn": "^8.5.0",
    "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-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "chalk": "^2.0.1",
    "compression-webpack-plugin": "^9.0.0",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^7.0.2",
    "css-loader": "^5.2.7",
    "css-minimizer-webpack-plugin": "^3.1.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": "^6.2.0",
    "filemanager-webpack-plugin": "^2.0.5",
    "friendly-errors-webpack-plugin": "^1.7.0",
    "html-webpack-plugin": "^5.4.0",
    "increase-memory-limit": "^1.0.7",
    "mini-css-extract-plugin": "^2.4.3",
    "node-notifier": "^5.1.2",
    "ora": "^1.2.0",
    "portfinder": "^1.0.28",
    "postcss": "^8.2.15",
    "postcss-import": "^14.0.2",
    "postcss-loader": "^6.2.0",
    "postcss-url": "^10.1.3",
    "rimraf": "^2.6.0",
    "semver": "^5.3.0",
    "shelljs": "^0.7.6",
    "style-loader": "^3.3.1",
    "stylus": "^0.54.8",
    "stylus-loader": "^3.0.2",
    "svg-sprite-loader": "^5.2.1",
    "url-loader": "^4.1.1",
    "vue-loader": "^15.8.0",
    "vue-loader-plugin": "^1.3.0",
    "vue-style-loader": "^4.1.3",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.37.0",
    "webpack-bundle-analyzer": "^4.5.0",
    "webpack-cli": "^4.9.0",
    "webpack-dev-server": "^3.11.2",
    "webpack-merge": "^5.7.3",
    "webpackbar": "^5.0.0-3"
  },
  "engines": {
    "node": ">= 10.13.0",
    "npm": ">= 6.4.1"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

build

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'
    ))
  })
})

 packZip.js

const pack = require('../package.json')
const path = require('path')
const FileManagerPlugin = require('filemanager-webpack-plugin')
const multiConfig = require('../config/multi.conf')
const argvs = process.argv.slice(2)

function getParams (key) {
  let item = argvs.find(item => item.split('=')[0] === key)
  return item ? item.split('=') : []
}

let datetime = Date.now()
let plugins = []

let zipPros = getParams('zip')
if (zipPros.length) {
  plugins.push(new FileManagerPlugin({
    onEnd: {
      archive: [{
        source: path.resolve(__dirname, `${argvs[0]}`),
        destination: path.resolve(__dirname, zipPros[1] ? `${argvs[0]}.zip` : `${argvs[0]}.zip`)
      }]
    }
  }))
}

module.exports = plugins

utils.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'),
  }
}

// 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')
    })
  }
}

webpack.base.conf.js

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const webpack = require('webpack')
const { VueLoaderPlugin } = require('vue-loader');
const multiConfig = require('../config/multi.conf')

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: multiConfig.process.entry,
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@comm': resolve(`src/common`),
      '@url': resolve('src/proxyUrl'),
      '@static': resolve('src'),
      '@': multiConfig.process.alias,
      ...multiConfig.moduleAlias
    },
    fallback: {
      fs: false
    }
  },
  module: {
    rules: [
      // ...(config.dev.useEslint ? [createLintingRule()] : []), //eslint校验
      {
        test: /\.vue$/,
        use: ['vue-loader'],
      },
      {
        test: /\.js$/,
        use: ['babel-loader?cacheDirectory=true'], //babel-loader 开启缓存
        include: [resolve('src'), resolve('test')],
        exclude: resolve('node_modules'),
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ],
        exclude: [resolve('../node_modules')],
      },
      {
        test: /\.styl(us)?$/,
        use: [
          'style-loader',
          'css-loader',
          'stylus-loader',
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]'),
          esModule: false,
        }
      },
      {
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: [resolve('src/common/svgIcons')],
        options: {
          symbolId: 'icon-[name]'
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      },
    ]
  },
  node: {
    global: false
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    new webpack.IgnorePlugin({
      resourceRegExp: /^\.\/lib\/chart\/(.)*/,
      contextRegExp: /echarts$/,
    }), //打包忽略echarts
    new VueLoaderPlugin(),
  ]
}

webpack.dev.conf.js

'use strict'
const os = require('os')
const fs = require('fs')
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const pack = require('../package.json')
const { merge } = require('webpack-merge')
const chalk = require('chalk')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const multiConfig = require('../config/multi.conf')
const WebpackBar = require('webpackbar')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

function getIPAdress() {
  var interfaces = os.networkInterfaces()
  for (var devName in interfaces) {
    var iface = interfaces[devName]
    for (var i = 0; i < iface.length; i++) {
      var alias = iface[i]
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
        return alias.address
      }
    }
  }
}

function isExists(path) {
  try {
    fs.statSync(path)
    return true
  } catch (e) {
    return false
  }
}

function porxyStatic() {
  return {
    '/static': {
      target: `http://${config.dev.host}:${config.dev.port}`,
      bypass: function (req, res, proxyOptions) {
        if (req.path.indexOf(`/${config.dev.assetsSubDirectory}/`) === 0) {
          let publics = multiConfig.process.publics
          for (let len = publics.length - 1; len >= 0; len--) {
            let pubPath = req.path.replace(`/${config.dev.assetsSubDirectory}/`, `/${config.dev.assetsSubDirectory}/${publics[len]}/`)
            if (isExists(path.resolve(__dirname, `../${pubPath}`))) {
              return pubPath
            }
          }
          return req.path
        }
      }
    }
  }
}

const devWebpackConfig = merge(baseWebpackConfig, {
  mode: 'development',
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },

  devtool: config.dev.devtool,

  // these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: Object.assign(porxyStatic(), config.dev.proxyTable, multiConfig.process.proxyTable),
    quiet: true, // necessary for FriendlyErrorsPlugin
    // useLocalIp: true,//用本地ip
    watchOptions: {
      poll: config.dev.poll,
    }
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      favicon: path.resolve('./src/common/images/favicon.ico'),
      inject: true,
      chunkSortMode: 'auto'
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        globOptions: {
          dot: true,
          gitignore: true,
          ignore: ['.*'],
        }
      }
    ]),
    new WebpackBar()
  ]
})

module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port
  portfinder.getPort((err, port) => {
    if (err) {
      reject(err)
    } else {
      // publish the new Port, necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin
      let host = ['localhost', '127.0.0.1', '0.0.0.0'].includes(devWebpackConfig.devServer.host) ? 'localhost' : devWebpackConfig.devServer.host
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [chalk`{bold.rgb(255,255,0) [${pack.name} => ${multiConfig.process.name}]} App running at:\n - Local:   {bold.cyan http://${host}:${port}${config.dev.assetsPublicPath}}\n - Network: {bold.cyan http://${getIPAdress()}:${port}${config.dev.assetsPublicPath}}`]
        },
        onErrors: config.dev.notifyOnErrors
          ? utils.createNotifierCallback()
          : undefined
      }))

      resolve(devWebpackConfig)
    }
  })
})

webpack.prod.conf.js

'use strict'
const fs = require('fs')
const path = require('path')
const utils = require('./utils')
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 CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const multiConfig = require('../config/multi.conf')
const TerserWebpackPlugin = require('terser-webpack-plugin');

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

function isDirectory(path) {
  try {
    let stat = fs.statSync(path)
    return stat.isDirectory()
  } catch (e) {
    return false
  }
}

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
          },
          format: {
            comments: false
          }
        }
      }),
      new CssMinimizerPlugin(),
    ],
    runtimeChunk: { name: 'runtime' },
    concatenateModules: true,
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          chunks: 'all',
          priority: -10
        },
        'async-vendors': {
          test: /[\\/]node_modules[\\/]/,
          minChunks: 2,
          chunks: 'async',
          name: 'async-vendors'
        }
      },
    },
    moduleIds: 'deterministic'
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      chunkFilename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      favicon: path.resolve('./src/common/images/favicon.ico'),
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'auto'
    }),
    // copy custom static assets
    new CopyWebpackPlugin(multiConfig.process.publics.filter(name => isDirectory(path.resolve(__dirname, `../static/${name}`))).map(name => {
      return {
        from: path.resolve(__dirname, `../static/${name}`),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    })),
    // pack zip
    ...require('./packZip')
  ]
})

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

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

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

module.exports = webpackConfig

config

dev.env.js

'use strict'
const { merge } = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})

index.js

'use strict'

const path = require('path')
const multiConfig = require('./multi.conf')

module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: multiConfig.process.assetsSubDirectory,
    assetsPublicPath: multiConfig.process.assetsPublicPath,
    proxyTable: multiConfig.process.proxyTable,

    // Various Dev Server settings
    host: multiConfig.process.host, // can be overwritten by process.env.HOST
    port: multiConfig.process.port, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: true, //自动打开浏览器
    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
     */

    devtool: 'cheap-module-source-map',
    cacheBusting: true,
    cssSourceMap: true,
  },

  build: {
    // Template for index.html
    index: multiConfig.process.index,

    // Paths
    assetsRoot: multiConfig.process.assetsRoot,
    assetsSubDirectory: multiConfig.process.assetsSubDirectory,
    assetsPublicPath: multiConfig.process.assetsBuildPublicPath + '/',

    /**
     * Source Maps
     */

    productionSourceMap: true,
    devtool: 'source-map',
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

multi.conf.js

const path = require('path')
const pack = require('../package.json')
const argvs = process.argv.slice(2)
const urlConfig = require('../src/proxyUrl/proxyUrl')
function resolve (dir) {
  return path.join(__dirname, '..', dir)
}
function getParams (key) {
  let item = argvs.find(item => item.split('=')[0] === key)
  return item ? item.split('=') : []
}

function getModuleAlias () {
  let alias = {}
  importModules.forEach(({ name }) => {
    alias[`@${name}`] = resolve(`src/${name}`)
  })
  return alias
}

class MultiModule {
  constructor (name, opts) {
    let datetime = Date.now()
    Object.assign(this, {
      name,
      assetsSubDirectory: 'static',
      assetsPublicPath: '/',
      port: 8080,
      host: 'localhost',
      proxyTable: null,
      entry: {
        app: ['@babel/polyfill', `./src/${name}/main.js`]
      },
      alias: resolve(`src/${name}`),
      index: path.resolve(__dirname, `${argvs[0]}/template/index.html`),
      // favicon: path.resolve(__dirname, `E:/build/${name}/favicon.ico`),
      assetsRoot: path.resolve(__dirname, `${argvs[0]}/template`),
      pubdate: `${name}_v${pack.version}_${datetime}`,
      publics: [name].concat(opts.statics || []),
      deployConfig: null
    }, opts)
  }
}

function getModuleProcess (name) {
  let mItem = importModules.find(item => item.name === name)
  return mItem || importModules[0]
}

function proxyHandle (proxyReq, req, res, options) {
  let origin = `${options.target.protocol}//${options.target.hostname}`
  proxyReq.setHeader('origin', origin)
  proxyReq.setHeader('referer', origin)
}

function onProxyReq (proxyReq, req, res, options) {
  proxyHandle(proxyReq, req, res, options)
}

function onProxyReqWs (proxyReq, req, socket, options, head) {
  proxyHandle(proxyReq, req, socket, options)
}

function getProxyConfig (targetOpt, options) {
  let target = targetOpt.isLocal ? targetOpt.target.substring(0, targetOpt.target.length - 1) :  targetOpt.target + targetOpt.name
  return Object.assign({
    target,
    // secure: false,
    changeOrigin: true,
    secure: false,
    // ws: false,
    // cookieDomainRewrite: { '*': '' },
    // cookiePathRewrite: { '*': '/' },
    pathRewrite: {'^/API': target},
    // onProxyReq,
    // onProxyReqWs
  }, options)
}

const PROXY_DOMAIN_DEFAULT = urlConfig.url
const IS_LOCAL = urlConfig.isLocal
// 多模块独立配置
var importModules = [
  new MultiModule('*****', {
    port: 7007,
    statics: ['****'],
    assetsBuildPublicPath: getProxyConfig({target: PROXY_DOMAIN_DEFAULT, name: '****', isLocal: IS_LOCAL}).target,
    proxyTable: {
      '/API': getProxyConfig({target: PROXY_DOMAIN_DEFAULT, name: '', isLocal: IS_LOCAL})
    }
  }),
]
var lifecycleEvents = String(process.env.npm_lifecycle_event).split(':')
var moduleName = getParams('name')[1] || lifecycleEvents[1]
const multiConfig = {
  modules: importModules,
  moduleAlias: getModuleAlias(),
  process: getModuleProcess(moduleName)
}
module.exports = multiConfig

prod.env.js

'use strict'
module.exports = {
  NODE_ENV: '"production"'
}

proxyUrl

mode.js

let mode = {
  uat: 'uat',
  dev: 'dev',
  online: 'online',
}
module.exports = mode.dev

proxyUrl.js

const mode = require('./mode')
const urlList = {
  uat: '',
  dev: '',
  online: '',
}

module.exports = {
  url: urlList[mode],
  isLocal: !urlList[mode].includes('*****')
}

postcss.config.js

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "targets": {
          "browsers": [
            "> 1%",
            "last 2 versions",
            "not ie <= 8"
          ]
        }
      }
    ]
  ],
  "plugins": [
    "transform-vue-jsx",
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 2
      }
    ],
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-syntax-import-meta",
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-json-strings",
    "@babel/plugin-proposal-function-sent",
    "@babel/plugin-proposal-export-namespace-from",
    "@babel/plugin-proposal-numeric-separator",
    "@babel/plugin-proposal-throw-expressions",
    [
      "module-resolver",
      {
        "root": [
          "element-ui"
        ],
        "alias": {
          "element-ui/src": "element-ui/lib"
        }
      }
    ]
  ]
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值