vue2项目从webpack3升级至webpack5

vue2项目从webpack3升级至webpack5

webpack3的打包速度已成为诟病,所以我们将原来的webpack3升级至webpack5

首先就是原来的项目结构,主要在于build目录下面,存在基础配置,开发配置,生产配置
build
|-------util.js
|-------webpack.base.js
|-------webpack.dev.conf.js
|-------webpack.prod.conf.js

首先当然是把旧的依赖从package中升级了,这里直接先
npm uninstall webpack webpack-dev-server webpack-cli
然后安装新版本的webpack webpack-dev-server webpack-cli
npm install webpack@5.51.1
npm install -D webpack-dev-server@4.0.0 webpack-cli@4.8.0

主要是webpack,其他的依赖可以通过一个插件来一次性升级
npm install -g npm-check-updates
然后直接输入
npm-check-updates
即可等待全部版本包更新完毕,当然会有一些坑之后填就好

接下来就是package.json的启动方式,由于webpack-dev-server升到了4版本用来配套webpack5,启动脚本需要改写一下
从webpack-dev-server 改成了 webpack serve 启动

对配置文件进行修改

接下来就是package.json的启动方式,由于webpack-dev-server升到了4版本用来配套webpack5,启动脚本需要改写一下
从webpack-dev-server 改成了 webpack serve 启动

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const { VueLoaderPlugin } = require('vue-loader')  // vue版本2.6.14

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

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    ...
  },
  output: {
    ...
  },
  resolve: {
    ...
  },
  module: {
    rules: [
      ...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      ...
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024,
          },
        },
        generator: {
          filename: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024,
          },
        },
        generator: {
          filename: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024,
          },
        },
        generator: {
          filename: utils.assetsPath('/fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    ...
  ],
  ...
}

// webpack.dev.conf.js

首先webpack-merge要结构出来,这个和之前有不同
const { merge } = require('webpack-merge')

改动点:
// new webpack.NamedModulesPlugin(), // webpack5改用配置方式 插件作用: 在热加载时直接返回更新文件名
新:
optimization: {
     moduleIds: 'named' // webpack5 采用此方式代替 NamedModulesPlugin
}

改动点:
// 旧copyWebpackPlugin插件使用方式
new CopyWebpackPlugin([
     {
       from: path.resolve(__dirname, '../static'),
       to: config.dev.assetsSubDirectory,
       ignore: ['.*']
     }
   ]),
新:
new CopyWebpackPlugin({
     patterns:[{
       from: path.resolve(__dirname, '../static'),
       to: config.dev.assetsSubDirectory,
       globOptions: {            // webpack5 ignore要写在globOptions这里
         ignore: ['.*']
       }
     }]
   }),

改动点:
webpack-dev-server   这个改动的比较多,因为v3升级到v4有很多属性的调整,见
```[https://github.com/webpack/webpack-dev-server/blob/master/migration-v4.md](https://github.com/webpack/webpack-dev-server/blob/master/migration-v4.md)
devServer: {
    // clientLogLevel: 'warning', // v4 移动到了client下面 改名logging 'warn'
    client: {
      logging: 'warn',
      overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
      progress: true,
    },
    static: false,
    devMiddleware: {
      publicPath: config.dev.assetsPublicPath
    },
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    // contentBase: false,   // v4移动到了static下面
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    // overlay: config.dev.errorOverlay
    //   ? { warnings: false, errors: true }   // v4 移动到了client下面
    //   : false,
    // publicPath: config.dev.assetsPublicPath, // v4 移动到了devMiddleware下面
    proxy: process.env.PROXY === 'true' ? config.dev.proxyTable : {},
    // quiet: true, // v4移除了该选项
    // watchOptions: {
    //   poll: config.dev.poll,   // v4移动到了static下面的watch
    // },
    // disableHostCheck: true // v4移除了该选项
    allowedHosts: "all"
  },
target: 'web'
// 生产环境
// 需要注意,一些旧的插件由于webpack新版已经不再支持,所以如果保留会报错,主要就是extract-text-webpack-plugin和optimize-css-assets-webpack-plugin。
分别用mini-css-extract-plugin和css-minimizer-webpack-plugin来代替
npm i  mini-css-extract-plugin
npm i css-minimizer-webpack-plugin
// const ExtractTextPlugin = require('extract-text-webpack-plugin') // 过期
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
// const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') // 压缩css过时,webpack5不用
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')  // webpack5使用
// 使用
plugins: [
   ...
    // new UglifyJsPlugin({   // 旧版写法
    //   uglifyOptions: {
    //     compress: {
    //       warnings: false
    //     }
    //   },
    //   sourceMap: config.build.productionSourceMap,
    //   parallel: true
    // }),

   new MiniCssExtractPlugin(),

   // new webpack.HashedModuleIdsPlugin(), // w5弃用  改用moduleIds: 'hashed',
   // new ExtractTextPlugin({   // 过期插件,弃用
    //   filename: utils.assetsPath('css/[name].[contenthash].css'),
    //   allChunks: true,
    // }),
    // new OptimizeCSSPlugin({   // 过时插件,弃用
    //   cssProcessorOptions: config.build.productionSourceMap
    //     ? { safe: true, map: { inline: false } }
    //     : { safe: true }
    // }),
   ...
],
optimization: {
    moduleIds: 'hashed',
    minimizer: [ 
      new CssMinimizerWebpackPlugin(), 
      new UglifyJsPlugin({         // 新版的丑化代码插件写在minimizer里
        uglifyOptions: {
          compress: {}
        },
        chunkFilter: (chunk) => chunk.name !== 'vendors',
        sourceMap: config.build.productionSourceMap,
        parallel: true,
      }),
    ],
}

代码拆分,之前采用new webpack.optimize.CommonsChunkPlugin拆分,现在webpack5能更智能拆分代码,通过配置optimization.splitChunks属性来实现功能,同时也可以拆分样式

//将此段代码写在optimization下
splitChunks: {
      chunks: 'all',
      minSize: 30000,
      minChunks: 1,
      automaticNameDelimiter: '~',
      cacheGroups: {
        vendors: {
          name: 'vendors',
          test({ resource }) {
            return /[\\/]node_modules[\\/]/.test(resource);
          },
          priority: 10,
        },
        styles: {
          name: "styles",
          test: /\.(le|c)ss$/,
          type: "css/mini-extract",
          chunks: "all",
          enforce: true,
        },
      },
    },

// 注意HtmlWebpackPlugin中的chunksSortMode现在只有’none’ | ‘auto’ | 'manual’三种配置,目前配置成auto即可

可能会遇到的问题

WARNING in ./node_modules/webpack-dev-server/client/index.js?protocol=ws%3A&hostname=0.0.0.0&port=8080&pathname=%2Fws&logging=warn 121:13-22
export ‘default’ (imported as ‘stripAnsi’) was not found in ‘./modules/strip-ansi/index.js’ (module has no exports)

这个问题是比较棘手的,因为是webpack内部的问题,首先第一种方法就是很简单的进行webpack-dev-server的卸载再重装

npm uninstall webpack-dev-serve
npm i webpack-dev-serve@4.0.0

第二种方法就是先进行检查
检查module.rules数组中,有没有某个元素中的include有这个句话

resolve('node_modules/webpack-dev-server/client')

把所有关于这句话的都注释掉
然后注意这一段

  resolve: {
    extensions: ['.js', '.vue', '.json', '.ts'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      pages: resolve('src/pages')
    }
  },

extensions中的内容很重要

其余的对于其中进行报错的包问题就该重装重装,该进行安装安装就完成啦

附上我的package.json文件

{
  "name": "xxx",
  "version": "1.0.0",
  "description": "A Vue.js project",
  "private": true,
  "scripts": {
    "dev": "webpack serve --mode development  --progress --config build/webpack.dev.conf.js --host 0.0.0.0",
    "start": "npm run dev",
    "build": "node build/build.js"
  },
  "dependencies": {
    "@vue/compiler-sfc": "^3.2.37",
    "@webpack-cli/serve": "^1.7.0",
    "ant-design-vue": "^1.7.8",
    "axios": "^0.24.0",
    "babel-plugin-import": "^1.13.3",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
    "bootstrap": "^5.1.3",
    "bootstrap-vue": "^2.21.2",
    "copy-webpack-plugin": "^11.0.0",
    "css-minimizer-webpack-plugin": "^4.0.0",
    "element-ui": "^2.15.6",
    "extract-text-webpack-plugin": "^3.0.2",
    "mini-css-extract-plugin": "^2.6.1",
    "nft.storage": "^5.1.3",
    "vue": "^2.6.14",
    "vue-router": "^3.0.1",
    "vue-video-player": "^5.0.2",
    "vuex": "^3.6.2",
    "webpack-bundle-analyzer": "^4.4.2",
    "webpack-dev-server": "^4.0.0",
    "webpack-merge": "^5.8.0"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.2",
    "babel-core": "^6.22.1",
    "babel-helper-vue-jsx-merge-props": "^2.0.3",
    "babel-loader": "^7.1.1",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "babel-preset-env": "^1.3.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "chalk": "^2.0.1",
    "compression-webpack-plugin": "^9.2.0",
    "css-loader": "^0.28.0",
    "file-loader": "^1.1.4",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "html-webpack-plugin": "^5.3.2",
    "node-notifier": "^5.1.2",
    "ora": "^1.2.0",
    "portfinder": "^1.0.13",
    "postcss-import": "^11.0.0",
    "postcss-loader": "^2.0.8",
    "postcss-url": "^7.2.1",
    "rimraf": "^2.6.0",
    "semver": "^5.3.0",
    "shelljs": "^0.7.6",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "url-loader": "^0.5.8",
    "vue-awesome-swiper": "^3.1.3",
    "vue-loader": "^15.9.8",
    "vue-style-loader": "^3.0.1",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.74.0",
    "webpack-bundle-analyzer": "^2.9.0",
    "webpack-cli": "^4.10.0",
    "webpack-merge": "^4.1.0"
  },
  "engines": {
    "node": ">= 6.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值