分享一些用webpack5打包vue2项目文件配置以及在配置过程中所遇到的坑
webpack配置文件
// webpack.config.js
// 项目生产环境和开发环境合并配置文件
const path = require('path')
const { DefinePlugin } = require('webpack')
const ESLintPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
// css样式压缩
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
// 提取css为单独文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
// 压缩html
const CopyPlugin = require("copy-webpack-plugin")
const TerserPlugin = require("terser-webpack-plugin")
// 判断是开发环境还是生产环境
const isProduction = process.env.NODE_ENV === 'production' //true
const getStyleLoader = (pre) => {
return [
isProduction? MiniCssExtractPlugin.loader : 'vue-style-loader',
'css-loader',
'postcss-loader',
pre
].filter(Boolean)
}
// [1, 2, undefined].filter(Boolean) 过滤掉undefined
module.exports = {
entry: './src/main.js',
output: {
path: isProduction? path.resolve(__dirname, '../dist') : undefined,
filename: isProduction? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].js',
// 打包异步代码
chunkFilename: isProduction? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].chunk.js',
// 图片资源
assetModuleFilename: 'static/media/[hash:5][ext][query]',
clean: true
},
module: {
rules: [
// 处理css、less
{
test: /\.css$/,
use: getStyleLoader()
},
{
test: /\.less$/,
use: getStyleLoader('less-loader')
},
// 处理图片
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
parser: {
dataUrlCondition: {
// 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中
maxSize: 10 * 1024,
}
},
generator: {
filename: 'static/media/[hash:5][ext][query]'
}
},
// 处理其他资源
{
test: /\.(ttf|woff2?)/,
type: "asset/resource"
},
// 处理js
{
test: /\.js$/,
include: path.resolve(__dirname, '../src'),
loader: 'babel-loader',
options: {
// 是否缓存(使第二次打包更快)
cacheDirectory: true,
// 是否压缩
cacheCompression: false
}
},
// 处理vue
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 处理eslint
new ESLintPlugin({
context: path.resolve(__dirname, '../src'), // 指定检查的目录
exclude: 'node_modules', // 指定排除检查的目录
}),
// 处理html
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html')
}),
// 处理vue
new VueLoaderPlugin(),
// cross-env定义的环境变量是给打包工具使用
// DefinePlugin定义的环境变量是给源代码使用, 从而解决v3页面警告问题
new DefinePlugin({
_VUE_OPTIONS_API_: true,
_VUE_PORD_DEVTOOL_: false
}),
// // 提取css为单独文件
isProduction && new MiniCssExtractPlugin({
filename: 'static/css/[name].[contenthash:10].css',
chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
}),
isProduction && new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, '../public'),
to: path.resolve(__dirname, '../dist'),
globOptions: {
// 忽略index.html文件
ignore: ["**/index.html"]
}
},
],
})
].filter(Boolean),
// 配置文件解析模块
resolve: {
// configuration options
extensions: ['.vue', '.js', '.json']
},
mode: isProduction? 'production' : 'development',
// 调试模式
devtool: isProduction? 'source-map' : 'cheap-module-source-map',
optimization: {
splitChunks: {
chunks: 'all'
},
// 判断是否需要压缩
minimize: isProduction,
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin()
]
},
devServer: {
host: 'localhost',
port: 9000,
open: true,
hot: true,
historyApiFallback: true
}
}
使用copy-webpack-plugin插件
在使用copy-webpack-plugin插件时,有个配置项globOptions
globOptions: {
// 忽略index.html文件
ignore: ["**/index.html"]
}
此时要注意,在copy时,要保证被copy的源文件目录下(本文是public目录)含有两个及以上文件,因为当index.html文件被忽略时,public就是空目录,会报unable to locate 'C:/Users/xxx/demo/vue-cli/public/**/*' glob错误,文件无法被锁定。
依赖包版本问题
在用webpack5打包vue2项目,依赖包版本的选择也是一个坑,下面是我试了许多次的结果
// vue版本
"dependencies": {
"vue": "^2.7.10",
"vue-router": "^3.6.5"
}
// vue-loader
// 打包vue2项目vue-loader最好使用17版本以下,v3可以使用17版本
"vue-loader": "^15.10.0",
"vue-style-loader": "^4.1.3"
// vue-template-compiler最好和vue版本同步
"vue-template-compiler": "^2.7.13"
favicon.icon图标引入问题
假如你在打包过程中,出现
ERROR in Template execution failed: ReferenceError: BASE_URL is not defined和Cannot find element: #app错误,不妨排查一下是不是某个文件引入错误。