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"
]
}