const EslintWebpackPlugin = require('eslint-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 ImageMinimizerPlugin = require('image-minimizer-webpack-plugin')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
const CopyPlugin = require("copy-webpack-plugin");
const { VueLoaderPlugin } = require('vue-loader')
const {DefinePlugin} = require('webpack')
const path = require('path')
const isProduction = process.env.NODE_ENV === 'production'
function getStyleLoaders (pre) {
return [
isProduction?MiniCssExtractPlugin.loader:'vue-style-loader',
'css-loader',
{
// 处理css兼容性
// 配合package.json 中browserslit来指定兼容性
loader:'postcss-loader',
options:{
postcssOptions:{
plugins:['postcss-preset-env'],
}
}
},
pre && {
loader:pre,
options:pre === 'sass-loader'?{
// 自定义主题
additionalData: `@use "@/styles/element/index.scss" as *;`,
}:{}
}
].filter(Boolean)
}
module.exports = {
entry: './src/main.js',
output: {
path: isProduction ? path.resolve(__dirname,'../dist'):undefined,
filename:isProduction ? 'static/js/[name].[contenthash:10].chunk.js':'static/js/[name].js',
chunkFilename: isProduction ? 'static/js/[name].[contenthash:10].chunk.js' : 'static/js/[name].js',
assetModuleFilename: 'static/media/[hash:10][ext][query]',
clean:true
},
module: {
rules: [
//css
{
test: /\.css$/,
use:getStyleLoaders(),
},
{
test: /\.less$/,
use:getStyleLoaders('less-loader'),
},
{
test: /\.s[ac]ss$/,
use:getStyleLoaders('sass-loader'),
},
{
test: /\.styl$/,
use:getStyleLoaders('stylus-loader'),
},
//图片
{
test:/\.(jpe?g|png|svg|gif)/,
type:"asset",
parser:{
dataUrlCondition:{
maxSize:10 * 1024,
},
}
},
//其他资源
{
test:/\.(woff2?|ttf)/,
type:'asset/resource'
},
//js
{
test:/\.js$/,
include:path.resolve(__dirname,'../src'),
loader:'babel-loader',
options:{
cacheDirectory:true, //开启缓存
cacheCompression:false, //不压缩缓存文件
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options:{
// 开启缓存
cacheDirectory:path.resolve(__dirname,'../node_modules/.cache/vue-loader')
}
}
]
},
// 处理html
plugins:[
new EslintWebpackPlugin({
context:path.resolve(__dirname,'../src'), //指定处理文件范围
exclude:'node_modules', //排除
cache:true, //开启缓存
cacheLocation:path.resolve(__dirname,'../node_modules/.cache/.eslintcache'),
}),
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html')
}),
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: {
dot: true,
gitignore: true,
ignore: ["**/index.html*"],//忽略index.html文件
},}]
}),
new VueLoaderPlugin(),
// cross-env定义的环境变量是给打包工具使用的
// DefinePlugin 定义的环境变量给源代码使用的,从而解决vue3页面警告的问题
new DefinePlugin({
__VUE_OPTIONS_API__ :true,
__VUE_PROD_DEVTOOLS__:false
}),
// 按需加载element-plus的配置
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver({
// 自定义主题配置,引入sass
importStyle: "sass",
})],
}),
].filter(Boolean),
mode: isProduction ? 'production' : 'development',
devtool: isProduction ? 'source-map' : 'cheap-module-source-map',
optimization:{
splitChunks:{
chunks:'all',
cacheGroups:{
vue:{
test:/[\\/]node_modules[\\/]vue(.*)?[\\/]/,
name:'vue-chunk'
},
elementPlus:{
test:/[\\/]node_modules[\\/]element-plus/,
name:'element-chunk'
},
libs:{
test:/[\\/]node_modules/,
name:'libs-chunk'
}
}
},
runtimeChunk:{
name:entrypoint => `runtime~${entrypoint.name}.js`
},
minimize: isProduction,
minimizer: [
new CssMinimizerWebpackPlugin(),
new TerserWebpackPlugin(),
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
["gifsicle", { interlaced: true }],
["jpegtran", { progressive: true }],
["optipng", { optimizationLevel: 5 }],
[
"svgo",
{
plugins: [
"preset-default",
"prefixIds",
{
name: "sortAttrs",
params: {
xmlnsOrder: "alphabetical",
},
},
],
},
],
],
},
},
}),
]
},
// webpack解析模块加载选项
resolve:{
// 自动补全文件扩展名
extensions:['.vue','.js','.json'],
// 路径别名
alias:{
'@':path.resolve(__dirname,'../src')
}
},
devServer:{
host:'localhost',
port:3001,
open:true,
hot:true,
historyApiFallback:true, //解决前端路由刷新404问题
},
performance:false,
}
module.exports = {
root: true,
// 启用node环境变量
env: {
node: true,
},
// 继承 vue3 和 eslint 官方规则
extends: ["plugin:vue/vue3-essential", "eslint:recommended"],
// 解析选项
parserOptions: {
parser: "@babel/eslint-parser",
},
};
module.exports = {
// 继承vue官方规则
presets: ["@vue/cli-plugin-babel/preset"],
};
"browserslist": [
"last 2 version",
"> 1%",
"not dead"
],
"scripts": {
"start": "npm run dev",
"dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"
},
关于vue的webpack配置,如君还有优化空间或问题,请在评论区讨论或私聊我,共同努力共同进步。
万分感谢